better option handling

multiple-file support for all modes
This commit is contained in:
Joey Hess 2010-10-10 21:00:42 -04:00
parent 344f13394f
commit 200bc6fdb8
3 changed files with 51 additions and 35 deletions

View file

@ -25,15 +25,14 @@ startAnnex = do
- the annex directory and setting up the symlink pointing to its content. -}
annexFile :: State -> FilePath -> IO ()
annexFile state file = do
checkExists file
checkLegal file
alreadyannexed <- lookupBackend (backends state) (repo state) file
case (alreadyannexed) of
Just _ -> error $ "already annexed " ++ file
Just _ -> error $ "already annexed: " ++ file
Nothing -> do
checkLegal file
stored <- storeFile (backends state) (repo state) file
case (stored) of
Nothing -> error $ "no backend could store " ++ file
Nothing -> error $ "no backend could store: " ++ file
Just key -> symlink key
where
symlink key = do
@ -42,11 +41,6 @@ annexFile state file = do
renameFile file dest
createSymbolicLink dest file
gitAdd (repo state) file
checkExists file = do
exists <- doesFileExist file
if (not exists)
then error $ "does not exist: " ++ file
else return ()
checkLegal file = do
s <- getSymbolicLinkStatus file
if ((isSymbolicLink s) || (not $ isRegularFile s))

View file

@ -10,34 +10,35 @@ import System.Console.GetOpt
import Types
import Annex
data Flag = Add FilePath | Push String | Pull String | Want FilePath |
Get (Maybe FilePath) | Drop FilePath | Unannex FilePath
data Mode = Add | Push | Pull | Want | Get | Drop | Unannex
deriving Show
options :: [OptDescr Flag]
options :: [OptDescr Mode]
options =
[ Option ['a'] ["add"] (ReqArg Add "FILE") "add file to annex"
, Option ['p'] ["push"] (ReqArg Push "REPO") "push annex to repo"
, Option ['P'] ["pull"] (ReqArg Pull "REPO") "pull annex from repo"
, Option ['w'] ["want"] (ReqArg Want "FILE") "request file contents"
, Option ['g'] ["get"] (OptArg Get "FILE") "transfer file contents"
, Option ['d'] ["drop"] (ReqArg Drop "FILE") "indicate file content not needed"
, Option ['u'] ["unannex"] (ReqArg Unannex "FILE") "undo --add"
[ Option ['a'] ["add"] (NoArg Add) "add files to annex"
, Option ['p'] ["push"] (NoArg Push) "push annex to repos"
, Option ['P'] ["pull"] (NoArg Pull) "pull annex from repos"
, Option ['w'] ["want"] (NoArg Want) "request file contents"
, Option ['g'] ["get"] (NoArg Get) "transfer file contents"
, Option ['d'] ["drop"] (NoArg Drop) "indicate file contents not needed"
, Option ['u'] ["unannex"] (NoArg Unannex) "undo --add"
]
argvToFlags argv = do
argvToMode argv = do
case getOpt Permute options argv of
-- no options? add listed files
([],p,[] ) -> return $ map (\f -> Add f) p
-- all options parsed, return flags
(o,[],[] ) -> return o
-- default mode is Add
([],files,[]) -> return (Add, files)
-- one mode is normal case
(m:[],files,[]) -> return (m, files)
-- multiple modes is an error
(ms,files,[]) -> ioError (userError ("only one mode should be specified\n" ++ usageInfo header options))
-- error case
(_,n,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: git-annex [option] file"
(_,files,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: git-annex [mode] file"
dispatch :: Flag -> State -> IO ()
dispatch flag state = do
case (flag) of
Add f -> annexFile state f
Unannex f -> unannexFile state f
dispatch :: State -> Mode -> FilePath -> IO ()
dispatch state mode file = do
case (mode) of
Add -> annexFile state file
Unannex -> unannexFile state file
_ -> error "not implemented"

View file

@ -1,16 +1,37 @@
{- git-annex main program
- -}
import System.IO
import System.Environment
import GitRepo
import Control.Exception
import CmdLine
import Annex
import BackendList
main = do
args <- getArgs
flags <- argvToFlags args
(mode, files) <- argvToMode args
state <- startAnnex
mapM (\f -> dispatch f state) flags
tryRun 0 $ map (\f -> dispatch state mode f) files
{- Tries to run a series of actions, not stopping if some error out,
- and propigating an overall error status at the end. -}
tryRun errflag [] = do
if (errflag > 0)
then error "unsuccessful"
else return ()
tryRun errflag (a:as) = do
result <- try (a)::IO (Either SomeException ())
case (result) of
Left err -> do
showErr err
tryRun 1 as
Right _ -> tryRun errflag as
{- Exception pretty-printing. -}
showErr :: SomeException -> IO ()
showErr e = do
let err = show e
hPutStrLn stderr $ "git-annex: " ++ err
return ()