graft in imported tree to avoid gc
Fix a bug that could prevent getting files from an importtree=yes remote, because the imported tree was allowed to be garbage collected.
This commit is contained in:
parent
c6e693b25d
commit
7916fc98a3
5 changed files with 58 additions and 34 deletions
|
@ -161,7 +161,7 @@ recordImportTree remote importtreeconfig importable = do
|
||||||
|
|
||||||
updateexportlog importedtree = do
|
updateexportlog importedtree = do
|
||||||
oldexport <- getExport (Remote.uuid remote)
|
oldexport <- getExport (Remote.uuid remote)
|
||||||
recordExport (Remote.uuid remote) $ ExportChange
|
recordExport (Remote.uuid remote) importedtree $ ExportChange
|
||||||
{ oldTreeish = exportedTreeishes oldexport
|
{ oldTreeish = exportedTreeishes oldexport
|
||||||
, newTreeish = importedtree
|
, newTreeish = importedtree
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ git-annex (8.20201128) UNRELEASED; urgency=medium
|
||||||
* Windows: include= and exclude= containing '/' will also match filenames
|
* Windows: include= and exclude= containing '/' will also match filenames
|
||||||
that are written using '\'. (And vice-versa, but it's better to use '/'
|
that are written using '\'. (And vice-versa, but it's better to use '/'
|
||||||
for portability.)
|
for portability.)
|
||||||
|
* Fix a bug that could prevent getting files from an importtree=yes
|
||||||
|
remote, because the imported tree was allowed to be garbage collected.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Mon, 30 Nov 2020 12:55:49 -0400
|
-- Joey Hess <id@joeyh.name> Mon, 30 Nov 2020 12:55:49 -0400
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ changeExport r db (PreferredFiltered new) = do
|
||||||
-- from a previous export, that are not part of this export.
|
-- from a previous export, that are not part of this export.
|
||||||
c <- Annex.getState Annex.errcounter
|
c <- Annex.getState Annex.errcounter
|
||||||
when (c == 0) $ do
|
when (c == 0) $ do
|
||||||
recordExport (uuid r) $ ExportChange
|
recordExportUnderway (uuid r) $ ExportChange
|
||||||
{ oldTreeish = exportedTreeishes old
|
{ oldTreeish = exportedTreeishes old
|
||||||
, newTreeish = new
|
, newTreeish = new
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- git-annex export log (also used to log imports)
|
{- git-annex export log (also used to log imports)
|
||||||
-
|
-
|
||||||
- Copyright 2017-2019 Joey Hess <id@joeyh.name>
|
- Copyright 2017-2020 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU AGPL version 3 or higher.
|
- Licensed under the GNU AGPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -15,8 +15,9 @@ module Logs.Export (
|
||||||
getExport,
|
getExport,
|
||||||
exportedTreeishes,
|
exportedTreeishes,
|
||||||
incompleteExportedTreeishes,
|
incompleteExportedTreeishes,
|
||||||
recordExport,
|
|
||||||
recordExportBeginning,
|
recordExportBeginning,
|
||||||
|
recordExportUnderway,
|
||||||
|
recordExport,
|
||||||
logExportExcluded,
|
logExportExcluded,
|
||||||
getExportExcluded,
|
getExportExcluded,
|
||||||
) where
|
) where
|
||||||
|
@ -85,35 +86,6 @@ getExport remoteuuid = nub . mapMaybe get . M.toList . simpleMap
|
||||||
| exportTo ep == remoteuuid = Just exported
|
| exportTo ep == remoteuuid = Just exported
|
||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
|
|
||||||
-- | Record a change in what's exported to a special remote.
|
|
||||||
--
|
|
||||||
-- This is called before an export begins uploading new files to the
|
|
||||||
-- remote, but after it's cleaned up any files that need to be deleted
|
|
||||||
-- from the old treeish.
|
|
||||||
--
|
|
||||||
-- Any entries in the log for the oldTreeish will be updated to the
|
|
||||||
-- newTreeish. This way, when multiple repositories are exporting to
|
|
||||||
-- the same special remote, there's no conflict as long as they move
|
|
||||||
-- forward in lock-step.
|
|
||||||
--
|
|
||||||
-- Also, the newTreeish is grafted into the git-annex branch. This is done
|
|
||||||
-- to ensure that it's available later.
|
|
||||||
recordExport :: UUID -> ExportChange -> Annex ()
|
|
||||||
recordExport remoteuuid ec = do
|
|
||||||
c <- liftIO currentVectorClock
|
|
||||||
u <- getUUID
|
|
||||||
let ep = ExportParticipants { exportFrom = u, exportTo = remoteuuid }
|
|
||||||
let exported = Exported (newTreeish ec) []
|
|
||||||
Annex.Branch.change exportLog $
|
|
||||||
buildExportLog
|
|
||||||
. changeMapLog c ep exported
|
|
||||||
. M.mapWithKey (updateothers c u)
|
|
||||||
. parseExportLog
|
|
||||||
where
|
|
||||||
updateothers c u ep le@(LogEntry _ exported@(Exported { exportedTreeish = t }))
|
|
||||||
| u == exportFrom ep || remoteuuid /= exportTo ep || t `notElem` oldTreeish ec = le
|
|
||||||
| otherwise = LogEntry c (exported { exportedTreeish = newTreeish ec })
|
|
||||||
|
|
||||||
-- | Record the beginning of an export, to allow cleaning up from
|
-- | Record the beginning of an export, to allow cleaning up from
|
||||||
-- interrupted exports.
|
-- interrupted exports.
|
||||||
--
|
--
|
||||||
|
@ -132,7 +104,52 @@ recordExportBeginning remoteuuid newtree = do
|
||||||
buildExportLog
|
buildExportLog
|
||||||
. changeMapLog c ep new
|
. changeMapLog c ep new
|
||||||
. parseExportLog
|
. parseExportLog
|
||||||
Annex.Branch.rememberTreeish newtree (asTopFilePath "export.tree")
|
recordExportTreeish newtree
|
||||||
|
|
||||||
|
-- Grade a tree ref into the git-annex branch. This is done
|
||||||
|
-- to ensure that it's available later, when getting exported files
|
||||||
|
-- from the remote. Since that could happen in another clone of the
|
||||||
|
-- repository, the tree has to be kept available, even if it
|
||||||
|
-- doesn't end up being merged into the master branch.
|
||||||
|
recordExportTreeish :: Git.Ref -> Annex ()
|
||||||
|
recordExportTreeish t =
|
||||||
|
Annex.Branch.rememberTreeish t (asTopFilePath "export.tree")
|
||||||
|
|
||||||
|
-- | Record that an export to a special remote is under way.
|
||||||
|
--
|
||||||
|
-- This is called before an export begins uploading new files to the
|
||||||
|
-- remote, but after it's cleaned up any files that need to be deleted
|
||||||
|
-- from the old treeish.
|
||||||
|
--
|
||||||
|
-- Any entries in the log for the oldTreeish will be updated to the
|
||||||
|
-- newTreeish. This way, when multiple repositories are exporting to
|
||||||
|
-- the same special remote, there's no conflict as long as they move
|
||||||
|
-- forward in lock-step.
|
||||||
|
recordExportUnderway :: UUID -> ExportChange -> Annex ()
|
||||||
|
recordExportUnderway remoteuuid ec = do
|
||||||
|
c <- liftIO currentVectorClock
|
||||||
|
u <- getUUID
|
||||||
|
let ep = ExportParticipants { exportFrom = u, exportTo = remoteuuid }
|
||||||
|
let exported = Exported (newTreeish ec) []
|
||||||
|
Annex.Branch.change exportLog $
|
||||||
|
buildExportLog
|
||||||
|
. changeMapLog c ep exported
|
||||||
|
. M.mapWithKey (updateothers c u)
|
||||||
|
. parseExportLog
|
||||||
|
where
|
||||||
|
updateothers c u ep le@(LogEntry _ exported@(Exported { exportedTreeish = t }))
|
||||||
|
| u == exportFrom ep || remoteuuid /= exportTo ep || t `notElem` oldTreeish ec = le
|
||||||
|
| otherwise = LogEntry c (exported { exportedTreeish = newTreeish ec })
|
||||||
|
|
||||||
|
-- Record information about the export to the git-annex branch.
|
||||||
|
--
|
||||||
|
-- This is equivilant to recordExportBeginning followed by
|
||||||
|
-- recordExportUnderway, but without the ability to clean up from
|
||||||
|
-- interrupted exports.
|
||||||
|
recordExport :: UUID -> Git.Ref -> ExportChange -> Annex ()
|
||||||
|
recordExport remoteuuid tree ec = do
|
||||||
|
recordExportTreeish tree
|
||||||
|
recordExportUnderway remoteuuid ec
|
||||||
|
|
||||||
parseExportLog :: L.ByteString -> MapLog ExportParticipants Exported
|
parseExportLog :: L.ByteString -> MapLog ExportParticipants Exported
|
||||||
parseExportLog = parseMapLog exportParticipantsParser exportedParser
|
parseExportLog = parseMapLog exportParticipantsParser exportedParser
|
||||||
|
|
|
@ -3,3 +3,8 @@ does not seem to get grafted into the git-annex branch, so
|
||||||
would be subject to being lost to GC.
|
would be subject to being lost to GC.
|
||||||
|
|
||||||
Is this a general problem affecting importtree too?
|
Is this a general problem affecting importtree too?
|
||||||
|
|
||||||
|
> Yes, it was. It would have only caused a problem if the user
|
||||||
|
> kept doing imports from a remote, but never exporting to it.
|
||||||
|
> Then, in a clone of the repo that was importing, they would not be able
|
||||||
|
> to get files. [[fixed|done]] --[[Joey]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue