summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2016-02-27 10:55:02 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2016-02-27 10:55:02 -0400
commit00361f2bf9da7bb8244445eae2bcee5487c809d1 (patch)
tree5236ede82937a35ae4e2ff94cbc1aa0619c420f6
parentf684572aef9d12cf0881ce6cfc053a87579182a3 (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.hs39
-rw-r--r--Backend/Hash.hs2
-rw-r--r--Limit.hs11
-rw-r--r--Types/MetaData.hs22
-rw-r--r--debian/changelog4
-rw-r--r--doc/git-annex-matching-options.mdwn9
-rw-r--r--doc/git-annex-preferred-content.mdwn9
-rw-r--r--doc/preferred_content.mdwn1
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,
diff --git a/Limit.hs b/Limit.hs
index 174d4582d..dc38b172d 100644
--- a/Limit.hs
+++ b/Limit.hs
@@ -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&lt;number" etc 6.20160227