cabalg-0.2.9: src/Main.hs
import Control.Applicative
import Control.Exception
import Control.Monad
import Data.Foldable
import Data.List
import Data.Maybe
import Data.Traversable
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO.Error
import System.Process
import Cabalg.Args
import Cabalg.Git
import Cabalg.Version
import System.Directory.NonExistent
main :: IO ()
main = do
action <- fromString <$> getArgs
case action of
Help -> printHelp
Version -> putStrLn version
Install repos args -> do
cabalFiles <- Data.Traversable.mapM fetch repos
cabalInstall (catMaybes cabalFiles) args
fetch :: String -> IO (Maybe FilePath)
fetch urlAndMaybeRevision = do
dir <- getWorkingDirectory
newDir <- createNonExistentDirectory dir ("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
getWorkingDirectory :: IO FilePath
getWorkingDirectory =
liftM2 fromMaybe getCurrentDirectory . fmap Data.Foldable.msum . traverse lookupEnv' $ ["TMPDIR", "TEMP"]
lookupEnv' :: String -> IO (Maybe String)
lookupEnv' var = do
fmap eitherToMaybe . tryJust (guard . isDoesNotExistError) $ getEnv var
where
eitherToMaybe (Left _) = Nothing
eitherToMaybe (Right x) = Just x
cabalInstall :: [String] -> Maybe String -> IO ()
cabalInstall cabalFiles args = do
(_, _, _, procHandle) <- createProcess $ proc "cabal" $ "install" : cabalFiles ++ words (fromMaybe "" args)
exitCode <- waitForProcess procHandle
case exitCode of
ExitSuccess -> return ()
ExitFailure _ -> exitFailure
-- | Compute the repository name from the URL
--
-- >>> repoName "https://github.com/dmalikov/cabalg"
-- "cabalg"
--
-- >>> repoName "https://github.com/dmalikov/cabalg@master"
-- "cabalg"
--
-- >>> repoName "git://github.com/dmalikov/cabalg"
-- "cabalg"
repoName :: String -> String
repoName = takeWhile (/= '@') . lastSplitOn '/'
where
lastSplitOn c = go
where
go xs = case break (== c) xs of
(ys , []) -> ys
(_ , _ : xs') -> go xs'
findCabalFile :: FilePath -> IO (Maybe FilePath)
findCabalFile path = ((path </>) `fmap`) `fmap` Data.List.find (".cabal" `isSuffixOf`) `fmap` getDirectoryContents path