LazyVault-0.0: src/Sandboxes.hs
{-
Copyright 2013 Kevin van Rooijen
This file is part of LazyVault.
LazyVault is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
LazyVault is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with LazyVault. If not, see http://www.gnu.org/licenses/.
-}
module Sandboxes where
import System.Posix.Files ( getSymbolicLinkStatus
, isSymbolicLink
, createSymbolicLink
)
import System.Directory ( doesDirectoryExist
, createDirectory
, getAppUserDataDirectory
, removeDirectoryRecursive
, getDirectoryContents
, removeFile
, renameDirectory
)
import Data.Foldable ( for_ )
import System.FilePath.Posix ((</>))
import System.IO
data CurrentDir = DSym | DDir | DEmpty deriving (Show)
lazyDir :: IO FilePath
lazyDirSandboxes :: IO FilePath
homeGhc :: IO FilePath
homeCabal :: IO FilePath
currentSBFile :: IO FilePath
lazyDir = getAppUserDataDirectory "lazyVault"
lazyDirSandboxes = getAppUserDataDirectory $ "lazyVault" </> "sandboxes"
currentSBFile = getAppUserDataDirectory $ "lazyVault" </> ".current"
homeGhc = getAppUserDataDirectory "ghc"
homeCabal = getAppUserDataDirectory "cabal"
(<:>) :: [a -> Bool] -> [a] -> [a]
xs <:> a = foldl (\acc x -> filter x acc) a xs
binPaths :: String
binPaths = "paths=`find /home/kevin/.lazyVault/* -type d | grep 'cabal/bin' | sed ':a;N;$!ba;s/\\n/ /g'`\nexport PATH=$PATH:${paths// /:}"
createEnv :: IO ()
createEnv = do
lazyDirExist <- lazyDir >>= doesDirectoryExist
if lazyDirExist == True
then return ()
else do
sequence [ lazyDir, lazyDirSandboxes ] >>=
mapM_ createDirectory
lazyDir >>= \d -> writeFile (d </> "binPaths") binPaths
lazyDir >>= \d -> writeFile (d </> ".current") "none"
createSandbox :: FilePath -> IO ()
createSandbox name = do
createEnv
lazyD <- lazyDirSandboxes
let projectDir = lazyD </> name
let ghc = projectDir </> "ghc"
cabal = projectDir </> "cabal"
exist <- (doesDirectoryExist projectDir)
if exist == True
then error "Project already Exists"
else mapM_ createDirectory $ [projectDir,ghc,cabal]
sandboxExist :: String -> IO Bool
sandboxExist name = do
lazy <- lazyDirSandboxes
doesDirectoryExist $ (lazy </> name)
writeCurrent :: String -> IO ()
writeCurrent sb = lazyDir >>= \a -> writeFile (a </> ".current") sb
removeSandbox :: IO String -> IO ()
removeSandbox sb = do
dir <- sb
exist <- lazyDirSandboxes >>= \l -> doesDirectoryExist $ l </> dir
if exist == True
then do
putStrLn "Are you sure you want to remove this sandbox?"
answer <- getLine
case answer of
"no" -> return ()
"yes" -> do
lazyDirSandboxes >>= \l -> removeDirectoryRecursive $ l </> dir
file <- currentSBFile
handle <- openFile file ReadMode
contents <- hGetContents handle
if contents == dir
then do
writeCurrent "none"
sequence [homeGhc, homeCabal] >>= mapM_ removeFile
else return ()
hClose handle
_ -> do putStrLn "Please answer yes or no"
removeSandbox sb
else error "Sandbox doesn't exist."
setSandbox :: String -> IO ()
setSandbox name = do
sandboxExist name >>= \bool ->
if bool == True
then do
dirList <- mapM checkDir [homeGhc, homeCabal]
let dirTuples = zip dirList [homeGhc, homeCabal]
for_ dirTuples $ \dir ->
case (fst dir) of
DSym -> snd dir >>= removeFile
DDir -> error "Move your .ghc and/or .cabal directory. Or use backup [Name]"
DEmpty -> return ()
[ghc, cabal] <- getSandboxDirs name
[newGhc, newCabal] <- sequence [homeGhc, homeCabal]
createSymbolicLink ghc newGhc
createSymbolicLink cabal newCabal
writeCurrent name
return ()
else print "Sanbox Doesn't exist"
listSandboxes :: IO ()
listSandboxes = do
sandBoxes <- lazyDirSandboxes >>= getDirectoryContents
file <- currentSBFile
handle <- openFile file ReadMode
contents <- hGetContents handle
putStrLn "Available sandboxes:"
putStrLn $ contents ++ " **"
hClose handle
for_ ([(/="."),(/=".."),(/=contents)] <:> sandBoxes) putStrLn
backupSystemDirs :: String -> IO ()
backupSystemDirs name = do
lazy <- lazyDirSandboxes
ghcExist <- checkDir homeGhc
cabalExist <- checkDir homeCabal
createDirectory $ lazy </> name
for_ [ (ghcExist, "ghc")
, (cabalExist, "cabal")] $ \a ->
case fst a of
DEmpty -> return ()
DSym -> homeP (snd a) >>= removeFile
DDir -> homeP (snd a) >>= \path ->
renameDirectory path $ lazy </> name </> (snd a)
where homeP a = getAppUserDataDirectory a
getSandboxDirs :: String -> IO [String]
getSandboxDirs name = do
location <- lazyDirSandboxes >>= \a -> return $ (</>name) a
return location >>= \a -> return $ map (a </>) ["ghc","cabal"]
checkDir :: IO FilePath -> IO CurrentDir
checkDir path = do
pathname <- path
exist <- doesDirectoryExist pathname
if exist == False
then return DEmpty
else getSymbolicLinkStatus pathname >>= \b ->
if isSymbolicLink b == False
then return DDir
else return DSym