add --ingroup limit

This commit is contained in:
Joey Hess 2012-10-08 15:18:58 -04:00
parent 7cd81bd978
commit e375b931c0
8 changed files with 65 additions and 20 deletions

View file

@ -147,9 +147,11 @@ options = Option.common ++
"skip files with fewer copies" "skip files with fewer copies"
, Option ['B'] ["inbackend"] (ReqArg Limit.addInBackend paramName) , Option ['B'] ["inbackend"] (ReqArg Limit.addInBackend paramName)
"skip files not using a key-value backend" "skip files not using a key-value backend"
, Option [] ["largerthan"] (ReqArg Limit.addLargerThan paramName) , Option [] ["ingroup"] (ReqArg Limit.addInGroup paramGroup)
"skip files not present in all remotes in a group"
, Option [] ["largerthan"] (ReqArg Limit.addLargerThan paramSize)
"skip files larger than a size" "skip files larger than a size"
, Option [] ["smallerthan"] (ReqArg Limit.addSmallerThan paramName) , Option [] ["smallerthan"] (ReqArg Limit.addSmallerThan paramSize)
"skip files smaller than a size" "skip files smaller than a size"
, Option ['T'] ["time-limit"] (ReqArg Limit.addTimeLimit paramTime) , Option ['T'] ["time-limit"] (ReqArg Limit.addTimeLimit paramTime)
"stop after the specified amount of time" "stop after the specified amount of time"

View file

@ -11,6 +11,7 @@ import Text.Regex.PCRE.Light.Char8
import System.Path.WildMatch import System.Path.WildMatch
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import qualified Data.Set as S import qualified Data.Set as S
import qualified Data.Map as M
import Common.Annex import Common.Annex
import qualified Annex import qualified Annex
@ -22,6 +23,7 @@ import Annex.UUID
import Logs.Trust import Logs.Trust
import Types.TrustLevel import Types.TrustLevel
import Types.Key import Types.Key
import Types.Group
import Logs.Group import Logs.Group
import Utility.HumanTime import Utility.HumanTime
import Utility.DataUnits import Utility.DataUnits
@ -135,6 +137,28 @@ limitCopies want = case split ":" want of
checktrust t u = (== t) <$> lookupTrust u checktrust t u = (== t) <$> lookupTrust u
checkgroup g u = S.member g <$> lookupGroups u checkgroup g u = S.member g <$> lookupGroups u
{- Adds a limit to skip files not believed to be present in all
- repositories in the specified group. -}
addInGroup :: String -> Annex ()
addInGroup groupname = do
m <- groupMap
addLimit $ limitInGroup m groupname
limitInGroup :: GroupMap -> MkLimit
limitInGroup m groupname
| S.null want = Right $ const $ const $ return True
| otherwise = Right $ \notpresent ->
Backend.lookupFile >=> check notpresent
where
want = fromMaybe S.empty $ M.lookup groupname $ uuidsByGroup m
check _ Nothing = return False
check notpresent (Just (key, _))
-- optimisation: Check if a wanted uuid is notpresent.
| not (S.null (S.intersection want notpresent)) = return False
| otherwise = do
present <- S.fromList <$> Remote.keyLocations key
return $ S.null $ want `S.difference` present
{- Adds a limit to skip files not using a specified key-value backend. -} {- Adds a limit to skip files not using a specified key-value backend. -}
addInBackend :: String -> Annex () addInBackend :: String -> Annex ()
addInBackend = addLimit . limitInBackend addInBackend = addLimit . limitInBackend

View file

