Add --exclude option to exclude files from processing.

Required some lifting so flags are evaled in the Annex monad before
file filtering.
This commit is contained in:
Joey Hess 2010-12-08 14:07:49 -04:00
parent 627a301437
commit 2099407d8a
5 changed files with 57 additions and 27 deletions

View file

@ -9,6 +9,7 @@ module CmdLine (parseCmd) where
import System.Console.GetOpt import System.Console.GetOpt
import Control.Monad (when) import Control.Monad (when)
import Control.Monad.State (liftIO)
import qualified Annex import qualified Annex
import Types import Types
@ -103,6 +104,8 @@ options = [
"specify to where to transfer content" "specify to where to transfer content"
, Option ['f'] ["from"] (ReqArg (storestring "fromrepository") "REPOSITORY") , Option ['f'] ["from"] (ReqArg (storestring "fromrepository") "REPOSITORY")
"specify from where to transfer content" "specify from where to transfer content"
, Option ['x'] ["exclude"] (ReqArg (storestring "exclude") "GLOB")
"skip files matching the glob pattern"
] ]
where where
storebool n b = Annex.flagChange n $ FlagBool b storebool n b = Annex.flagChange n $ FlagBool b
@ -125,22 +128,17 @@ usage = usageInfo header options ++ "\nSubcommands:\n" ++ cmddescs
indent l = " " ++ l indent l = " " ++ l
pad n s = replicate (n - length s) ' ' pad n s = replicate (n - length s) ' '
{- Parses command line and returns two lists of actions to be {- Parses command line, stores configure flags, and returns a
- run in the Annex monad. The first actions configure it - list of actions to be run in the Annex monad. -}
- according to command line options, while the second actions parseCmd :: [String] -> Annex [Annex Bool]
- handle subcommands. -} parseCmd argv = do
parseCmd :: [String] -> AnnexState -> IO ([Annex Bool], [Annex Bool]) (flags, params) <- liftIO $ getopt
parseCmd argv state = do
(flags, params) <- getopt
when (null params) $ error usage when (null params) $ error usage
case lookupCmd (head params) of case lookupCmd (head params) of
[] -> error usage [] -> error usage
[subcommand] -> do [subcommand] -> do
actions <- prepSubCmd subcommand state (drop 1 params) _ <- sequence flags
let configactions = map (\flag -> do prepSubCmd subcommand (drop 1 params)
flag
return True) flags
return (configactions, actions)
_ -> error "internal error: multiple matching subcommands" _ -> error "internal error: multiple matching subcommands"
where where
getopt = case getOpt Permute options argv of getopt = case getOpt Permute options argv of

View file

