drop, move, mirror: when two files have the same content, honor the max numcopies and requiredcopies

Eg, before with a .gitattributes like:

*.2 annex.numcopies=2
*.1 annex.numcopies=1

And foo.1 and foo.2 having the same content and key, git-annex drop foo.1 foo.2
would succeed, leaving just 1 copy, despite foo.2 needing 2 copies.
It dropped foo.1 first and then skipped foo.2 since its content was gone.

Now that the keys database includes locked files, this longstanding wart
can be fixed.

Sponsored-by: Noam Kremen on Patreon
This commit is contained in:
Joey Hess 2021-06-15 11:38:44 -04:00
parent 0ed1369dcd
commit d2be68907c
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 24 additions and 30 deletions

View file

@ -60,7 +60,7 @@ handleDropsFrom locs rs reason fromhere key afile si preverified runner = do
where where
getcopies fs = do getcopies fs = do
(untrusted, have) <- trustPartition UnTrusted locs (untrusted, have) <- trustPartition UnTrusted locs
(numcopies, mincopies) <- getSafestNumMinCopies' key fs (numcopies, mincopies) <- getSafestNumMinCopies' afile key fs
return (length have, numcopies, mincopies, S.fromList untrusted) return (length have, numcopies, mincopies, S.fromList untrusted)
{- Check that we have enough copies still to drop the content. {- Check that we have enough copies still to drop the content.

View file

@ -11,7 +11,6 @@ module Annex.NumCopies (
module Types.NumCopies, module Types.NumCopies,
module Logs.NumCopies, module Logs.NumCopies,
getFileNumMinCopies, getFileNumMinCopies,
getAssociatedFileNumMinCopies,
getSafestNumMinCopies, getSafestNumMinCopies,
getSafestNumMinCopies', getSafestNumMinCopies',
getGlobalFileNumCopies, getGlobalFileNumCopies,
@ -123,33 +122,21 @@ getFileNumMinCopies f = do
<$> fallbacknum <$> fallbacknum
<*> fallbackmin <*> fallbackmin
{- NumCopies and MinCopies value for an associated file, or the default
- when there is no associated file.
-
- This does not include other associated files using the same key.
-}
getAssociatedFileNumMinCopies :: AssociatedFile -> Annex (NumCopies, MinCopies)
getAssociatedFileNumMinCopies (AssociatedFile (Just file)) =
getFileNumMinCopies file
getAssociatedFileNumMinCopies (AssociatedFile Nothing) = (,)
<$> getNumCopies
<*> getMinCopies
{- Gets the highest NumCopies and MinCopies value for all files {- Gets the highest NumCopies and MinCopies value for all files
- associated with a key. Provide any known associated file; - associated with a key. Provide any known associated file;
- the rest are looked up from the database. - the rest are looked up from the database.
- -
- Using this when dropping avoids dropping one file that - Using this when dropping, rather than getFileNumMinCopies
- has a smaller value violating the value set for another file - avoids dropping one file that has a smaller value violating
- that uses the same content. - the value set for another file that uses the same content.
-} -}
getSafestNumMinCopies :: AssociatedFile -> Key -> Annex (NumCopies, MinCopies) getSafestNumMinCopies :: AssociatedFile -> Key -> Annex (NumCopies, MinCopies)
getSafestNumMinCopies afile k = getSafestNumMinCopies afile k =
Database.Keys.getAssociatedFilesIncluding afile k Database.Keys.getAssociatedFilesIncluding afile k
>>= getSafestNumMinCopies' k >>= getSafestNumMinCopies' afile k
getSafestNumMinCopies' :: Key -> [RawFilePath] -> Annex (NumCopies, MinCopies) getSafestNumMinCopies' :: AssociatedFile -> Key -> [RawFilePath] -> Annex (NumCopies, MinCopies)
getSafestNumMinCopies' k fs = do getSafestNumMinCopies' afile k fs = do
l <- mapM getFileNumMinCopies fs l <- mapM getFileNumMinCopies fs
let l' = zip l fs let l' = zip l fs
(,) (,)
@ -158,7 +145,12 @@ getSafestNumMinCopies' k fs = do
where where
-- Some associated files in the keys database may no longer -- Some associated files in the keys database may no longer
-- correspond to files in the repository. -- correspond to files in the repository.
stillassociated f = catKeyFile f >>= \case -- (But the AssociatedFile passed to this is known to be
-- an associated file, which may not be in the keys database
-- yet, so checking it is skipped.)
stillassociated f
| AssociatedFile (Just f) == afile = return True
| otherwise = catKeyFile f >>= \case
Just k' | k' == k -> return True Just k' | k' == k -> return True
_ -> return False _ -> return False

View file

@ -4,7 +4,7 @@ git-annex (8.20210429) UNRELEASED; urgency=medium
* When two files have the same content, and a required content expression * When two files have the same content, and a required content expression
matches one but not the other, dropping the latter file will fail as it matches one but not the other, dropping the latter file will fail as it
would also remove the content of the required file. would also remove the content of the required file.
* drop, move, import: When two files have the same content, and * drop, move, mirror: When two files have the same content, and
different numcopies or requiredcopies values, use the higher value. different numcopies or requiredcopies values, use the higher value.
* drop --auto: When two files have the same content, and a preferred content * drop --auto: When two files have the same content, and a preferred content
expression matches one but not the other, do not drop the content. expression matches one but not the other, do not drop the content.

View file

@ -227,7 +227,7 @@ checkRequiredContent (PreferredContentChecked False) u k afile =
- copies on other semitrusted repositories. -} - copies on other semitrusted repositories. -}
checkDropAuto :: Bool -> Maybe Remote -> AssociatedFile -> Key -> (NumCopies -> MinCopies -> CommandStart) -> CommandStart checkDropAuto :: Bool -> Maybe Remote -> AssociatedFile -> Key -> (NumCopies -> MinCopies -> CommandStart) -> CommandStart
checkDropAuto automode mremote afile key a = checkDropAuto automode mremote afile key a =
go =<< getAssociatedFileNumMinCopies afile go =<< getSafestNumMinCopies afile key
where where
go (numcopies, mincopies) go (numcopies, mincopies)
| automode = do | automode = do

View file

@ -68,7 +68,7 @@ startKey o afile (si, key, ai) = case fromToOptions o of
ToRemote r -> checkFailedTransferDirection ai Upload $ ifM (inAnnex key) ToRemote r -> checkFailedTransferDirection ai Upload $ ifM (inAnnex key)
( Command.Move.toStart Command.Move.RemoveNever afile key ai si =<< getParsed r ( Command.Move.toStart Command.Move.RemoveNever afile key ai si =<< getParsed r
, do , do
(numcopies, mincopies) <- getAssociatedFileNumMinCopies afile (numcopies, mincopies) <- getSafestNumMinCopies afile key
Command.Drop.startRemote pcc afile ai si numcopies mincopies key =<< getParsed r Command.Drop.startRemote pcc afile ai si numcopies mincopies key =<< getParsed r
) )
FromRemote r -> checkFailedTransferDirection ai Download $ do FromRemote r -> checkFailedTransferDirection ai Download $ do
@ -81,7 +81,7 @@ startKey o afile (si, key, ai) = case fromToOptions o of
) )
Right False -> ifM (inAnnex key) Right False -> ifM (inAnnex key)
( do ( do
(numcopies, mincopies) <- getAssociatedFileNumMinCopies afile (numcopies, mincopies) <- getSafestNumMinCopies afile key
Command.Drop.startLocal pcc afile ai si numcopies mincopies key [] Command.Drop.startLocal pcc afile ai si numcopies mincopies key []
, stop , stop
) )

