cabalg-0.2.3: src/Main.hs
import Control.Applicative
import Control.Arrow
import Control.Monad
import Data.List
import Data.Maybe
import System.Directory
import System.Environment
import System.FilePath
import System.Process
import Git
main :: IO ()
main = do
(repos, args) <- reposAndArgs <$> getArgs
cabalFiles <- mapM fetch repos
cabalInstall (catMaybes cabalFiles) args
reposAndArgs :: [String] -> ([String], Maybe String)
reposAndArgs = second flags . span (/= "--")
where
flags [] = Nothing
flags ["--"] = Nothing
flags (_:xs) = Just $ unwords xs
fetch :: String -> IO (Maybe FilePath)
fetch urlAndMaybeRevision = do
currentDir <- getCurrentDirectory
newDir <- createNonExistentDirectory currentDir ("cabalg_" ++ repoName urlAndMaybeRevision)
case maybeRevision of
Just revision -> cloneRevision url revision newDir
Nothing -> clone url newDir
findCabalFile newDir
where
maybeRevision = case dropWhile (/= '@') urlAndMaybeRevision of
'@':x -> Just x
_ -> Nothing
url = takeWhile (/= '@') urlAndMaybeRevision
cabalInstall :: [String] -> Maybe String -> IO ()
cabalInstall cabalFiles args = void $ readProcess "cabal" ("install" : cabalFiles ++ words (fromMaybe "" args)) []
repoName :: String -> String
repoName = takeWhile (/= '@') . lastSplitOn '/'
where lastSplitOn :: Eq a => a -> [a] -> [a]
lastSplitOn c = go []
where
go acc (x:xs) | x == c = go [] xs
| otherwise = go (acc ++ [x]) xs
go acc [] = acc
createNonExistentDirectory :: FilePath -> String -> IO FilePath
createNonExistentDirectory currentDir dirname = do
newDir <- generateNonExistentDirectory dirname Nothing
createDirectory newDir
return newDir
where
generateNonExistentDirectory :: FilePath -> Maybe Int -> IO FilePath
generateNonExistentDirectory d suffix = let fullDirName = currentDir </> d ++ maybe "" show suffix in do
exist <- doesDirectoryExist fullDirName
if exist
then generateNonExistentDirectory d $ return $ maybe 1 (+ 1) suffix
else return fullDirName
findCabalFile :: FilePath -> IO (Maybe FilePath)
findCabalFile path = ((path </>) `fmap`) `fmap` find (".cabal" `isSuffixOf`) `fmap` getDirectoryContents path