never executed always true always false
    1 {-# LANGUAGE RecordWildCards #-}
    2 
    3 -- |
    4 --
    5 -- The layout of the .\/dist\/ directory where cabal keeps all of its state
    6 -- and build artifacts.
    7 --
    8 module Distribution.Client.DistDirLayout (
    9     -- * 'DistDirLayout'
   10     DistDirLayout(..),
   11     DistDirParams(..),
   12     defaultDistDirLayout,
   13     ProjectRoot(..),
   14 
   15     -- * 'StoreDirLayout'
   16     StoreDirLayout(..),
   17     defaultStoreDirLayout,
   18 
   19     -- * 'CabalDirLayout'
   20     CabalDirLayout(..),
   21     mkCabalDirLayout,
   22     defaultCabalDirLayout
   23 ) where
   24 
   25 import Distribution.Client.Compat.Prelude
   26 import Prelude ()
   27 
   28 import System.FilePath
   29 
   30 import Distribution.Package
   31          ( PackageId, ComponentId, UnitId )
   32 import Distribution.Compiler
   33 import Distribution.Simple.Compiler
   34          ( PackageDB(..), PackageDBStack, OptimisationLevel(..) )
   35 import Distribution.Types.ComponentName
   36 import Distribution.Types.LibraryName
   37 import Distribution.System
   38 
   39 
   40 -- | Information which can be used to construct the path to
   41 -- the build directory of a build.  This is LESS fine-grained
   42 -- than what goes into the hashed 'InstalledPackageId',
   43 -- and for good reason: we don't want this path to change if
   44 -- the user, say, adds a dependency to their project.
   45 data DistDirParams = DistDirParams {
   46     distParamUnitId         :: UnitId,
   47     distParamPackageId      :: PackageId,
   48     distParamComponentId    :: ComponentId,
   49     distParamComponentName  :: Maybe ComponentName,
   50     distParamCompilerId     :: CompilerId,
   51     distParamPlatform       :: Platform,
   52     distParamOptimization   :: OptimisationLevel
   53     -- TODO (see #3343):
   54     --  Flag assignments
   55     --  Optimization
   56     }
   57 
   58 
   59 -- | The layout of the project state directory. Traditionally this has been
   60 -- called the @dist@ directory.
   61 --
   62 data DistDirLayout = DistDirLayout {
   63 
   64        -- | The root directory of the project. Many other files are relative to
   65        -- this location. In particular, the @cabal.project@ lives here.
   66        --
   67        distProjectRootDirectory     :: FilePath,
   68 
   69        -- | The @cabal.project@ file and related like @cabal.project.freeze@.
   70        -- The parameter is for the extension, like \"freeze\", or \"\" for the
   71        -- main file.
   72        --
   73        distProjectFile              :: String -> FilePath,
   74 
   75        -- | The \"dist\" directory, which is the root of where cabal keeps all
   76        -- its state including the build artifacts from each package we build.
   77        --
   78        distDirectory                :: FilePath,
   79 
   80        -- | The directory under dist where we keep the build artifacts for a
   81        -- package we're building from a local directory.
   82        --
   83        -- This uses a 'UnitId' not just a 'PackageName' because technically
   84        -- we can have multiple instances of the same package in a solution
   85        -- (e.g. setup deps).
   86        --
   87        distBuildDirectory           :: DistDirParams -> FilePath,
   88        distBuildRootDirectory       :: FilePath,
   89 
   90        -- | The directory under dist where we download tarballs and source
   91        -- control repos to.
   92        --
   93        distDownloadSrcDirectory     :: FilePath,
   94 
   95        -- | The directory under dist where we put the unpacked sources of
   96        -- packages, in those cases where it makes sense to keep the build
   97        -- artifacts to reduce rebuild times.
   98        --
   99        distUnpackedSrcDirectory     :: PackageId -> FilePath,
  100        distUnpackedSrcRootDirectory :: FilePath,
  101 
  102        -- | The location for project-wide cache files (e.g. state used in
  103        -- incremental rebuilds).
  104        --
  105        distProjectCacheFile         :: String -> FilePath,
  106        distProjectCacheDirectory    :: FilePath,
  107 
  108        -- | The location for package-specific cache files (e.g. state used in
  109        -- incremental rebuilds).
  110        --
  111        distPackageCacheFile         :: DistDirParams -> String -> FilePath,
  112        distPackageCacheDirectory    :: DistDirParams -> FilePath,
  113 
  114        -- | The location that sdists are placed by default.
  115        distSdistFile                :: PackageId -> FilePath,
  116        distSdistDirectory           :: FilePath,
  117 
  118        distTempDirectory            :: FilePath,
  119        distBinDirectory             :: FilePath,
  120 
  121        distPackageDB                :: CompilerId -> PackageDB
  122      }
  123 
  124 
  125 -- | The layout of a cabal nix-style store.
  126 --
  127 data StoreDirLayout = StoreDirLayout {
  128        storeDirectory         :: CompilerId -> FilePath,
  129        storePackageDirectory  :: CompilerId -> UnitId -> FilePath,
  130        storePackageDBPath     :: CompilerId -> FilePath,
  131        storePackageDB         :: CompilerId -> PackageDB,
  132        storePackageDBStack    :: CompilerId -> PackageDBStack,
  133        storeIncomingDirectory :: CompilerId -> FilePath,
  134        storeIncomingLock      :: CompilerId -> UnitId -> FilePath
  135      }
  136 
  137 
  138 --TODO: move to another module, e.g. CabalDirLayout?
  139 -- or perhaps rename this module to DirLayouts.
  140 
  141 -- | The layout of the user-wide cabal directory, that is the @~/.cabal@ dir
  142 -- on unix, and equivalents on other systems.
  143 --
  144 -- At the moment this is just a partial specification, but the idea is
  145 -- eventually to cover it all.
  146 --
  147 data CabalDirLayout = CabalDirLayout {
  148        cabalStoreDirLayout        :: StoreDirLayout,
  149 
  150        cabalLogsDirectory         :: FilePath,
  151        cabalWorldFile             :: FilePath
  152      }
  153 
  154 
  155 -- | Information about the root directory of the project.
  156 --
  157 -- It can either be an implicit project root in the current dir if no
  158 -- @cabal.project@ file is found, or an explicit root if the file is found.
  159 --
  160 data ProjectRoot =
  161        -- | -- ^ An implicit project root. It contains the absolute project
  162        -- root dir.
  163        ProjectRootImplicit FilePath
  164 
  165        -- | -- ^ An explicit project root. It contains the absolute project
  166        -- root dir and the relative @cabal.project@ file (or explicit override)
  167      | ProjectRootExplicit FilePath FilePath
  168   deriving (Eq, Show)
  169 
  170 -- | Make the default 'DistDirLayout' based on the project root dir and
  171 -- optional overrides for the location of the @dist@ directory and the
  172 -- @cabal.project@ file.
  173 --
  174 defaultDistDirLayout :: ProjectRoot    -- ^ the project root
  175                      -> Maybe FilePath -- ^ the @dist@ directory or default
  176                                        -- (absolute or relative to the root)
  177                      -> DistDirLayout
  178 defaultDistDirLayout projectRoot mdistDirectory =
  179     DistDirLayout {..}
  180   where
  181     (projectRootDir, projectFile) = case projectRoot of
  182       ProjectRootImplicit dir      -> (dir, dir </> "cabal.project")
  183       ProjectRootExplicit dir file -> (dir, dir </> file)
  184 
  185     distProjectRootDirectory = projectRootDir
  186     distProjectFile ext      = projectFile <.> ext
  187 
  188     distDirectory = distProjectRootDirectory
  189                 </> fromMaybe "dist-newstyle" mdistDirectory
  190     --TODO: switch to just dist at some point, or some other new name
  191 
  192     distBuildRootDirectory   = distDirectory </> "build"
  193     distBuildDirectory params =
  194         distBuildRootDirectory </>
  195         prettyShow (distParamPlatform params) </>
  196         prettyShow (distParamCompilerId params) </>
  197         prettyShow (distParamPackageId params) </>
  198         (case distParamComponentName params of
  199             Nothing                  -> ""
  200             Just (CLibName LMainLibName) -> ""
  201             Just (CLibName (LSubLibName name)) -> "l" </> prettyShow name
  202             Just (CFLibName name)    -> "f" </> prettyShow name
  203             Just (CExeName name)     -> "x" </> prettyShow name
  204             Just (CTestName name)    -> "t" </> prettyShow name
  205             Just (CBenchName name)   -> "b" </> prettyShow name) </>
  206         (case distParamOptimization params of
  207             NoOptimisation -> "noopt"
  208             NormalOptimisation -> ""
  209             MaximumOptimisation -> "opt") </>
  210         (let uid_str = prettyShow (distParamUnitId params)
  211          in if uid_str == prettyShow (distParamComponentId params)
  212                 then ""
  213                 else uid_str)
  214 
  215     distUnpackedSrcRootDirectory   = distDirectory </> "src"
  216     distUnpackedSrcDirectory pkgid = distUnpackedSrcRootDirectory
  217                                       </> prettyShow pkgid
  218     -- we shouldn't get name clashes so this should be fine:
  219     distDownloadSrcDirectory       = distUnpackedSrcRootDirectory
  220 
  221     distProjectCacheDirectory = distDirectory </> "cache"
  222     distProjectCacheFile name = distProjectCacheDirectory </> name
  223 
  224     distPackageCacheDirectory params = distBuildDirectory params </> "cache"
  225     distPackageCacheFile params name = distPackageCacheDirectory params </> name
  226 
  227     distSdistFile pid = distSdistDirectory </> prettyShow pid <.> "tar.gz"
  228 
  229     distSdistDirectory = distDirectory </> "sdist"
  230 
  231     distTempDirectory = distDirectory </> "tmp"
  232 
  233     distBinDirectory = distDirectory </> "bin"
  234 
  235     distPackageDBPath compid = distDirectory </> "packagedb" </> prettyShow compid
  236     distPackageDB = SpecificPackageDB . distPackageDBPath
  237 
  238 
  239 defaultStoreDirLayout :: FilePath -> StoreDirLayout
  240 defaultStoreDirLayout storeRoot =
  241     StoreDirLayout {..}
  242   where
  243     storeDirectory compid =
  244       storeRoot </> prettyShow compid
  245 
  246     storePackageDirectory compid ipkgid =
  247       storeDirectory compid </> prettyShow ipkgid
  248 
  249     storePackageDBPath compid =
  250       storeDirectory compid </> "package.db"
  251 
  252     storePackageDB compid =
  253       SpecificPackageDB (storePackageDBPath compid)
  254 
  255     storePackageDBStack compid =
  256       [GlobalPackageDB, storePackageDB compid]
  257 
  258     storeIncomingDirectory compid =
  259       storeDirectory compid </> "incoming"
  260 
  261     storeIncomingLock compid unitid =
  262       storeIncomingDirectory compid </> prettyShow unitid <.> "lock"
  263 
  264 
  265 defaultCabalDirLayout :: FilePath -> CabalDirLayout
  266 defaultCabalDirLayout cabalDir =
  267     mkCabalDirLayout cabalDir Nothing Nothing
  268 
  269 mkCabalDirLayout :: FilePath -- ^ Cabal directory
  270                  -> Maybe FilePath -- ^ Store directory. Must be absolute
  271                  -> Maybe FilePath -- ^ Log directory
  272                  -> CabalDirLayout
  273 mkCabalDirLayout cabalDir mstoreDir mlogDir =
  274     CabalDirLayout {..}
  275   where
  276     cabalStoreDirLayout =
  277         defaultStoreDirLayout (fromMaybe (cabalDir </> "store") mstoreDir)
  278     cabalLogsDirectory = fromMaybe (cabalDir </> "logs") mlogDir
  279     cabalWorldFile = cabalDir </> "world"