run restagePointerFiles in adjustedBranchRefreshFull

Avoid failure to update adjusted branch --unlock-present after git-annex
drop when annex.adjustedbranchrefresh=1

At higher values, it did flush the queue, which ran restagePointerFiles.
But at 1, adjustedBranchRefreshFull gets added to the queue, and while
restagePointerFiles is also in the queue, it runs after that.

Sponsored-by: Brock Spratlen on Patreon
This commit is contained in:
Joey Hess 2023-03-23 16:23:56 -04:00
parent d580ea2120
commit cb4d9f7b1f
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
6 changed files with 88 additions and 11 deletions

View file

@ -45,7 +45,6 @@ import Annex.Common
import Types.AdjustedBranch
import Annex.AdjustedBranch.Name
import qualified Annex
import qualified Annex.Queue
import Git
import Git.Types
import qualified Git.Branch
@ -312,22 +311,20 @@ adjustedBranchRefresh _af a = do
!s' = s { Annex.adjustedbranchrefreshcounter = c' }
in pure (s', enough)
update adj origbranch = do
-- Flush the queue, to make any pending changes be written
-- out to disk. But mostly so any pointer files
-- restagePointerFile was called on get updated so git
-- checkout won't fall over.
Annex.Queue.flush
-- This is slow, it would be better to incrementally
-- adjust the AssociatedFile, and only call this once
-- at shutdown to handle cases where not all
-- AssociatedFiles are known.
-- This is slow, it would be better to incrementally
-- adjust the AssociatedFile, and only call this once
-- at shutdown to handle cases where not all
-- AssociatedFiles are known.
update adj origbranch =
adjustedBranchRefreshFull adj origbranch
{- Slow, but more dependable version of adjustedBranchRefresh that
- does not rely on all AssociatedFiles being known. -}
adjustedBranchRefreshFull :: Adjustment -> OrigBranch -> Annex ()
adjustedBranchRefreshFull adj origbranch = do
-- Restage pointer files so modifications to them due to get/drop
-- do not prevent checking out the updated adjusted branch.
restagePointerFiles =<< Annex.gitRepo
let adjbranch = originalToAdjusted origbranch adj
unlessM (updateAdjustedBranch adj adjbranch origbranch) $
warning $ unwords [ "Updating adjusted branch failed." ]

View file

@ -1,6 +1,8 @@
git-annex (10.20230322) UNRELEASED; urgency=medium
* sync: Fix parsing of gcrypt::rsync:// urls that use a relative path.
* Avoid failure to update adjusted branch --unlock-present after git-annex
drop when annex.adjustedbranchrefresh=1
-- Joey Hess <id@joeyh.name> Thu, 23 Mar 2023 15:04:41 -0400

View file

@ -6,4 +6,6 @@
I assume this is a --hide-missing adjusted branch?
Update: Oh, I see from a forum post that it's --unlock-present actually.
What is the annex.adjustedbranchrefresh git config set to?
"""]]

View file

@ -0,0 +1,42 @@
[[!comment format=mdwn
username="joey"
subject="""comment 2"""
date="2023-03-23T19:35:33Z"
content="""
I was able to reproduce something that looks similar to this without
needing to interrupt any command:
joey@darkstar:~/tmp/bench>git clone a b
Cloning into 'b'...
done.
joey@darkstar:~/tmp/bench>cd b
joey@darkstar:~/tmp/bench/b>git config annex.adjustedbranchrefresh 1
joey@darkstar:~/tmp/bench/b>git annex adjust --unlock-present
adjust
Switched to branch 'adjusted/master(unlockpresent)'
ok
joey@darkstar:~/tmp/bench/b#master(unlockpresent)>ls
foo@
joey@darkstar:~/tmp/bench/b#master(unlockpresent)>git-annex get
get foo (from origin...)
ok
(recording state in git...)
joey@darkstar:~/tmp/bench/b#master(unlockpresent)>ls
foo
joey@darkstar:~/tmp/bench/b#master(unlockpresent)>git-annex drop
drop foo ok
error: Your local changes to the following files would be overwritten by checkout:
foo
Please commit your changes or stash them before you switch branches.
Aborting
Updating adjusted branch failed.
(recording state in git...)
And it was left in a similar detached head status:
HEAD detached at 2aab85d
nothing to commit, working tree clean
This seems be be a bug with the implementation of annex.adjustedbranchrefresh
"""]]

View file

@ -0,0 +1,23 @@
[[!comment format=mdwn
username="joey"
subject="""comment 3"""
date="2023-03-23T19:50:45Z"
content="""
git-annex is what writes that detached HEAD,
in updateAdjustedBranch. And I've verified that when it fails like this,
git status shows the file is modified. But of course the modification is
only that the annex content has been replaced by an annex pointer. Running
`git add` on the file makes the modification status go away.
And this only happens when annex.adjustedbranchrefresh=1.
At higher values, it calls Annex.Queue.flush, but at 1 it does not, and so
restagePointerFiles does not get called before adjustedBranchRefreshFull.
(Or at least may not, they're both running as cleanup actions and order is
not really defined.)
I wonder if there are other situations where modifications can prevent
checkout of the updated adjusted branch? Eg, what if the user has made some
other modification to an annexed file? It seems wise for git-annex to
defend against it in depth, by making sure no crash can leave it in
detached head state.
"""]]

View file

@ -0,0 +1,11 @@
[[!comment format=mdwn
username="joey"
subject="""comment 1"""
date="2023-03-23T19:30:12Z"
content="""
You can just run "git checkout adjusted/master(unlockpresent)"
to switch back to that branch.
It's fine to switch between adjusted and other branches, though the way git-annex
failed and left your head detached is certainly a bug.
"""]]