hackport-0.2.10: cabal-install-0.9.5_rc20101226/Distribution/Client/Unpack.hs
-----------------------------------------------------------------------------
-- |
-- Module : Distribution.Client.Unpack
-- Copyright : (c) Andrea Vezzosi 2008
-- License : BSD-like
--
-- Maintainer : cabal-devel@haskell.org
-- Stability : provisional
-- Portability : portable
--
--
-----------------------------------------------------------------------------
module Distribution.Client.Unpack (
-- * Commands
unpack,
) where
import Distribution.Package
( PackageId, Dependency(..) )
import Distribution.Simple.Setup(fromFlag, fromFlagOrDefault)
import Distribution.Simple.Utils
( notice, die )
import Distribution.Verbosity
( Verbosity )
import Distribution.Text(display)
import Distribution.Client.Setup(UnpackFlags(unpackVerbosity,
unpackDestDir))
import Distribution.Client.Types(UnresolvedDependency(..),
Repo, AvailablePackageSource(..),
AvailablePackage(AvailablePackage),
AvailablePackageDb(AvailablePackageDb))
import Distribution.Client.Dependency as Dependency
( resolveAvailablePackages
, dependencyConstraints, dependencyTargets
, PackagesPreference(..), PackagesPreferenceDefault(..)
, PackagePreference(..) )
import Distribution.Client.Fetch
( fetchPackage )
import Distribution.Client.HttpUtils
( downloadURI )
import qualified Distribution.Client.Tar as Tar (extractTarGzFile)
import Distribution.Client.IndexUtils as IndexUtils
(getAvailablePackages, disambiguateDependencies)
import System.Directory
( createDirectoryIfMissing, doesDirectoryExist, doesFileExist
, getTemporaryDirectory )
import System.IO
( openTempFile, hClose )
import Control.Monad
( unless, when )
import Data.Monoid
( mempty )
import System.FilePath
( (</>), addTrailingPathSeparator )
import qualified Data.Map as Map
unpack :: UnpackFlags -> [Repo] -> [Dependency] -> IO ()
unpack flags _ [] =
notice verbosity "No packages requested. Nothing to do."
where
verbosity = fromFlag (unpackVerbosity flags)
unpack flags repos deps = do
db@(AvailablePackageDb available _)
<- getAvailablePackages verbosity repos
deps' <- IndexUtils.disambiguateDependencies available
. map toUnresolved $ deps
pkgs <- resolvePackages db deps'
unless (null prefix) $
createDirectoryIfMissing True prefix
flip mapM_ pkgs $ \pkg -> case pkg of
AvailablePackage pkgid _ (LocalTarballPackage tarballPath) ->
unpackPackage verbosity prefix pkgid tarballPath
AvailablePackage pkgid _ (RemoteTarballPackage tarballURL) -> do
tmp <- getTemporaryDirectory
(tarballPath, hnd) <- openTempFile tmp (display pkgid)
hClose hnd
--TODO: perhaps we've already had to download this to a local cache
-- so we even know what package version it is. So might be able
-- to get it from the local cache rather than from remote.
downloadURI verbosity tarballURL tarballPath
unpackPackage verbosity prefix pkgid tarballPath
AvailablePackage pkgid _ (RepoTarballPackage repo) -> do
tarballPath <- fetchPackage verbosity repo pkgid
unpackPackage verbosity prefix pkgid tarballPath
AvailablePackage _ _ (LocalUnpackedPackage _) ->
error "Distribution.Client.Unpack.unpack: the impossible happened."
where
verbosity = fromFlag (unpackVerbosity flags)
prefix = fromFlagOrDefault "" (unpackDestDir flags)
toUnresolved d = UnresolvedDependency d []
unpackPackage :: Verbosity -> FilePath -> PackageId -> FilePath -> IO ()
unpackPackage verbosity prefix pkgid pkgPath = do
let pkgdirname = display pkgid
pkgdir = prefix </> pkgdirname
pkgdir' = addTrailingPathSeparator pkgdir
existsDir <- doesDirectoryExist pkgdir
when existsDir $ die $
"The directory \"" ++ pkgdir' ++ "\" already exists, not unpacking."
existsFile <- doesFileExist pkgdir
when existsFile $ die $
"A file \"" ++ pkgdir ++ "\" is in the way, not unpacking."
notice verbosity $ "Unpacking to " ++ pkgdir'
Tar.extractTarGzFile prefix pkgdirname pkgPath
resolvePackages :: AvailablePackageDb
-> [UnresolvedDependency]
-> IO [AvailablePackage]
resolvePackages
(AvailablePackageDb available availablePrefs) deps =
either (die . unlines . map show) return $
resolveAvailablePackages
installed available
preferences constraints
targets
where
installed = mempty
targets = dependencyTargets deps
constraints = dependencyConstraints deps
preferences = PackagesPreference
PreferLatestForSelected
[ PackageVersionPreference name ver
| (name, ver) <- Map.toList availablePrefs ]