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