diff options
author | Joey Hess <joeyh@joeyh.name> | 2016-02-27 10:55:02 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2016-02-27 10:55:02 -0400 |
commit | 00361f2bf9da7bb8244445eae2bcee5487c809d1 (patch) | |
tree | 5236ede82937a35ae4e2ff94cbc1aa0619c420f6 | |
parent | f684572aef9d12cf0881ce6cfc053a87579182a3 (diff) |
Support --metadata field<number, --metadata field>number etc to match ranges of numeric values.
Similarly (well, for free), support preferred content expressions like
metadata=field<number and metadata=field>number
-rw-r--r-- | Annex/MetaData.hs | 39 | ||||
-rw-r--r-- | Backend/Hash.hs | 2 | ||||
-rw-r--r-- | Limit.hs | 11 | ||||
-rw-r--r-- | Types/MetaData.hs | 22 | ||||
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | doc/git-annex-matching-options.mdwn | 9 | ||||
-rw-r--r-- | doc/git-annex-preferred-content.mdwn | 9 | ||||
-rw-r--r-- | doc/preferred_content.mdwn | 1 |
8 files changed, 67 insertions, 30 deletions
diff --git a/Annex/MetaData.hs b/Annex/MetaData.hs index 1f6a484ff..cc00baca5 100644 --- a/Annex/MetaData.hs +++ b/Annex/MetaData.hs @@ -1,6 +1,6 @@ {- git-annex metadata - - - Copyright 2014 Joey Hess <id@joeyh.name> + - Copyright 2014-2016 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -} @@ -8,6 +8,8 @@ module Annex.MetaData ( genMetaData, dateMetaData, + parseModMeta, + parseMetaDataMatcher, module X ) where @@ -17,6 +19,7 @@ import Types.MetaData as X import Annex.MetaData.StandardFields as X import Logs.MetaData import Annex.CatFile +import Utility.Glob import qualified Data.Set as S import qualified Data.Map as M @@ -53,3 +56,37 @@ dateMetaData mtime old = MetaData $ M.fromList $ filter isnew where isnew (f, _) = S.null (currentMetaDataValues f old) (y, m, _d) = toGregorian $ utctDay mtime + +{- Parses field=value, field+=value, field-=value, field?=value -} +parseModMeta :: String -> Either String ModMeta +parseModMeta p = case lastMaybe f of + Just '+' -> AddMeta <$> mkMetaField f' <*> v + Just '-' -> DelMeta <$> mkMetaField f' <*> v + Just '?' -> MaybeSetMeta <$> mkMetaField f' <*> v + _ -> SetMeta <$> mkMetaField f <*> v + where + (f, sv) = separate (== '=') p + f' = beginning f + v = pure (toMetaValue sv) + +{- Parses field=value, field<value, field<=value, field>value, field>=value -} +parseMetaDataMatcher :: String -> Either String (MetaField, MetaValue -> Bool) +parseMetaDataMatcher p = (,) + <$> mkMetaField f + <*> pure matcher + where + (f, op_v) = break (`elem` "=<>") p + matcher = case op_v of + ('=':v) -> checkglob v + ('<':'=':v) -> checkcmp (<=) v + ('<':v) -> checkcmp (<) v + ('>':'=':v) -> checkcmp (>=) v + ('>':v) -> checkcmp (>) v + _ -> checkglob "" + checkglob v = + let cglob = compileGlob v CaseInsensative + in matchGlob cglob . fromMetaValue + checkcmp cmp v v' = case (doubleval v, doubleval (fromMetaValue v')) of + (Just d, Just d') -> d' `cmp` d + _ -> False + doubleval v = readish v :: Maybe Double diff --git a/Backend/Hash.hs b/Backend/Hash.hs index 2835b5637..6f42cac88 100644 --- a/Backend/Hash.hs +++ b/Backend/Hash.hs @@ -5,7 +5,7 @@ - Licensed under the GNU GPL version 3 or higher. -} -{-# LANGUAGE CPP, BangPatterns #-} +{-# LANGUAGE CPP #-} module Backend.Hash ( backends, @@ -23,6 +23,7 @@ import Types.TrustLevel import Types.Group import Types.FileMatcher import Types.MetaData +import Annex.MetaData import Logs.MetaData import Logs.Group import Logs.Unused @@ -278,14 +279,12 @@ addMetaData :: String -> Annex () addMetaData = addLimit . limitMetaData limitMetaData :: MkLimit Annex -limitMetaData s = case parseMetaData s of +limitMetaData s = case parseMetaDataMatcher s of Left e -> Left e - Right (f, v) -> - let cglob = compileGlob (fromMetaValue v) CaseInsensative - in Right $ const $ checkKey (check f cglob) + Right (f, matching) -> Right $ const $ checkKey (check f matching) where - check f cglob k = not . S.null - . S.filter (matchGlob cglob . fromMetaValue) + check f matching k = not . S.null + . S.filter matching . metaDataValues f <$> getCurrentMetaData k addTimeLimit :: String -> Annex () diff --git a/Types/MetaData.hs b/Types/MetaData.hs index cf2811b22..976f37e46 100644 --- a/Types/MetaData.hs +++ b/Types/MetaData.hs @@ -36,8 +36,6 @@ module Types.MetaData ( metaDataValues, ModMeta(..), modMeta, - parseModMeta, - parseMetaData, prop_metadata_sane, prop_metadata_serialize ) where @@ -239,26 +237,6 @@ modMeta m (MaybeSetMeta f v) | S.null (currentMetaDataValues f m) = updateMetaData f v emptyMetaData | otherwise = emptyMetaData -{- Parses field=value, field+=value, field-=value, field?=value -} -parseModMeta :: String -> Either String ModMeta -parseModMeta p = case lastMaybe f of - Just '+' -> AddMeta <$> mkMetaField f' <*> v - Just '-' -> DelMeta <$> mkMetaField f' <*> v - Just '?' -> MaybeSetMeta <$> mkMetaField f' <*> v - _ -> SetMeta <$> mkMetaField f <*> v - where - (f, sv) = separate (== '=') p - f' = beginning f - v = pure (toMetaValue sv) - -{- Parses field=value -} -parseMetaData :: String -> Either String (MetaField, MetaValue) -parseMetaData p = (,) - <$> mkMetaField f - <*> pure (toMetaValue v) - where - (f, v) = separate (== '=') p - {- Avoid putting too many fields in the map; extremely large maps make - the seriaization test slow due to the sheer amount of data. - It's unlikely that more than 100 fields of metadata will be used. -} diff --git a/debian/changelog b/debian/changelog index 207c1feee..7c97d97bf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,10 @@ git-annex (6.20160218) UNRELEASED; urgency=medium * Fix memory leak when hashing files, which triggered during fsck when an external hash program was not used. (This leak was introduced in version 6.20160114.) + * Support --metadata field<number, --metadata field>number etc + to match ranges of numeric values. + * Similarly, support preferred content expressions like + metadata=field<number and metadata=field>number -- Joey Hess <id@joeyh.name> Thu, 18 Feb 2016 13:09:21 -0400 diff --git a/doc/git-annex-matching-options.mdwn b/doc/git-annex-matching-options.mdwn index 34cc05c6a..d94c0faf1 100644 --- a/doc/git-annex-matching-options.mdwn +++ b/doc/git-annex-matching-options.mdwn @@ -115,6 +115,15 @@ file contents are present at either of two repositories. matches the glob. The values of metadata fields are matched case insensitively. +* `--metadata field<number` / `--metadata field>number` +* `--metadata field<=number` / `--metadata field>=number` + + Matches only files that have a metadata field attached with a value that + is a number and is less than or greater than the specified number. + + (Note that you will need to quote the second parameter to avoid + the shell doing redirection.) + * `--want-get` Matches files that the preferred content settings for the repository diff --git a/doc/git-annex-preferred-content.mdwn b/doc/git-annex-preferred-content.mdwn index bea82654f..5e2a7a9c5 100644 --- a/doc/git-annex-preferred-content.mdwn +++ b/doc/git-annex-preferred-content.mdwn @@ -119,6 +119,15 @@ elsewhere to allow removing it). To match author metadata, use `metadata=author=*Smith` +* `metadata=field<number` / `metadata=field>number` +* `metadata=field<=number` / `metadata=field>=number` + + Matches only files that have a metadata field attached with a value that + is a number and is less than or greater than the specified number. + + To match PDFs with between 100 and 200 pages (assuming something has set + that metadata), use `metadata=pagecount>=100 and metadata=pagecount<=200` + * `present` Makes content be wanted if it's present, but not otherwise. diff --git a/doc/preferred_content.mdwn b/doc/preferred_content.mdwn index f8c6ce6cd..d7b9870e5 100644 --- a/doc/preferred_content.mdwn +++ b/doc/preferred_content.mdwn @@ -67,3 +67,4 @@ they were added in. * "metadata=" 5.20140221 * "lackingcopies=", "approxlackingcopies=", "unused=" 5.20140127 * "inpreferreddir=" 4.20130501 +* "metadata=field<number" etc 6.20160227 |