summaryrefslogtreecommitdiff
path: root/src/SensibleDir.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SensibleDir.hs')
-rw-r--r--src/SensibleDir.hs121
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 #-}
3module SensibleDir where
4
5import Paths_testcabaldir
6import System.Directory
7#ifdef VERSION_directory_xdg
8import System.DirectoryXdg
9#endif
10import System.FilePath
11import System.IO
12import System.Info
13import System.Environment
14import Control.Arrow
15import Control.Applicative
16import Data.List
17
18installScenario = NotInstalled
19doit = 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
39runningInBuildDir :: IO Bool
40runningInBuildDir = any (=="build") . take 2 . reverse . splitDirectories . takeDirectory <$> getExecutablePath
41
42runningInCabalDir :: IO Bool
43runningInCabalDir = any (==".cabal") . take 2 . reverse . splitDirectories . takeDirectory <$> getExecutablePath
44
45runningInSysBin = 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
55runningInLocalBin = 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
66data 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.
81detectLikelyInstall :: IO InstallScenario
82detectLikelyInstall = 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
91isUnix 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)
96sensibleCacheDir 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
119sensibleCacheDirCreateIfMissing suffix = do
120 dir <- sensibleCacheDir suffix
121 createDirectoryIfMissing True dir