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
This commit is contained in:
parent
01f1de0c3c
commit
b946ca44c3
8 changed files with 67 additions and 30 deletions
|
@ -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
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- Licensed under the GNU GPL version 3 or higher.
|
||||
-}
|
||||
|
||||
{-# LANGUAGE CPP, BangPatterns #-}
|
||||
{-# LANGUAGE CPP #-}
|
||||
|
||||
module Backend.Hash (
|
||||
backends,
|
||||
|
|
11
Limit.hs
11
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 ()
|
||||
|
|
|
@ -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. -}
|
||||
|
|
4
debian/changelog
vendored
4
debian/changelog
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue