2011-01-16 20:05:05 +00:00
|
|
|
{- git-annex command line parsing and dispatch
|
2010-11-02 23:04:24 +00:00
|
|
|
-
|
|
|
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
2010-12-30 19:06:26 +00:00
|
|
|
module CmdLine (
|
2010-12-30 20:52:24 +00:00
|
|
|
dispatch,
|
2010-12-31 00:08:22 +00:00
|
|
|
usage,
|
2011-01-16 20:05:05 +00:00
|
|
|
shutdown
|
2010-12-30 19:06:26 +00:00
|
|
|
) where
|
2010-11-02 23:04:24 +00:00
|
|
|
|
2011-01-16 20:05:05 +00:00
|
|
|
import System.IO.Error (try)
|
2010-11-02 23:04:24 +00:00
|
|
|
import System.Console.GetOpt
|
2010-12-08 18:07:49 +00:00
|
|
|
import Control.Monad.State (liftIO)
|
2011-04-07 17:59:31 +00:00
|
|
|
import Control.Monad (when)
|
2010-11-02 23:04:24 +00:00
|
|
|
|
|
|
|
import qualified Annex
|
2011-04-07 17:59:31 +00:00
|
|
|
import qualified AnnexQueue
|
2011-06-30 17:16:57 +00:00
|
|
|
import qualified Git
|
2011-06-23 01:19:52 +00:00
|
|
|
import Content
|
2010-11-02 23:04:24 +00:00
|
|
|
import Types
|
|
|
|
import Command
|
2010-12-30 20:52:24 +00:00
|
|
|
import Options
|
2011-01-16 20:05:05 +00:00
|
|
|
import Messages
|
2011-08-17 18:14:43 +00:00
|
|
|
import Init
|
2010-11-02 23:04:24 +00:00
|
|
|
|
2010-12-30 20:52:24 +00:00
|
|
|
{- Runs the passed command line. -}
|
2011-06-02 06:40:43 +00:00
|
|
|
dispatch :: [String] -> [Command] -> [Option] -> String -> Git.Repo -> IO ()
|
|
|
|
dispatch args cmds options header gitrepo = do
|
2011-03-12 19:30:17 +00:00
|
|
|
setupConsole
|
2011-07-05 22:31:46 +00:00
|
|
|
state <- Annex.new gitrepo
|
2010-12-30 19:44:15 +00:00
|
|
|
(actions, state') <- Annex.run state $ parseCmd args header cmds options
|
2011-03-19 22:33:39 +00:00
|
|
|
tryRun state' $ [startup] ++ actions ++ [shutdown]
|
2010-12-30 19:44:15 +00:00
|
|
|
|
2010-12-08 18:07:49 +00:00
|
|
|
{- Parses command line, stores configure flags, and returns a
|
|
|
|
- list of actions to be run in the Annex monad. -}
|
2010-12-30 19:06:26 +00:00
|
|
|
parseCmd :: [String] -> String -> [Command] -> [Option] -> Annex [Annex Bool]
|
|
|
|
parseCmd argv header cmds options = do
|
2011-07-15 07:12:05 +00:00
|
|
|
(flags, params) <- liftIO getopt
|
2010-12-30 20:52:24 +00:00
|
|
|
when (null params) $ error $ "missing command" ++ usagemsg
|
2010-11-06 21:06:19 +00:00
|
|
|
case lookupCmd (head params) of
|
2010-12-30 20:52:24 +00:00
|
|
|
[] -> error $ "unknown command" ++ usagemsg
|
2010-12-30 18:19:16 +00:00
|
|
|
[command] -> do
|
2010-12-08 18:07:49 +00:00
|
|
|
_ <- sequence flags
|
2011-08-17 18:14:43 +00:00
|
|
|
checkCmdEnviron command
|
2011-03-19 22:58:49 +00:00
|
|
|
prepCommand command (drop 1 params)
|
2010-12-30 18:19:16 +00:00
|
|
|
_ -> error "internal error: multiple matching commands"
|
2010-11-02 23:04:24 +00:00
|
|
|
where
|
|
|
|
getopt = case getOpt Permute options argv of
|
2010-12-30 20:52:24 +00:00
|
|
|
(flags, params, []) ->
|
|
|
|
return (flags, params)
|
|
|
|
(_, _, errs) ->
|
|
|
|
ioError (userError (concat errs ++ usagemsg))
|
2010-12-30 18:19:16 +00:00
|
|
|
lookupCmd cmd = filter (\c -> cmd == cmdname c) cmds
|
2010-12-30 20:52:24 +00:00
|
|
|
usagemsg = "\n\n" ++ usage header cmds options
|
2010-12-30 19:06:26 +00:00
|
|
|
|
2011-08-17 18:14:43 +00:00
|
|
|
{- Checks that the command can be run in the current environment. -}
|
|
|
|
checkCmdEnviron :: Command -> Annex ()
|
2011-08-17 22:38:26 +00:00
|
|
|
checkCmdEnviron command = when (cmdusesrepo command) ensureInitialized
|
2011-08-17 18:14:43 +00:00
|
|
|
|
2010-12-30 19:06:26 +00:00
|
|
|
{- Usage message with lists of commands and options. -}
|
|
|
|
usage :: String -> [Command] -> [Option] -> String
|
|
|
|
usage header cmds options =
|
2010-12-30 20:52:24 +00:00
|
|
|
usageInfo (header ++ "\n\nOptions:") options ++
|
|
|
|
"\nCommands:\n" ++ cmddescs
|
2010-12-30 19:06:26 +00:00
|
|
|
where
|
|
|
|
cmddescs = unlines $ map (indent . showcmd) cmds
|
|
|
|
showcmd c =
|
|
|
|
cmdname c ++
|
2010-12-30 19:15:22 +00:00
|
|
|
pad (longest cmdname + 1) (cmdname c) ++
|
2010-12-30 19:06:26 +00:00
|
|
|
cmdparams c ++
|
2010-12-30 19:15:22 +00:00
|
|
|
pad (longest cmdparams + 2) (cmdparams c) ++
|
2010-12-30 19:06:26 +00:00
|
|
|
cmddesc c
|
|
|
|
pad n s = replicate (n - length s) ' '
|
2010-12-30 19:15:22 +00:00
|
|
|
longest f = foldl max 0 $ map (length . f) cmds
|
2011-01-16 20:05:05 +00:00
|
|
|
|
|
|
|
{- Runs a list of Annex actions. Catches IO errors and continues
|
|
|
|
- (but explicitly thrown errors terminate the whole command).
|
|
|
|
-}
|
2011-01-26 01:49:04 +00:00
|
|
|
tryRun :: Annex.AnnexState -> [Annex Bool] -> IO ()
|
2011-07-15 07:12:05 +00:00
|
|
|
tryRun = tryRun' 0
|
|
|
|
tryRun' :: Integer -> Annex.AnnexState -> [Annex Bool] -> IO ()
|
|
|
|
tryRun' errnum state (a:as) = do
|
2011-04-07 17:59:31 +00:00
|
|
|
result <- try $ Annex.run state $ do
|
|
|
|
AnnexQueue.flushWhenFull
|
2011-10-02 15:16:34 +00:00
|
|
|
r <- a
|
|
|
|
liftIO Git.reap
|
|
|
|
return r
|
2011-01-16 20:05:05 +00:00
|
|
|
case result of
|
|
|
|
Left err -> do
|
2011-07-05 18:58:33 +00:00
|
|
|
Annex.eval state $ do
|
|
|
|
showErr err
|
2011-09-06 17:46:08 +00:00
|
|
|
showEndFail
|
2011-07-15 07:12:05 +00:00
|
|
|
tryRun' (errnum + 1) state as
|
|
|
|
Right (True,state') -> tryRun' errnum state' as
|
|
|
|
Right (False,state') -> tryRun' (errnum + 1) state' as
|
|
|
|
tryRun' errnum _ [] = when (errnum > 0) $ error $ show errnum ++ " failed"
|
2011-01-16 20:05:05 +00:00
|
|
|
|
|
|
|
{- Actions to perform each time ran. -}
|
|
|
|
startup :: Annex Bool
|
2011-08-17 18:14:43 +00:00
|
|
|
startup = return True
|
2011-01-16 20:05:05 +00:00
|
|
|
|
|
|
|
{- Cleanup actions. -}
|
2011-01-30 03:32:32 +00:00
|
|
|
shutdown :: Annex Bool
|
|
|
|
shutdown = do
|
2011-06-23 01:19:52 +00:00
|
|
|
saveState
|
2011-01-30 03:32:32 +00:00
|
|
|
return True
|