[PATCH 2 of 4 STABLE] largefiles: defer lfdirstate.drop() until after commit (issue3364)

Matt Harbison matt_harbison at yahoo.com
Fri Jul 20 16:19:03 CDT 2012


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1342706415 14400
# Node ID 4cf8aa8986e321ba8de95e6017b20c723f4642e7
# Parent  3446acc27a9c4c29e27cd8f7e3714109c21dd36c
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.

diff --git a/hgext/largefiles/reposetup.py b/hgext/largefiles/reposetup.py
--- a/hgext/largefiles/reposetup.py
+++ b/hgext/largefiles/reposetup.py
@@ -338,15 +338,18 @@
                                     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()
diff --git a/tests/test-largefiles.t b/tests/test-largefiles.t
--- a/tests/test-largefiles.t
+++ b/tests/test-largefiles.t
@@ -389,6 +389,59 @@
   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


More information about the Mercurial-devel mailing list