This commit is contained in:
Joey Hess 2010-10-14 14:38:29 -04:00
parent 65e4f9cc73
commit 90cdc61c7c
5 changed files with 86 additions and 101 deletions

View file

@ -1,52 +0,0 @@
{- git-annex command line
-
- TODO: This is very rough and stupid; I would like to use
- System.Console.CmdArgs.Implicit but it is not yet packaged in Debian.
-}
module CmdLine (
argvToMode,
dispatch,
Mode
) where
import System.Console.GetOpt
import Types
import Commands
data Mode = Default | Add | Push | Pull | Want | Get | Drop | Unannex
deriving Show
options :: [OptDescr Mode]
options =
[ 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"
]
argvToMode argv = do
case getOpt Permute options argv of
([],files,[]) -> return (Default, 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
(_,files,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: git-annex [mode] file"
dispatch :: Mode -> FilePath -> Annex ()
dispatch mode item = do
case (mode) of
Default -> defaultCmd item
Add -> addCmd item
Push -> pushCmd item
Pull -> pullCmd item
Want -> wantCmd item
Get -> getCmd item
Drop -> dropCmd item
Unannex -> unannexCmd item

View file

@ -1,16 +1,12 @@
{- git-annex subcommands -}
{- git-annex command line -}
module Commands (
defaultCmd,
addCmd,
unannexCmd,
getCmd,
wantCmd,
dropCmd,
pushCmd,
pullCmd
argvToMode,
dispatch,
Mode
) where
import System.Console.GetOpt
import Control.Monad.State (liftIO)
import System.Posix.Files
import System.Directory
@ -25,6 +21,44 @@ import BackendList
import UUID
import LocationLog
import Types
import Core
data Mode = Default | Add | Push | Pull | Want | Get | Drop | Unannex
deriving Show
options :: [OptDescr Mode]
options =
[ 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"
]
argvToMode argv = do
case getOpt Permute options argv of
([],files,[]) -> return (Default, 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
(_,files,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: git-annex [mode] file"
dispatch :: Mode -> FilePath -> Annex ()
dispatch mode item = do
case (mode) of
Default -> defaultCmd item
Add -> addCmd item
Push -> pushCmd item
Pull -> pullCmd item
Want -> wantCmd item
Get -> getCmd item
Drop -> dropCmd item
Unannex -> unannexCmd item
{- Default mode is to annex a file if it is not already, and otherwise
- get its content. -}
@ -163,9 +197,3 @@ inBackend file yes no = do
Just v -> yes v
Nothing -> no
notinBackend file yes no = inBackend file no yes
{- Checks if a given key is currently present in the annexLocation -}
inAnnex :: Backend -> Key -> Annex Bool
inAnnex backend key = do
g <- Annex.gitRepo
liftIO $ doesFileExist $ annexLocation g backend key

37
Core.hs
View file

@ -5,8 +5,6 @@ module Core where
import System.IO
import System.Directory
import Control.Monad.State (liftIO)
import Control.Exception
import CmdLine
import Types
import BackendList
import Locations
@ -33,35 +31,6 @@ start = do
Git.configGet g' "annex.backends" ""
prepUUID
{- Processes each param in the list by dispatching the handler function
- for the user-selection operation mode. Catches exceptions, not stopping
- if some error out, and propigates an overall error status at the end.
-
- This runs in the IO monad, not in the Annex monad. It seems that
- exceptions can only be caught in the IO monad, not in a stacked monad;
- or more likely I missed an easy way to do it. So, I have to laboriously
- thread AnnexState through this function.
-}
tryRun :: AnnexState -> Mode -> [String] -> IO ()
tryRun state mode params = tryRun' state mode 0 0 params
tryRun' state mode errnum oknum [] = do
if (errnum > 0)
then error $ (show errnum) ++ " failed ; " ++ show (oknum) ++ " ok"
else return ()
tryRun' state mode errnum oknum (f:fs) = do
result <- try
(Annex.run state (dispatch mode f))::IO (Either SomeException ((), AnnexState))
case (result) of
Left err -> do
showErr err
tryRun' state mode (errnum + 1) oknum fs
Right (_,state') -> tryRun' state' mode errnum (oknum + 1) fs
{- Exception pretty-printing. -}
showErr e = do
hPutStrLn stderr $ "git-annex: " ++ (show e)
return ()
{- Sets up a git repo for git-annex. May be called repeatedly. -}
gitSetup :: Git.Repo -> IO ()
gitSetup repo = do
@ -85,3 +54,9 @@ gitSetup repo = do
Git.run repo ["add", attributes]
Git.run repo ["commit", "-m", "git-annex setup",
attributes]
{- Checks if a given key is currently present in the annexLocation -}
inAnnex :: Backend -> Key -> Annex Bool
inAnnex backend key = do
g <- Annex.gitRepo
liftIO $ doesFileExist $ annexLocation g backend key

View file

@ -1,12 +1,44 @@
{- git-annex main program -}
import Control.Exception
import System.IO
import System.Environment
import qualified Annex
import Types
import Core
import CmdLine
import Commands
main = do
args <- getArgs
(mode, params) <- argvToMode args
state <- start
tryRun state mode params
{- Processes each param in the list by dispatching the handler function
- for the user-selection operation mode. Catches exceptions, not stopping
- if some error out, and propigates an overall error status at the end.
-
- This runs in the IO monad, not in the Annex monad. It seems that
- exceptions can only be caught in the IO monad, not in a stacked monad;
- or more likely I missed an easy way to do it. So, I have to laboriously
- thread AnnexState through this function.
-}
tryRun :: AnnexState -> Mode -> [String] -> IO ()
tryRun state mode params = tryRun' state mode 0 0 params
tryRun' state mode errnum oknum (f:fs) = do
result <- try
(Annex.run state (dispatch mode f))::IO (Either SomeException ((), AnnexState))
case (result) of
Left err -> do
showErr err
tryRun' state mode (errnum + 1) oknum fs
Right (_,state') -> tryRun' state' mode errnum (oknum + 1) fs
tryRun' state mode errnum oknum [] = do
if (errnum > 0)
then error $ (show errnum) ++ " failed ; " ++ show (oknum) ++ " ok"
else return ()
{- Exception pretty-printing. -}
showErr e = do
hPutStrLn stderr $ "git-annex: " ++ (show e)
return ()

View file

@ -48,9 +48,11 @@ git-annex can be configured to try to keep N copies of a file's content
available across all repositories. By default, N is 1 (configured by
annex.numcopies).
`git annex --drop` attempts to communicate with all other configured
`git annex --drop` attempts to check all other configured
repositories, to check that N copies of the file exist. If enough
repositories cannot be contacted, it will retain the file content.
repositories cannot be verified to have it, it will retain the file content
to avoid data loss.
You can later use `git annex --drop --retry` to retry pending drops.
Or you can use `git annex --drop --force $file` to force dropping of
file content.