Skip to content

Commit 9f7dc55

Browse files
athasMikolajulysses4ever
authored
Adopt XDG Base Directory Specification (#7386)
* Move towards using XDG directories. * Install binaries in $HOME/.local/bin. * Fix tests. * Ensure config file is where it should be. * Require newer directory for XdgState. * Put world file in XDG_STATE_HOME. * Oops, forgot to import. * Remove uses of getCabalDir. * These all need directory-1.3.7.0 now. * Oh right, not a builtin anymore. If this works I will also change the other .json files. * Try it by hand. * Haskell is better than JSON. * Bump directory in all jsons. * Put directory first. * Let us assume that getConfigFilePath gets this right. * Implement backwards compatibility. * This is now elsewhere. * We need to create parents as well because ~/.local might not exist. * Put scripts-build in distinct cache directory. * Document XDG behaviour. * Remove help text references to ~/.cabal. * Remove references to .cabla/bin. * Backwards compatible install paths. * Remove more references to ~/.cabal. * Fix typo. * Fix ~/.cabal paths making their way into default config. * Reduce duplication. * Add changelog entry. * Also note install dir change. * It is the cabal-install config file. * Avoid dependending on cabal-install in Hackage-tests. * ALso respect CABAL_DIR here. * Try leaving InstallDirs alone. * Also need duplication here. * Add missing newline. * Fix doc typos. * Make this a Haddock comment. * Revision field must not be null. * Link directories. * Update doc/config.rst Co-authored-by: Artem Pelenitsyn <a.pelenitsyn@gmail.com> * No need for this. * We install foreign libraries here now. * Clarify Nothing case. * Avoid using ~/.config/cabal in manual. Co-authored-by: Mikolaj Konarski <mikolaj@well-typed.com> Co-authored-by: Artem Pelenitsyn <a.pelenitsyn@gmail.com>
1 parent 67b3c8d commit 9f7dc55

31 files changed

+293
-153
lines changed

Cabal-tests/tests/HackageTests.hs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import Distribution.PackageDescription.PrettyPrint (showGenericPackageDescriptio
2525
import Distribution.PackageDescription.Quirks (patchQuirks)
2626
import Distribution.Simple.Utils (fromUTF8BS, toUTF8BS)
2727
import Numeric (showFFloat)
28-
import System.Directory (getAppUserDataDirectory)
28+
import System.Directory (getXdgDirectory, XdgDirectory(XdgCache, XdgConfig), getAppUserDataDirectory, doesDirectoryExist)
2929
import System.Environment (lookupEnv)
3030
import System.Exit (exitFailure)
3131
import System.FilePath ((</>))
@@ -63,27 +63,38 @@ import Data.TreeDiff.Pretty (ansiWlEditExprCompact)
6363
parseIndex :: (Monoid a, NFData a) => (FilePath -> Bool)
6464
-> (FilePath -> B.ByteString -> IO a) -> IO a
6565
parseIndex predicate action = do
66-
cabalDir <- getCabalDir
67-
configPath <- getCabalConfigPath cabalDir
66+
configPath <- getCabalConfigPath
6867
cfg <- B.readFile configPath
6968
cfgFields <- either (fail . show) pure $ Parsec.readFields cfg
69+
repoCache <- case lookupInConfig "remote-repo-cache" cfgFields of
70+
[] -> getCacheDirPath -- Default
71+
(rrc : _) -> return rrc -- User-specified
7072
let repos = reposFromConfig cfgFields
71-
repoCache = case lookupInConfig "remote-repo-cache" cfgFields of
72-
[] -> cabalDir </> "packages" -- Default
73-
(rrc : _) -> rrc -- User-specified
7473
tarName repo = repoCache </> repo </> "01-index.tar"
7574
mconcat <$> traverse (parseIndex' predicate action . tarName) repos
7675
where
77-
getCabalDir = do
78-
mx <- lookupEnv "CABAL_DIR"
79-
case mx of
80-
Just x -> return x
81-
Nothing -> getAppUserDataDirectory "cabal"
82-
getCabalConfigPath cabalDir = do
76+
getCacheDirPath =
77+
getXdgDirectory XdgCache $ "cabal" </> "packages"
78+
getCabalConfigPath = do
8379
mx <- lookupEnv "CABAL_CONFIG"
8480
case mx of
8581
Just x -> return x
86-
Nothing -> return (cabalDir </> "config")
82+
Nothing -> do
83+
mDir <- maybeGetCabalDir
84+
case mDir of
85+
Nothing -> getXdgDirectory XdgConfig $ "cabal" </> "config"
86+
Just dir -> return $ dir </> "config"
87+
maybeGetCabalDir :: IO (Maybe FilePath)
88+
maybeGetCabalDir = do
89+
mDir <- lookupEnv "CABAL_DIR"
90+
case mDir of
91+
Just dir -> return $ Just dir
92+
Nothing -> do
93+
defaultDir <- getAppUserDataDirectory "cabal"
94+
dotCabalExists <- doesDirectoryExist defaultDir
95+
return $ if dotCabalExists
96+
then Just defaultDir
97+
else Nothing
8798

8899

89100
parseIndex'

bootstrap/linux-8.10.7.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"dependencies": [
3+
{
4+
"cabal_sha256": "1125a0a4be3aafc8da208940f219d4e4df8a0db87d892cc42bb369071855c590",
5+
"revision": 0,
6+
"src_sha256": "dc2785d6548cec2e80700fab007d3e9467f65d3c58ab3efa21b34d9017cf0efd",
7+
"flags": [],
8+
"package": "directory",
9+
"source": "hackage",
10+
"version": "1.3.7.1"
11+
},
312
{
413
"cabal_sha256": null,
514
"revision": null,
@@ -352,10 +361,6 @@
352361
"package": "unix",
353362
"version": "2.7.2.2"
354363
},
355-
{
356-
"package": "directory",
357-
"version": "1.3.6.0"
358-
},
359364
{
360365
"package": "transformers",
361366
"version": "0.5.6.2"

bootstrap/linux-8.6.5.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"dependencies": [
3+
{
4+
"cabal_sha256": "1125a0a4be3aafc8da208940f219d4e4df8a0db87d892cc42bb369071855c590",
5+
"revision": 0,
6+
"src_sha256": "dc2785d6548cec2e80700fab007d3e9467f65d3c58ab3efa21b34d9017cf0efd",
7+
"flags": [],
8+
"package": "directory",
9+
"source": "hackage",
10+
"version": "1.3.7.1"
11+
},
312
{
413
"cabal_sha256": null,
514
"revision": null,
@@ -363,10 +372,6 @@
363372
"package": "unix",
364373
"version": "2.7.2.2"
365374
},
366-
{
367-
"package": "directory",
368-
"version": "1.3.3.0"
369-
},
370375
{
371376
"package": "transformers",
372377
"version": "0.5.6.2"

bootstrap/linux-8.8.4.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"dependencies": [
3+
{
4+
"cabal_sha256": "1125a0a4be3aafc8da208940f219d4e4df8a0db87d892cc42bb369071855c590",
5+
"revision": 0,
6+
"src_sha256": "dc2785d6548cec2e80700fab007d3e9467f65d3c58ab3efa21b34d9017cf0efd",
7+
"flags": [],
8+
"package": "directory",
9+
"source": "hackage",
10+
"version": "1.3.7.1"
11+
},
312
{
413
"cabal_sha256": null,
514
"revision": null,
@@ -363,10 +372,6 @@
363372
"package": "unix",
364373
"version": "2.7.2.2"
365374
},
366-
{
367-
"package": "directory",
368-
"version": "1.3.6.0"
369-
},
370375
{
371376
"package": "transformers",
372377
"version": "0.5.6.2"

bootstrap/linux-9.0.2.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"dependencies": [
3+
{
4+
"cabal_sha256": "1125a0a4be3aafc8da208940f219d4e4df8a0db87d892cc42bb369071855c590",
5+
"revision": 0,
6+
"src_sha256": "dc2785d6548cec2e80700fab007d3e9467f65d3c58ab3efa21b34d9017cf0efd",
7+
"flags": [],
8+
"package": "directory",
9+
"source": "hackage",
10+
"version": "1.3.7.1"
11+
},
312
{
413
"cabal_sha256": null,
514
"revision": null,
@@ -352,10 +361,6 @@
352361
"package": "unix",
353362
"version": "2.7.2.2"
354363
},
355-
{
356-
"package": "directory",
357-
"version": "1.3.6.2"
358-
},
359364
{
360365
"package": "transformers",
361366
"version": "0.5.6.2"

bootstrap/linux-9.2.3.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
{
22
"dependencies": [
3+
{
4+
"cabal_sha256": "1125a0a4be3aafc8da208940f219d4e4df8a0db87d892cc42bb369071855c590",
5+
"revision": 0,
6+
"src_sha256": "dc2785d6548cec2e80700fab007d3e9467f65d3c58ab3efa21b34d9017cf0efd",
7+
"flags": [],
8+
"package": "directory",
9+
"source": "hackage",
10+
"version": "1.3.7.1"
11+
},
312
{
413
"cabal_sha256": null,
514
"revision": null,
@@ -355,10 +364,6 @@
355364
"package": "unix",
356365
"version": "2.7.2.2"
357366
},
358-
{
359-
"package": "directory",
360-
"version": "1.3.6.2"
361-
},
362367
{
363368
"package": "transformers",
364369
"version": "0.5.6.2"

cabal-install/cabal-install.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ library
208208
bytestring >= 0.10.6.0 && < 0.12,
209209
containers >= 0.5.6.2 && < 0.7,
210210
cryptohash-sha256 >= 0.11 && < 0.12,
211-
directory >= 1.2.2.0 && < 1.4,
211+
directory >= 1.3.7.0 && < 1.4,
212212
echo >= 0.1.3 && < 0.2,
213213
edit-distance >= 0.2.2 && < 0.3,
214214
exceptions >= 0.10.4 && < 0.11,

cabal-install/main/Main.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ filterBuildFlags version config buildFlags
427427
buildNumJobs = NoFlag
428428
}
429429
buildFlags_latest = buildFlags {
430-
-- Take the 'jobs' setting '~/.cabal/config' into account.
430+
-- Take the 'jobs' setting config file into account.
431431
buildNumJobs = Flag . Just . determineNumJobs $
432432
(numJobsConfigFlag `mappend` numJobsCmdLineFlag)
433433
}

cabal-install/src/Distribution/Client/CmdClean.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ module Distribution.Client.CmdClean (cleanCommand, cleanAction) where
44
import Prelude ()
55
import Distribution.Client.Compat.Prelude
66

7+
import Distribution.Client.Config
8+
( defaultScriptBuildsDir )
79
import Distribution.Client.DistDirLayout
810
( DistDirLayout(..), defaultDistDirLayout )
911
import Distribution.Client.ProjectConfig
1012
( findProjectRoot )
11-
import Distribution.Client.ScriptUtils
12-
( getScriptCacheDirectoryRoot )
1313
import Distribution.Client.Setup
1414
( GlobalFlags )
1515
import Distribution.ReadE ( succeedReadE )
@@ -121,7 +121,7 @@ cleanAction CleanFlags{..} extraArgs _ = do
121121
-- There is currently no good way to specify to only clean orphaned caches.
122122
-- It would be better as part of an explicit gc step (see issue #3333)
123123
toClean <- Set.fromList <$> mapM canonicalizePath extraArgs
124-
cacheDir <- getScriptCacheDirectoryRoot
124+
cacheDir <- defaultScriptBuildsDir
125125
existsCD <- doesDirectoryExist cacheDir
126126
caches <- if existsCD then listDirectory cacheDir else return []
127127
paths <- fmap concat . forM caches $ \cache -> do

cabal-install/src/Distribution/Client/CmdInstall.hs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ import Distribution.Simple.BuildPaths
6464
import Distribution.Simple.Program.Find
6565
( ProgramSearchPathEntry(..) )
6666
import Distribution.Client.Config
67-
( defaultInstallPath, getCabalDir, loadConfig, SavedConfig(..) )
67+
( defaultInstallPath, loadConfig, SavedConfig(..) )
6868
import qualified Distribution.Simple.PackageIndex as PI
6969
import Distribution.Solver.Types.PackageIndex
7070
( lookupPackageName, searchByName )
@@ -150,7 +150,7 @@ installCommand = CommandUI
150150
, commandDescription = Just $ \_ -> wrapText $
151151
"Installs one or more packages. This is done by installing them "
152152
++ "in the store and symlinking/copying the executables in the directory "
153-
++ "specified by the --installdir flag (`~/.cabal/bin/` by default). "
153+
++ "specified by the --installdir flag (`~/.local/bin/` by default). "
154154
++ "If you want the installed executables to be available globally, "
155155
++ "make sure that the PATH environment variable contains that directory. "
156156
++ "\n\n"
@@ -254,7 +254,6 @@ installAction flags@NixStyleFlags { extraFlags = clientInstallFlags', .. } targe
254254
withoutProject globalConfig = do
255255
tss <- traverse (parseWithoutProjectTargetSelector verbosity) targetStrings'
256256

257-
cabalDir <- getCabalDir
258257
let
259258
projectConfig = globalConfig <> cliConfig
260259

@@ -268,8 +267,9 @@ installAction flags@NixStyleFlags { extraFlags = clientInstallFlags', .. } targe
268267

269268
mlogsDir = flagToMaybe projectConfigLogsDir
270269
mstoreDir = flagToMaybe projectConfigStoreDir
271-
cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
270+
cabalDirLayout <- mkCabalDirLayout mstoreDir mlogsDir
272271

272+
let
273273
buildSettings = resolveBuildTimeSettings
274274
verbosity cabalDirLayout
275275
projectConfig
@@ -605,7 +605,7 @@ installExes verbosity baseCtx buildCtx platform compiler
605605
installdir <- fromFlagOrDefault
606606
(warn verbosity installdirUnknown >> pure installPath) $
607607
pure <$> cinstInstalldir clientInstallFlags
608-
createDirectoryIfMissingVerbose verbosity False installdir
608+
createDirectoryIfMissingVerbose verbosity True installdir
609609
warnIfNoExes verbosity buildCtx
610610

611611
installMethod <- flagElim defaultMethod return $
@@ -912,11 +912,10 @@ getPackageDbStack
912912
-> Flag FilePath
913913
-> IO PackageDBStack
914914
getPackageDbStack compilerId storeDirFlag logsDirFlag = do
915-
cabalDir <- getCabalDir
916915
mstoreDir <- traverse makeAbsolute $ flagToMaybe storeDirFlag
917916
let
918917
mlogsDir = flagToMaybe logsDirFlag
919-
cabalLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
918+
cabalLayout <- mkCabalDirLayout mstoreDir mlogsDir
920919
pure $ storePackageDBStack (cabalStoreDirLayout cabalLayout) compilerId
921920

922921
-- | This defines what a 'TargetSelector' means for the @bench@ command.

0 commit comments

Comments
 (0)