largefiles: defer lfdirstate.drop() until after commit (issue3364)

The example in comment #9 of the bug writeup must be run exactly- it was the
commit after the rm and prior to the addremove that screwed things up, because
that commit noticed that the largefile was missing, called drop(), and then the
original commit function did nothing (due to the file in the '!' state).  The
addremove command properly put it into the 'R' state, but it remained stuck in
that state (because commit insisted 'nothing changed').  Without the commit
prior to addremove, the problem didn't occur.

Maybe this is an indication that lfdirstate needs to take a few more hints from
the regular dirstate, regardless of what _it_ thinks the state is- similar
inconsistency is probably still possible with this patch if the original commit
succeeds but the lfdirstate write fails.
This commit is contained in:
Matt Harbison 2012-07-19 10:00:15 -04:00
parent 91452ea7b9
commit f0d41a8692
2 changed files with 62 additions and 6 deletions

View File

@ -338,15 +338,18 @@ def reposetup(ui, repo):
lfutil.updatestandin(self,
lfutil.standin(lfile))
lfdirstate.normal(lfile)
for lfile in lfdirstate:
if lfile in modifiedfiles:
if (not os.path.exists(repo.wjoin(
lfutil.standin(lfile)))) or \
(not os.path.exists(repo.wjoin(lfile))):
lfdirstate.drop(lfile)
result = orig(text=text, user=user, date=date, match=match,
force=force, editor=editor, extra=extra)
if result is not None:
for lfile in lfdirstate:
if lfile in modifiedfiles:
if (not os.path.exists(repo.wjoin(
lfutil.standin(lfile)))) or \
(not os.path.exists(repo.wjoin(lfile))):
lfdirstate.drop(lfile)
# This needs to be after commit; otherwise precommit hooks
# get the wrong status
lfdirstate.write()

View File

@ -389,6 +389,59 @@ Test addremove with -R
adding normaladdremove
$ cd a
Test 3364
$ hg clone . ../addrm
updating to branch default
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
getting changed largefiles
3 largefiles updated, 0 removed
$ cd ../addrm
$ cat >> .hg/hgrc <<EOF
> [hooks]
> post-commit.stat=sh -c "echo \"Invoking status postcommit hook\"; hg status -A"
> EOF
$ touch foo
$ hg add --large foo
$ hg ci -m "add foo"
Invoking status precommit hook
A foo
Invoking status postcommit hook
C foo
C normal3
C sub/large4
C sub/normal4
C sub2/large6
C sub2/large7
$ rm foo
$ hg st
! foo
hmm.. no precommit invoked, but there is a postcommit??
$ hg ci -m "will not checkin"
nothing changed
Invoking status postcommit hook
! foo
C normal3
C sub/large4
C sub/normal4
C sub2/large6
C sub2/large7
[1]
$ hg addremove
removing foo
$ hg st
R foo
$ hg ci -m "used to say nothing changed"
Invoking status precommit hook
R foo
Invoking status postcommit hook
C normal3
C sub/large4
C sub/normal4
C sub2/large6
C sub2/large7
$ hg st
$ cd ../a
Clone a largefiles repo.
$ hg clone . ../b