Patchwork [STABLE] largefiles: properly sync lfdirstate after removing largefiles

login
register
mail settings
Submitter Matt Harbison
Date Jan. 4, 2015, 8:35 p.m.
Message ID <1b3df5ef594965843adb.1420403742@Envy>
Download mbox | patch
Permalink /patch/7315/
State Accepted
Commit 1b3df5ef594965843adb6993fb559d3de9099360
Headers show

Comments

Matt Harbison - Jan. 4, 2015, 8:35 p.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1420403186 18000
#      Sun Jan 04 15:26:26 2015 -0500
# Branch stable
# Node ID 1b3df5ef594965843adb6993fb559d3de9099360
# Parent  4308087f2fbd90b5beaac53a71d6264684ee0c40
largefiles: properly sync lfdirstate after removing largefiles

The more aggressive synchronization of lfdirstate that was backed out in
1265a3a71d75 masked the problem where lfdirstate would hold an 'R' for a
largefile that was added and then removed without a commit between.  We could
just conditionally call lfdirstate.drop() or lfdirstate.remove() here, but this
also properly updates lfdirstate if the standin doesn't exist for the file
somehow (i.e. call drop instead of remove).

Without this change, the precommit status in the commit command immediately
after the test change lists the removed (and never committed) largefile as 'R'.
It can also lead to situations where the status command reports the same, long
after the commit [1].

[1] http://www.selenic.com/pipermail/mercurial-devel/2015-January/065153.html
Matt Mackall - Jan. 5, 2015, 8:52 p.m.
On Sun, 2015-01-04 at 15:35 -0500, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1420403186 18000
> #      Sun Jan 04 15:26:26 2015 -0500
> # Branch stable
> # Node ID 1b3df5ef594965843adb6993fb559d3de9099360
> # Parent  4308087f2fbd90b5beaac53a71d6264684ee0c40
> largefiles: properly sync lfdirstate after removing largefiles

Queued for stable, thanks.

Patch

diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -206,12 +206,10 @@ 
             if not opts.get('dry_run'):
                 if not after:
                     util.unlinkpath(repo.wjoin(f), ignoremissing=True)
-                lfdirstate.remove(f)
 
         if opts.get('dry_run'):
             return result
 
-        lfdirstate.write()
         remove = [lfutil.standin(f) for f in remove]
         # If this is being called by addremove, let the original addremove
         # function handle this.
@@ -219,6 +217,12 @@ 
             for f in remove:
                 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
         repo[None].forget(remove)
+
+        for f in remove:
+            lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f),
+                                  False)
+
+        lfdirstate.write()
     finally:
         wlock.release()
 
diff --git a/tests/test-largefiles-misc.t b/tests/test-largefiles-misc.t
--- a/tests/test-largefiles-misc.t
+++ b/tests/test-largefiles-misc.t
@@ -250,6 +250,7 @@ 
 Add a normal file to the subrepo, then test archiving
 
   $ echo 'normal file' > subrepo/normal.txt
+  $ touch large.dat
   $ mv subrepo/large.txt subrepo/renamed-large.txt
   $ hg -R subrepo addremove --dry-run
   removing large.txt
@@ -257,11 +258,19 @@ 
   adding renamed-large.txt
   $ hg status -S
   ! subrepo/large.txt
+  ? large.dat
   ? subrepo/normal.txt
   ? subrepo/renamed-large.txt
   $ mv subrepo/renamed-large.txt subrepo/large.txt
   $ hg -R subrepo add subrepo/normal.txt
 
+  $ hg addremove
+  adding large.dat as a largefile
+  $ rm large.dat
+
+  $ hg addremove
+  removing large.dat
+
 Lock in subrepo, otherwise the change isn't archived
 
   $ hg ci -S -m "add normal file to top level"