This commit is contained in:
Joey Hess 2011-10-30 20:04:15 -04:00
parent 1530eac312
commit e09dd6f306
3 changed files with 51 additions and 59 deletions

View file

@ -31,9 +31,6 @@ toOpt = CommandCheck 2 $ do
v <- Annex.getState Annex.toremote v <- Annex.getState Annex.toremote
unless (v == Nothing) $ error "cannot use --to with this command" unless (v == Nothing) $ error "cannot use --to with this command"
checkCommand :: Command -> Annex ()
checkCommand Command { cmdcheck = c } = sequence_ $ map runCheck c
dontCheck :: CommandCheck -> Command -> Command dontCheck :: CommandCheck -> Command -> Command
dontCheck check cmd = mutateCheck cmd $ \c -> filter (/= check) c dontCheck check cmd = mutateCheck cmd $ \c -> filter (/= check) c

View file

@ -21,45 +21,41 @@ import qualified Git
import Annex.Content import Annex.Content
import Command import Command
type Params = [String]
type Flags = [Annex ()]
{- Runs the passed command line. -} {- Runs the passed command line. -}
dispatch :: [String] -> [Command] -> [Option] -> String -> Git.Repo -> IO () dispatch :: Params -> [Command] -> [Option] -> String -> Git.Repo -> IO ()
dispatch args cmds options header gitrepo = do dispatch args cmds options header gitrepo = do
setupConsole setupConsole
state <- Annex.new gitrepo state <- Annex.new gitrepo
((cmd, actions), state') <- Annex.run state $ parseCmd args header cmds options (actions, state') <- Annex.run state $ do
sequence_ flags
prepCommand cmd params
tryRun state' cmd $ [startup] ++ actions ++ [shutdown] tryRun state' cmd $ [startup] ++ actions ++ [shutdown]
{- Parses command line, stores configure flags, and returns a
- list of actions to be run in the Annex monad and the Command
- being run. -}
parseCmd :: [String] -> String -> [Command] -> [Option] -> Annex (Command, [Annex Bool])
parseCmd argv header cmds options = do
(flags, params) <- liftIO getopt
when (null params) $ error $ "missing command" ++ usagemsg
let (c:rest) = params
case lookupCmd c of
[] -> error $ "unknown command " ++ c ++ " " ++ usagemsg
[cmd] -> do
_ <- sequence flags
checkCommand cmd
as <- prepCommand cmd rest
return (cmd, as)
_ -> error $ "internal error: multiple matching commands for " ++ c
where where
getopt = case getOpt Permute options argv of (flags, cmd, params) = parseCmd args cmds options header
(flags, params, []) ->
return (flags, params) {- Parses command line, and returns actions to run to configure flags,
(_, _, errs) -> - the Command being run, and the remaining parameters for the command. -}
ioError (userError (concat errs ++ usagemsg)) parseCmd :: Params -> [Command] -> [Option] -> String -> (Flags, Command, Params)
lookupCmd cmd = filter (\c -> cmd == cmdname c) cmds parseCmd argv cmds options header = check $ getOpt Permute options argv
usagemsg = "\n\n" ++ usage header cmds options where
check (_, [], []) = err "missing command"
check (flags, name:rest, [])
| null matches = err $ "unknown command " ++ name
| otherwise = (flags, head matches, rest)
where
matches = filter (\c -> name == cmdname c) cmds
check (_, _, errs) = err $ concat errs
err msg = error $ msg ++ "\n\n" ++ usage header cmds options
{- Usage message with lists of commands and options. -} {- Usage message with lists of commands and options. -}
usage :: String -> [Command] -> [Option] -> String usage :: String -> [Command] -> [Option] -> String
usage header cmds options = usage header cmds options = usageInfo top options ++ commands
usageInfo (header ++ "\n\nOptions:") options ++
"\nCommands:\n" ++ cmddescs
where where
top = header ++ "\n\nOptions:"
commands = "\nCommands:\n" ++ cmddescs
cmddescs = unlines $ map (indent . showcmd) cmds cmddescs = unlines $ map (indent . showcmd) cmds
showcmd c = showcmd c =
cmdname c ++ cmdname c ++
@ -73,23 +69,23 @@ usage header cmds options =
{- Runs a list of Annex actions. Catches IO errors and continues {- Runs a list of Annex actions. Catches IO errors and continues
- (but explicitly thrown errors terminate the whole command). - (but explicitly thrown errors terminate the whole command).
-} -}
tryRun :: Annex.AnnexState -> Command -> [Annex Bool] -> IO () tryRun :: Annex.AnnexState -> Command -> [CommandCleanup] -> IO ()
tryRun = tryRun' 0 tryRun = tryRun' 0
tryRun' :: Integer -> Annex.AnnexState -> Command -> [Annex Bool] -> IO () tryRun' :: Integer -> Annex.AnnexState -> Command -> [CommandCleanup] -> IO ()
tryRun' errnum state cmd (a:as) = do tryRun' errnum _ cmd []
result <- try $ Annex.run state $ do | errnum > 0 = error $ cmdname cmd ++ ": " ++ show errnum ++ " failed"
Annex.Queue.flushWhenFull | otherwise = return ()
a tryRun' errnum state cmd (a:as) = run >>= handle
case result of where
Left err -> do run = try $ Annex.run state $ do
Annex.eval state $ do Annex.Queue.flushWhenFull
showErr err a
showEndFail handle (Left err) = showerr err >> cont False state
tryRun' (errnum + 1) state cmd as handle (Right (success, state')) = cont success state'
Right (True,state') -> tryRun' errnum state' cmd as cont success s = tryRun' (if success then errnum else errnum + 1) s cmd as
Right (False,state') -> tryRun' (errnum + 1) state' cmd as showerr err = Annex.eval state $ do
tryRun' errnum _ cmd [] = when (errnum > 0) $ showErr err
error $ cmdname cmd ++ ": " ++ show errnum ++ " failed" showEndFail
{- Actions to perform each time ran. -} {- Actions to perform each time ran. -}
startup :: Annex Bool startup :: Annex Bool

View file

@ -46,25 +46,24 @@ next a = return $ Just a
stop :: Annex (Maybe a) stop :: Annex (Maybe a)
stop = return Nothing stop = return Nothing
{- Prepares a list of actions to run to perform a command, based on {- Prepares to run a command via the check and seek stages, returning a
- the parameters passed to it. -} - list of actions to perform to run the command. -}
prepCommand :: Command -> [String] -> Annex [Annex Bool] prepCommand :: Command -> [String] -> Annex [CommandCleanup]
prepCommand cmd ps = return . map doCommand =<< seekCommand cmd ps prepCommand Command { cmdseek = seek, cmdcheck = c } params = do
sequence_ $ map runCheck c
{- Runs a command through the seek stage. -} map doCommand . concat <$> mapM (\s -> s params) seek
seekCommand :: Command -> [String] -> Annex [CommandStart]
seekCommand Command { cmdseek = seek } ps = concat <$> mapM (\s -> s ps) seek
{- Runs a command through the start, perform and cleanup stages -} {- Runs a command through the start, perform and cleanup stages -}
doCommand :: CommandStart -> CommandCleanup doCommand :: CommandStart -> CommandCleanup
doCommand = start doCommand = start
where where
start = stage $ maybe success perform start = stage $ maybe skip perform
perform = stage $ maybe failure cleanup perform = stage $ maybe failure cleanup
cleanup = stage $ \r -> showEndResult r >> return r cleanup = stage $ status
stage = (=<<) stage = (=<<)
success = return True skip = return True
failure = showEndFail >> return False failure = showEndFail >> return False
status r = showEndResult r >> return r
notAnnexed :: FilePath -> Annex (Maybe a) -> Annex (Maybe a) notAnnexed :: FilePath -> Annex (Maybe a) -> Annex (Maybe a)
notAnnexed file a = maybe a (const $ return Nothing) =<< Backend.lookupFile file notAnnexed file a = maybe a (const $ return Nothing) =<< Backend.lookupFile file