Patchwork [7,of,8] largefiles: avoid corruption of largefiles at "rebase --continue"

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Sept. 9, 2014, 6:18 p.m.
Message ID <8135c7dc8f6db4823753.1410286731@feefifofum>
Download mbox | patch
Permalink /patch/5752/
State Changes Requested
Headers show

Comments

Katsunori FUJIWARA - Sept. 9, 2014, 6:18 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1410286454 -32400
#      Wed Sep 10 03:14:14 2014 +0900
# Node ID 8135c7dc8f6db4823753b2c1bd8c2a28c369fd3f
# Parent  514254647d89290af5d2d036479accda1e8ea729
largefiles: avoid corruption of largefiles at "rebase --continue"

Before this patch, "repo._lfautocommit='rebase'" attribute is created
even at the 1st commit of resuming ("hg rebase --continue"), and it
makes "lfilesrepo.commit" assume that:

  - standins are already updated, and
  - largefiles have to be synchronize to standins

This causes corruption of largefiles modified manually before
resuming.

The code path for the 1st commit of resuming should move out of
"repo._lfautocommit='rebase'" scope.

To avoid corruption of largefiles at "hg rebase --continue", this
patch uses "cmdutil.autocommit" to wrap "rebase.concludenode" instead
of direct wrapping by "rebaseconcludenode".

This patch passes "resuming=True" to "cmdutil.autocommit" only for the
1st commit of resuming, and this prevent from creating
"repo._lfautocommit='rebase'" scope at that time.

Changes in this patch also allow rebase extension to change around
"concludenode" (including removal of it) without adjusting
implementation in largefiles extension, while rebase extension uses
"autocommit" framework.

Patch

diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1356,13 +1356,6 @@ 
 
     return orig(commandname, repo, wrapper)
 
-def rebaseconcludenode(orig, repo, *args, **kwargs):
-    repo._lfautocommit = 'rebase'
-    try:
-        return orig(repo, *args, **kwargs)
-    finally:
-        repo._lfautocommit = False
-
 def rebaserebasenode(orig, repo, *args, **kwargs):
     repo._lfautocommit = 'rebase'
     try:
diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py
--- a/hgext/largefiles/uisetup.py
+++ b/hgext/largefiles/uisetup.py
@@ -171,8 +171,6 @@ 
             extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
                 overrides.overridepurge)
         if name == 'rebase':
-            extensions.wrapfunction(module, 'concludenode',
-                                    overrides.rebaseconcludenode)
             extensions.wrapfunction(module, 'rebasenode',
                                     overrides.rebaserebasenode)
         if name == 'transplant':
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -320,6 +320,10 @@ 
         sortedstate = sorted(state)
         total = len(sortedstate)
         pos = 0
+        def autocommit(resuming):
+            return cmdutil.autocommit("rebase", repo, concludenode,
+                                      resuming=resuming)
+        commitfunc = autocommit(contf)
         for rev in sortedstate:
             pos += 1
             if state[rev] == -1:
@@ -356,8 +360,10 @@ 
                     merging = repo[p2].rev() != nullrev
                     editform = cmdutil.mergeeditform(merging, 'rebase')
                     editor = cmdutil.getcommiteditor(editform=editform, **opts)
-                    newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn,
-                                          editor=editor)
+                    newrev = commitfunc(repo, rev, p1, p2, extrafn=extrafn,
+                                        editor=editor)
+                    # the 2nd or later commits are always non-resuming ones
+                    commitfunc = autocommit(False)
                 else:
                     # Skip commit if we are collapsing
                     repo.setparents(repo[p1].node())
@@ -389,8 +395,8 @@ 
                         commitmsg += '\n* %s' % repo[rebased].description()
                 editopt = True
             editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
-            newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
-                                  extrafn=extrafn, editor=editor)
+            newrev = commitfunc(repo, rev, p1, external, commitmsg=commitmsg,
+                                extrafn=extrafn, editor=editor)
             for oldrev in state.iterkeys():
                 if state[oldrev] > nullmerge:
                     state[oldrev] = newrev
diff --git a/tests/test-largefiles-update.t b/tests/test-largefiles-update.t
--- a/tests/test-largefiles-update.t
+++ b/tests/test-largefiles-update.t
@@ -482,8 +482,29 @@ 
   $ cat large1
   large1 in #1
 
-  $ hg rebase -q --abort
-  rebase aborted
+Test that rebase commits largefiles at "rebae --continue" correctly,
+even if they are modified manually before resuming.
+
+  $ echo 'modified before rebase --continue' > large1
+  $ hg resolve -m normal1
+  (no more unresolved files)
+  $ hg rebase --continue
+  local changed .hglf/large1 which remote deleted
+  use (c)hanged version or (d)elete? c
+  getting changed largefiles
+  1 largefiles updated, 1 removed
+
+  $ hg diff -c 6 .hglf/large1 | grep '^[+-][0-9a-z]'
+  -e5bb990443d6a92aaf7223813720f7566c9dd05b
+  +1cd09404d81c9dd9ff2048aebb61934c13d367dd
+  $ hg cat -r 6 large1
+  modified before rebase --continue
+  $ hg diff -c 7 .hglf/large1 | grep '^[+-][0-9a-z]'
+  [1]
+  $ hg cat -r 7 large1
+  modified before rebase --continue
+
+  $ hg strip -q 6
 
 Test that transplant updates largefiles, of which standins are safely
 changed, even if it is aborted by conflict of other.