Utility.Matcher.matchMrun' matcher $ \o ->
matchAction o NoLiveUpdate S.empty i
explain (mkActionItem i) $ UnquotedString <$>
- Utility.Matcher.describeMatchResult matchDesc desc
+ Utility.Matcher.describeMatchResult
+ (\o -> matchDesc o . Just) desc
(if match then "matches:" else "does not match:")
return match
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "include" =? glob
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "exclude" =? glob
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "includesamecontent" =? glob
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "excludesamecontent" =? glob
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = limitname =? glob
}
where
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "unlocked"
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "locked"
}
, matchNeedsKey = True
, matchNeedsLocationLog = not inhere
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "in" =? s
}
checkinuuid u notpresent key
, matchNeedsKey = True
, matchNeedsLocationLog = True
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = True
, matchDesc = matchDescSimple "expected-present"
}
, matchNeedsKey = True
, matchNeedsLocationLog = not (isNothing u)
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = True
, matchDesc = matchDescSimple "present"
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple desc
}
where
, matchNeedsKey = True
, matchNeedsLocationLog = True
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "copies" =? want
}
go' n good notpresent key = do
, matchNeedsKey = True
, matchNeedsLocationLog = True
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple desc
}
Nothing -> Left "bad value for number of lacking copies"
, matchNeedsKey = True
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "unused"
}
where
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "anything"
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "nothing"
}
, matchNeedsKey = True
, matchNeedsLocationLog = True
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "inallgroup" =? groupname
}
where
, matchNeedsKey = True
, matchNeedsLocationLog = True
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "onlyingroup" =? groupname
}
where
then groupname
else groupname ++ ":1"
let present = limitPresent mu
+ let combo f = f present || f fullybalanced || f copies
Right $ MatchFiles
{ matchAction = \lu a i ->
ifM (Annex.getRead Annex.rebalance)
<&&> matchAction fullybalanced lu a i
)
)
- , matchNeedsFileName =
- matchNeedsFileName present ||
- matchNeedsFileName fullybalanced ||
- matchNeedsFileName copies
- , matchNeedsFileContent =
- matchNeedsFileContent present ||
- matchNeedsFileContent fullybalanced ||
- matchNeedsFileContent copies
- , matchNeedsKey =
- matchNeedsKey present ||
- matchNeedsKey fullybalanced ||
- matchNeedsKey copies
- , matchNeedsLocationLog =
- matchNeedsLocationLog present ||
- matchNeedsLocationLog fullybalanced ||
- matchNeedsLocationLog copies
+ , matchNeedsFileName = combo matchNeedsFileName
+ , matchNeedsFileContent = combo matchNeedsFileContent
+ , matchNeedsKey = combo matchNeedsKey
+ , matchNeedsLocationLog = combo matchNeedsLocationLog
, matchNeedsLiveRepoSize = True
+ , matchNegationUnstable = combo matchNegationUnstable
, matchDesc = termname =? groupname
}
+
limitFullyBalanced :: Maybe UUID -> Annex GroupMap -> MkLimit Annex
limitFullyBalanced = limitFullyBalanced' "fullybalanced"
, matchNeedsKey = True
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = True
+ , matchNegationUnstable = False
, matchDesc = termname =? want
}
, matchNeedsKey = True
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "inbackend" =? name
}
where
, matchNeedsKey = True
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = matchDescSimple "securehash"
}
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = desc =? s
}
where
, matchNeedsKey = True
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "metadata" =? s
}
where
, matchNeedsKey = False
, matchNeedsLocationLog = False
, matchNeedsLiveRepoSize = False
+ , matchNegationUnstable = False
, matchDesc = "accessedwithin" =? fromDuration duration
}
where
checkKey a (MatchingInfo p) = maybe (return False) a (providedKey p)
checkKey a (MatchingUserInfo p) = a =<< getUserInfo (userProvidedKey p)
-matchDescSimple :: String -> (Bool -> Utility.Matcher.MatchDesc)
-matchDescSimple s b = Utility.Matcher.MatchDesc $ s ++
+matchDescSimple :: String -> (Maybe Bool -> Utility.Matcher.MatchDesc)
+matchDescSimple s (Just b) = Utility.Matcher.MatchDesc $ s ++
if b then "[TRUE]" else "[FALSE]"
+matchDescSimple s Nothing = Utility.Matcher.MatchDesc s
-(=?) :: String -> String -> (Bool -> Utility.Matcher.MatchDesc)
+(=?) :: String -> String -> (Maybe Bool -> Utility.Matcher.MatchDesc)
k =? v = matchDescSimple (k ++ "=" ++ v)
of preferred content expressions, or a way to simulate the behavior of a
network of git-annex repositories with a given preferred content configuration
-For example, consider two reposities A and B. A is in group M and B is in
-group N. A has preferred content `not inallgroup=N` and B has `not inallgroup=M`.
-
-If A contains a file, then B will want to also get a copy. And things
-stabilize there. But if the file is removed from A, then B also wants to
-remove it. And once B has removed it, A wants a copy of it. And then B also
-wants a copy of it. So the result is that the file got transferred twice,
-to end up right back where we started.
-
The worst case of this is `not present`, where the file gets dropped and
transferred over and over again. The docs warn against using that one. But
they can't warn about every bad preferred content expression.
+Mostly, git-annex manages to keep things stable that seem like they would
+not be. Consider repo A that is not in group foo, and B is in group foo. A
+has preferred content "onlyingroup=foo". This will make A want a file that
+is in B. And once it has it, it will not want to drop it. That's because
+when dropping, it considers if it would be preferred content after the
+drop. In this case it would, so it doesn't drop it.
+
## balanced preferred content
When [[design/balanced_preferred_content]] is added, a whole new level of
content does take repository fullness into account, which further
complicates fully understanding the behavior.
-Notice that `fullbalanced()` is not stable when used
+Notice that `fullybalanced()` is not stable when used
on its own, and so `balanced()` adds an "or present" to stabilize it.
And so `not balanced()` includes `not present`, which is bad!
if it could detect it. Similarly `not groupwanted` could be detected as a
problem when the group's preferred content expression contains `present`.
-Is there is a more general purpose and not expensive way to detect such
-problematic expressions, that can find problems such as the
-`not inallgroup=N` example above?
+> This is now detected and such an unstable expression never matches.
+> --debug explains why too.
+>
+> Note that the detection will not be trigged by `"not (not present)"`,
+> but it will by `"include=* or (not present)"` even though that is always
+> stable, because `"include=*"` always matches and so what it's ORed with
+> doesn't matter. Probably noone will set something like that in real life
+> though.
+>
+> It's problimatic to make `git-annex wanted` warn about it. Consider
+> if in one repository, groupwanted is set to "present". In another
+> repository, which is disconnected, wanted is set to "not groupwanted".
+> Both operations are ok, but upon merging the two repositories,
+> the combined effect is that "not present" has been set.
+>
+> So while it could warn sometimes on setting "not present",
+> it would sometimes not be able to. Better to not warn inconsistently.
+> --[[Joey]]
## simulation
Simulation seems fairly straightforward, just simulate the network of
git-annex repositories with random files with different sizes and
-metadata. Be sure to enforce invariants like numcopies the same as
-git-annex does.
+metadata. Or use the current files and metadata.
+Be sure to enforce invariants like numcopies the same as git-annex does.
Since users can write preferred content expressions, this should be
targeted at being used by end users.