{-# 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