@ -25,6 +25,8 @@ import Limit
import qualified Utility.Matcher import qualified Utility.Matcher
import Annex.UUID import Annex.UUID
import Git.FilePath import Git.FilePath
import Types.Group
import Logs.Group
{- Filename of preferred-content.log. -} {- Filename of preferred-content.log. -}
preferredContentLog :: FilePath preferredContentLog :: FilePath
@ -54,11 +56,12 @@ isPreferredContent mu notpresent file = do
{- Read the preferredContentLog into a map. The map is cached for speed. -} {- Read the preferredContentLog into a map. The map is cached for speed. -}
preferredContentMap :: Annex Annex.PreferredContentMap preferredContentMap :: Annex Annex.PreferredContentMap
preferredContentMap = do preferredContentMap = do
groupmap <- groupMap
cached <- Annex.getState Annex.preferredcontentmap cached <- Annex.getState Annex.preferredcontentmap
case cached of case cached of
Just m -> return m Just m -> return m
Nothing -> do Nothing -> do
m <- simpleMap . parseLog (Just . makeMatcher) m <- simpleMap . parseLog (Just . makeMatcher groupmap)
<$> Annex.Branch.get preferredContentLog <$> Annex.Branch.get preferredContentLog
Annex.changeState $ \s -> s { Annex.preferredcontentmap = Just m } Annex.changeState $ \s -> s { Annex.preferredcontentmap = Just m }
return m return m
@ -71,21 +74,22 @@ preferredContentMapRaw = simpleMap . parseLog Just
- because the configuration is shared amoung repositories and newer - because the configuration is shared amoung repositories and newer
- versions of git-annex may add new features. Instead, parse errors - versions of git-annex may add new features. Instead, parse errors
- result in a Matcher that will always succeed. -} - result in a Matcher that will always succeed. -}
makeMatcher :: String -> Utility.Matcher.Matcher MatchFiles makeMatcher :: GroupMap -> String -> Utility.Matcher.Matcher MatchFiles
makeMatcher s makeMatcher groupmap s
| null (lefts tokens) = Utility.Matcher.generate $ rights tokens | null (lefts tokens) = Utility.Matcher.generate $ rights tokens
| otherwise = Utility.Matcher.generate [] | otherwise = Utility.Matcher.generate []
where where
tokens = map parseToken $ tokenizeMatcher s tokens = map (parseToken groupmap) (tokenizeMatcher s)
{- Checks if an expression can be parsed, if not returns Just error -} {- Checks if an expression can be parsed, if not returns Just error -}
checkPreferredContentExpression :: String -> Maybe String checkPreferredContentExpression :: String -> Maybe String
checkPreferredContentExpression s = case lefts $ map parseToken $ tokenizeMatcher s of checkPreferredContentExpression s =
[] -> Nothing case lefts $ map (parseToken emptyGroupMap) (tokenizeMatcher s) of
l -> Just $ unwords $ map ("Parse failure: " ++) l [] -> Nothing
l -> Just $ unwords $ map ("Parse failure: " ++) l
parseToken :: String -> Either String (Utility.Matcher.Token MatchFiles) parseToken :: GroupMap -> String -> Either String (Utility.Matcher.Token MatchFiles)
parseToken t parseToken groupmap t
| any (== t) Utility.Matcher.tokens = Right $ Utility.Matcher.token t | any (== t) Utility.Matcher.tokens = Right $ Utility.Matcher.token t
| otherwise = maybe (Left $ "near " ++ show t) use $ M.lookup k m | otherwise = maybe (Left $ "near " ++ show t) use $ M.lookup k m
where where
@ -95,9 +99,10 @@ parseToken t
, ("exclude", limitExclude) , ("exclude", limitExclude)
, ("in", limitIn) , ("in", limitIn)
, ("copies", limitCopies) , ("copies", limitCopies)
, ("backend", limitInBackend) , ("inbackend", limitInBackend)
, ("largerthan", limitSize (>)) , ("largerthan", limitSize (>))
, ("smallerthan", limitSize (<)) , ("smallerthan", limitSize (<))
, ("ingroup", limitInGroup groupmap)
] ]
use a = Utility.Matcher.Operation <$> a v use a = Utility.Matcher.Operation <$> a v

View file

@ -7,7 +7,8 @@
module Types.Group ( module Types.Group (
Group, Group,
GroupMap(..) GroupMap(..),
emptyGroupMap
) where ) where
import Types.UUID import Types.UUID
@ -21,3 +22,6 @@ data GroupMap = GroupMap
{ groupsByUUID :: M.Map UUID (S.Set Group) { groupsByUUID :: M.Map UUID (S.Set Group)
, uuidsByGroup :: M.Map Group (S.Set UUID) , uuidsByGroup :: M.Map Group (S.Set UUID)
} }
emptyGroupMap :: GroupMap
emptyGroupMap = GroupMap M.empty M.empty

