packages feed

clone-all-0.1.0.0: clone-all.hs

{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}

module Main where

import Prelude
import System.Directory          (doesDirectoryExist)
import Control.Monad             (filterM, liftM)
import System.Exit               (ExitCode(..), exitFailure, exitSuccess)
import System.Process            (system)
import Control.Applicative       ((<$>), (<*>))
import Data.Monoid               (mempty, (<>))
import Data.Maybe                (fromMaybe)
import Github.Data               (Repo(..))
import Github.Repos              (userRepos, RepoPublicity(..))

import qualified Options.Applicative.Builder.Internal as X
import qualified Options.Applicative                  as O

data Options = Options { directory :: String
                       , user      :: String
                       } deriving Show

main :: IO ()
main = O.execParser (O.info (O.helper <*> options) mempty) >>= start

options :: O.Parser Options
options = Options
  <$> defStr "."             ( O.metavar "DIRECTORY"            <> O.help "Directory to clone everything into" )
  <*> O.strOption            ( O.short 'u' <> O.long "user"     <> O.help "Name of the user to clone the repos of.")

defStr :: String -> X.Mod X.ArgumentFields String -> O.Parser String
defStr a = def a . O.argument O.str

def :: a -> O.Parser a -> O.Parser a
def a = fmap (fromMaybe a) . O.optional

start :: Options -> IO ()
start opts = do
  putStrLn $ "Looking up repositories for " ++ (user opts) ++ " ..."

  d <- userRepos (user opts) All

  case d of
    Left  err   -> putStrLn $ show err
    Right repos -> cloneRepos repos opts


cloneRepos :: [Repo] -> Options -> IO ()
cloneRepos rawRepos opts = do
  putStrLn $ "Found " ++ (show $ length rawRepos) ++ " repositories for " ++ (user opts) ++ "."

  -- Filter the ones that already exist
  repos <- filterM (\r -> (liftM not) $ doesDirectoryExist $ ((directory opts) ++ "/" ++ (repoName r))) rawRepos

  putStrLn $ (show $ length repos) ++ " that you don't already have."

  returnCodes <- mapM (\r -> system $ "cd " ++ (directory opts) ++ " && git clone " ++ (repoSshUrl r)) repos
  let rs = all (\e -> e == ExitSuccess) returnCodes
  
  case rs
    of True   -> exitSuccess
       False  -> exitFailure