@ -11,6 +11,8 @@ import Control.Monad.State (liftIO)
import System.Directory import System.Directory
import System.Posix.Files import System.Posix.Files
import Control.Monad (filterM) import Control.Monad (filterM)
import System.Path.WildMatch
import Text.Regex
import Types import Types
import qualified Backend import qualified Backend
@ -59,9 +61,9 @@ data SubCommand = SubCommand {
{- Prepares a list of actions to run to perform a subcommand, based on {- Prepares a list of actions to run to perform a subcommand, based on
- the parameters passed to it. -} - the parameters passed to it. -}
prepSubCmd :: SubCommand -> AnnexState -> [String] -> IO [Annex Bool] prepSubCmd :: SubCommand -> [String] -> Annex [Annex Bool]
prepSubCmd SubCommand { subcmdseek = seek } state params = do prepSubCmd SubCommand { subcmdseek = seek } params = do
lists <- Annex.eval state $ mapM (\s -> s params) seek lists <- mapM (\s -> s params) seek
return $ map doSubCmd $ foldl (++) [] lists return $ map doSubCmd $ foldl (++) [] lists
{- Runs a subcommand through the start, perform and cleanup stages -} {- Runs a subcommand through the start, perform and cleanup stages -}
@ -106,18 +108,20 @@ withFilesInGit :: SubCmdSeekStrings
withFilesInGit a params = do withFilesInGit a params = do
repo <- Annex.gitRepo repo <- Annex.gitRepo
files <- liftIO $ mapM (Git.inRepo repo) params files <- liftIO $ mapM (Git.inRepo repo) params
return $ map a $ filter notState $ foldl (++) [] files files' <- filterFiles $ foldl (++) [] files
return $ map a files'
withAttrFilesInGit :: String -> SubCmdSeekAttrFiles withAttrFilesInGit :: String -> SubCmdSeekAttrFiles
withAttrFilesInGit attr a params = do withAttrFilesInGit attr a params = do
repo <- Annex.gitRepo repo <- Annex.gitRepo
files <- liftIO $ mapM (Git.inRepo repo) params files <- liftIO $ mapM (Git.inRepo repo) params
pairs <- liftIO $ Git.checkAttr repo attr $ files' <- filterFiles $ foldl (++) [] files
filter notState $ foldl (++) [] files pairs <- liftIO $ Git.checkAttr repo attr files'
return $ map a pairs return $ map a pairs
withFilesMissing :: SubCmdSeekStrings withFilesMissing :: SubCmdSeekStrings
withFilesMissing a params = do withFilesMissing a params = do
files <- liftIO $ filterM missing params files <- liftIO $ filterM missing params
return $ map a $ filter notState files files' <- filterFiles files
return $ map a files'
where where
missing f = do missing f = do
e <- doesFileExist f e <- doesFileExist f
@ -126,7 +130,8 @@ withFilesNotInGit :: SubCmdSeekBackendFiles
withFilesNotInGit a params = do withFilesNotInGit a params = do
repo <- Annex.gitRepo repo <- Annex.gitRepo
newfiles <- liftIO $ mapM (Git.notInRepo repo) params newfiles <- liftIO $ mapM (Git.notInRepo repo) params
backendPairs a $ filter notState $ foldl (++) [] newfiles newfiles' <- filterFiles $ foldl (++) [] newfiles
backendPairs a newfiles'
withString :: SubCmdSeekStrings withString :: SubCmdSeekStrings
withString a params = return [a $ unwords params] withString a params = return [a $ unwords params]
withStrings :: SubCmdSeekStrings withStrings :: SubCmdSeekStrings
@ -135,7 +140,8 @@ withFilesToBeCommitted :: SubCmdSeekStrings
withFilesToBeCommitted a params = do withFilesToBeCommitted a params = do
repo <- Annex.gitRepo repo <- Annex.gitRepo
tocommit <- liftIO $ mapM (Git.stagedFiles repo) params tocommit <- liftIO $ mapM (Git.stagedFiles repo) params
return $ map a $ filter notState $ foldl (++) [] tocommit tocommit' <- filterFiles $ foldl (++) [] tocommit
return $ map a tocommit'
withFilesUnlocked :: SubCmdSeekBackendFiles withFilesUnlocked :: SubCmdSeekBackendFiles
withFilesUnlocked = withFilesUnlocked' Git.typeChangedFiles withFilesUnlocked = withFilesUnlocked' Git.typeChangedFiles
withFilesUnlockedToBeCommitted :: SubCmdSeekBackendFiles withFilesUnlockedToBeCommitted :: SubCmdSeekBackendFiles
@ -146,7 +152,8 @@ withFilesUnlocked' typechanged a params = do
repo <- Annex.gitRepo repo <- Annex.gitRepo
typechangedfiles <- liftIO $ mapM (typechanged repo) params typechangedfiles <- liftIO $ mapM (typechanged repo) params
unlockedfiles <- liftIO $ filterM notSymlink $ foldl (++) [] typechangedfiles unlockedfiles <- liftIO $ filterM notSymlink $ foldl (++) [] typechangedfiles
backendPairs a $ filter notState unlockedfiles unlockedfiles' <- filterFiles unlockedfiles
backendPairs a unlockedfiles'
withKeys :: SubCmdSeekStrings withKeys :: SubCmdSeekStrings
withKeys a params = return $ map a params withKeys a params = return $ map a params
withTempFile :: SubCmdSeekStrings withTempFile :: SubCmdSeekStrings
@ -173,9 +180,23 @@ withDefault :: String-> (a -> SubCmdSeek) -> (a -> SubCmdSeek)
withDefault d w a [] = w a [d] withDefault d w a [] = w a [d]
withDefault _ w a p = w a p withDefault _ w a p = w a p
{- filter out files from the state directory -} {- Filter out files from the state directory, and those matching the
notState :: FilePath -> Bool - exclude glob pattern, if it was specified. -}
notState f = stateLoc /= take (length stateLoc) f filterFiles :: [FilePath] -> Annex [FilePath]
filterFiles l = do
let l' = filter notState l
exclude <- Annex.flagGet "exclude"
if null exclude
then return l'
else do
let regexp = mkRegex $ "^" ++ wildToRegex exclude
return $ filter (notExcluded regexp) l'
where
notState f = stateLoc /= take stateLocLen f
stateLocLen = length stateLoc
notExcluded r f = case matchRegex r f of
Nothing -> True
Just _ -> False
{- filter out symlinks -} {- filter out symlinks -}
notSymlink :: FilePath -> IO Bool notSymlink :: FilePath -> IO Bool

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
git-annex (0.12) UNRELEASED; urgency=low
* Add --exclude option to exclude files from processing.
-- Joey Hess <joeyh@debian.org> Wed, 08 Dec 2010 14:06:47 -0400
git-annex (0.11) unstable; urgency=low git-annex (0.11) unstable; urgency=low
* If available, rsync will be used for file transfers from remote * If available, rsync will be used for file transfers from remote

View file

@ -234,6 +234,11 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
Specifies a git repository that content will be sent to. Specifies a git repository that content will be sent to.
It should be specified using the name of a configured git remote. It should be specified using the name of a configured git remote.
* --exclude=glob
Skips files matching the glob pattern. The glob is matched relative to
the current directory.
* --backend=name * --backend=name
Specifies which key-value backend to use. Specifies which key-value backend to use.

View file

@ -19,5 +19,5 @@ main = do
args <- getArgs args <- getArgs
gitrepo <- Git.repoFromCwd gitrepo <- Git.repoFromCwd
state <- Annex.new gitrepo allBackends state <- Annex.new gitrepo allBackends
(configure, actions) <- parseCmd args state (actions, state') <- Annex.run state $ parseCmd args
tryRun state $ [startup, upgrade] ++ configure ++ actions tryRun state' $ [startup, upgrade] ++ actions