View file

@ -85,6 +85,8 @@ paramFile :: String
paramFile = "FILE" paramFile = "FILE"
paramGroup :: String paramGroup :: String
paramGroup = "GROUP" paramGroup = "GROUP"
paramSize :: String
paramSize = "SIZE"
paramKeyValue :: String paramKeyValue :: String
paramKeyValue = "K=V" paramKeyValue = "K=V"
paramNothing :: String paramNothing :: String

9
debian/changelog vendored
View file

@ -1,11 +1,10 @@
git-annex (3.20121002) UNRELEASED; urgency=low git-annex (3.20121002) UNRELEASED; urgency=low
* group, ungroup: New commands to indicate groups of repositories. * group, ungroup: New commands to indicate groups of repositories.
* --copies=group:number can now be used to match files that are present
in a specified number of repositories in a group.
* watch, assistant: It's now safe to git annex unlock files while * watch, assistant: It's now safe to git annex unlock files while
the watcher is running, as well as modify files checked into git the watcher is running, as well as modify files checked into git
as normal files. as normal files. Additionally, .gitignore settings are now honored.
Closes: #689979
* vicfg: New command, allows editing (or simply viewing) most * vicfg: New command, allows editing (or simply viewing) most
of the repository configuration settings stored in the git-annex branch. of the repository configuration settings stored in the git-annex branch.
* Added preferred content expressions, configurable using vicfg. * Added preferred content expressions, configurable using vicfg.
@ -13,7 +12,9 @@ git-annex (3.20121002) UNRELEASED; urgency=low
configured, only get that content. configured, only get that content.
* drop --auto: If the local repository has preferred content configured, * drop --auto: If the local repository has preferred content configured,
drop content that is not preferred, when numcopies allows. drop content that is not preferred, when numcopies allows.
* Added --smallerthan and --largerthan limits. * --copies=group:number can now be used to match files that are present
in a specified number of repositories in a group.
* Added --smallerthan, --largerthan, and --inall limits.
* Only build-depend on libghc-clientsession-dev on arches that will have * Only build-depend on libghc-clientsession-dev on arches that will have
the webapp. the webapp.
* uninit: Unset annex.version. Closes: #689852 * uninit: Unset annex.version. Closes: #689852

View file

@ -27,7 +27,7 @@ check if preferred content settings rejects the data, and if so, drop it
from the repo. So once all three laptops have the data, it is from the repo. So once all three laptops have the data, it is
pruned from the transfer drive. pruned from the transfer drive.
## repo groups ## repo groups **done**
Seems like git-annex needs a way to know the groups of repos. Some Seems like git-annex needs a way to know the groups of repos. Some
groups: groups:
@ -53,14 +53,14 @@ Some examples of using groups:
* Make a cloud repo only hold data until all known clients have a copy: * Make a cloud repo only hold data until all known clients have a copy:
`not inall(enduser)` `not ingroup(enduser)`
## configuration ## configuration
The above is all well and good for those who enjoy boolean algebra, but The above is all well and good for those who enjoy boolean algebra, but
how to configure these sorts of expressions in the webapp? how to configure these sorts of expressions in the webapp?
## the state change problem ## the state change problem **done**
Imagine that a trusted repo has setting like `not copies=trusted:2` Imagine that a trusted repo has setting like `not copies=trusted:2`
This means that `git annex get --auto` should get files not in 2 trusted This means that `git annex get --auto` should get files not in 2 trusted
@ -77,3 +77,5 @@ Or, perhaps simulation could be used to detect the problem. Before
dropping, check the expression. Then simulate that the drop has happened. dropping, check the expression. Then simulate that the drop has happened.
Does the expression now make it want to add it? Then don't drop it! Does the expression now make it want to add it? Then don't drop it!
How to implement this simulation? How to implement this simulation?
> Solved, fwiw..

View file

@ -643,6 +643,11 @@ file contents are present at either of two repositories.
Matches only files whose content is stored using the specified key-value Matches only files whose content is stored using the specified key-value
backend. backend.
* --ingroup=groupname
Matches only files that git-annex believes are present in all repositories
in the specified group.
* --smallerthan=size * --smallerthan=size
* --largerthan=size * --largerthan=size