1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
{-# LANGUAGE CPP #-}
{-# LANGUAGE TupleSections #-}
module SensibleDir where
import Paths_testcabaldir
import System.Directory
#ifdef VERSION_directory_xdg
import System.DirectoryXdg
#endif
import System.FilePath
import System.IO
import System.Info
import System.Environment
import Control.Arrow
import Control.Applicative
import Data.List
installScenario = NotInstalled
doit = do
ddir <- getDataDir
ldir <- getLibDir
pname <- getProgName
ppath <- getExecutablePath
sysconfdir <- getSysconfDir
putStrLn ("ddir = " ++ ddir);
putStrLn ("ldir = " ++ ldir);
putStrLn ("sysconfdir = " ++ sysconfdir);
putStrLn ("pname = " ++ pname);
putStr "runningInBuildDir = "
print =<< runningInBuildDir
putStr "detectLikelyInstall = "
print =<< detectLikelyInstall
putStrLn "---------------------"
putStr "sensibleCacheDir = "
print =<< sensibleCacheDir pname
-- putStr "sensibleConfigDir = "
-- print =<< sensibleConfigDir pname
runningInBuildDir :: IO Bool
runningInBuildDir = any (=="build") . take 2 . reverse . splitDirectories . takeDirectory <$> getExecutablePath
runningInCabalDir :: IO Bool
runningInCabalDir = any (==".cabal") . take 2 . reverse . splitDirectories . takeDirectory <$> getExecutablePath
runningInSysBin = do
exedir <- splitDirectories . takeDirectory <$> getExecutablePath
return $
case take 3 (drop 1 exedir) of
["bin"] -> True
["sbin"] -> True
["usr","bin"] -> True
["usr","sbin"] -> True
_ -> False
runningInLocalBin = do
exedir <- splitDirectories . takeDirectory <$> getExecutablePath
putStr "exedir = "
print exedir
return $
case take 3 (drop 1 exedir) of
["usr","local","bin"] -> True
["usr","local","sbin"] -> True
_ -> False
-- scenarios
data InstallScenario = PrefixInstall
-- ^ installed in /opt or some other prefix, or running inside source folder
| SystemInstall
-- ^ installed system wide
| LocalInstall
-- ^ installed in /usr/local/
| UserInstall
-- ^ installed for a given user
| NotInstalled
-- ^ not installed, built by cabal or make, running from dist folder
deriving (Show,Enum,Eq)
-- | careful, assumes unix-style FHS
-- windows aware contributions welcome
-- Detects the likely install scenario based on the path to the exectuable.
detectLikelyInstall :: IO InstallScenario
detectLikelyInstall = do
bBuildDir <- fmap (,NotInstalled) runningInBuildDir
bCabalDir <- fmap (,UserInstall) runningInCabalDir
bLocalDir <- fmap (,LocalInstall) runningInLocalBin
bSysDir <- fmap (,SystemInstall) runningInSysBin
case dropWhile (not . fst) [bBuildDir,bCabalDir,bLocalDir,bSysDir] of
(True,scenario):_ -> return scenario
_ -> return PrefixInstall
isUnix os = not $ "mingw" `isPrefixOf` os
-- | Try to get the cache directory appropriate to the install scenario.
-- On windows it just calls getAppUserDataDirectory and appends "cache".
-- (windows behavior subject to change, contributions welcome)
sensibleCacheDir suffix = do
let ifunix x = if isUnix os then x
else PrefixInstall
install <- ifunix <$> detectLikelyInstall
case install of
PrefixInstall -> do
if isUnix os
then do
dir <- splitDirectories . takeDirectory <$> getExecutablePath
let rdir = reverse dir
case take 1 rdir of
["bin"] -> return $ (foldl1 combine $ reverse (drop 1 rdir)) </> "cache" </> suffix
_ -> fmap ((</> suffix) . (</> "cache") . takeDirectory) getExecutablePath
else getAppUserDataDirectory ("cache" </> suffix)
SystemInstall -> return ("/var/cache" </> suffix)
LocalInstall -> return ("/var/local/cache" </> suffix)
UserInstall -> getXdgDirectory XdgCache suffix
NotInstalled -> do
dir <- splitDirectories . takeDirectory <$> getExecutablePath
let rdir = reverse dir
return . foldl1 combine $ reverse ("cache": drop 2 rdir)
-- | like 'sensibleCacheDir', but creates it if needed
sensibleCacheDirCreateIfMissing suffix = do
dir <- sensibleCacheDir suffix
createDirectoryIfMissing True dir
|