View file

@ -166,7 +166,7 @@ toPerform dest removewhen key afile fastcheck isthere = do
willDropMakeItWorse srcuuid destuuid deststartedwithcopy key afile >>= \case willDropMakeItWorse srcuuid destuuid deststartedwithcopy key afile >>= \case
DropAllowed -> drophere setpresentremote contentlock "moved" DropAllowed -> drophere setpresentremote contentlock "moved"
DropCheckNumCopies -> do DropCheckNumCopies -> do
(numcopies, mincopies) <- getAssociatedFileNumMinCopies afile (numcopies, mincopies) <- getSafestNumMinCopies afile key
(tocheck, verified) <- verifiableCopies key [srcuuid] (tocheck, verified) <- verifiableCopies key [srcuuid]
verifyEnoughCopiesToDrop "" key (Just contentlock) verifyEnoughCopiesToDrop "" key (Just contentlock)
numcopies mincopies [srcuuid] verified numcopies mincopies [srcuuid] verified
@ -245,7 +245,7 @@ fromPerform src removewhen key afile = do
willDropMakeItWorse srcuuid destuuid deststartedwithcopy key afile >>= \case willDropMakeItWorse srcuuid destuuid deststartedwithcopy key afile >>= \case
DropAllowed -> dropremote "moved" DropAllowed -> dropremote "moved"
DropCheckNumCopies -> do DropCheckNumCopies -> do
(numcopies, mincopies) <- getAssociatedFileNumMinCopies afile (numcopies, mincopies) <- getSafestNumMinCopies afile key
(tocheck, verified) <- verifiableCopies key [Remote.uuid src] (tocheck, verified) <- verifiableCopies key [Remote.uuid src]
verifyEnoughCopiesToDrop "" key Nothing numcopies mincopies [Remote.uuid src] verified verifyEnoughCopiesToDrop "" key Nothing numcopies mincopies [Remote.uuid src] verified
tocheck (dropremote . showproof) faileddropremote tocheck (dropremote . showproof) faileddropremote

View file

@ -21,4 +21,6 @@ do say that it bypasses checking .gitattributes numcopies.
> files. With the recent change to also track > files. With the recent change to also track
> associated files for locked files, they also handle it for those. > associated files for locked files, they also handle it for those.
> >
> But, git-annex drop/move/import don't yet. > But, git-annex drop/move/mirror don't yet.
>
> > [[fixed|done]] (did not change --all behavior) --[[Joey]]