D135: rebase: use one dirstateguard for when using rebase.singletransaction

durham (Durham Goode) phabricator at mercurial-scm.org
Tue Aug 1 20:35:38 UTC 2017


This revision was automatically updated to reflect the committed changes.
Closed by commit rHG609606d21765: rebase: use one dirstateguard for when using rebase.singletransaction (authored by durham).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D135?vs=338&id=483

REVISION DETAIL
  https://phab.mercurial-scm.org/D135

AFFECTED FILES
  hgext/rebase.py
  mercurial/dirstateguard.py
  mercurial/util.py
  tests/test-rebase-base.t

CHANGE DETAILS

diff --git a/tests/test-rebase-base.t b/tests/test-rebase-base.t
--- a/tests/test-rebase-base.t
+++ b/tests/test-rebase-base.t
@@ -379,3 +379,40 @@
    /
   o  0: A
   
+Rebasing using a single transaction
+
+  $ hg init singletr && cd singletr
+  $ cat >> .hg/hgrc <<EOF
+  > [rebase]
+  > singletransaction=True
+  > EOF
+  $ hg debugdrawdag <<'EOF'
+  >   Z
+  >   |
+  >   | D
+  >   | |
+  >   | C
+  >   | |
+  >   Y B
+  >   |/
+  >   A
+  > EOF
+- We should only see two status stored messages. One from the start, one from
+- the end.
+  $ hg rebase --debug -b D -d Z | grep 'status stored'
+  rebase status stored
+  rebase status stored
+  $ hg tglog
+  o  5: D
+  |
+  o  4: C
+  |
+  o  3: B
+  |
+  o  2: Z
+  |
+  o  1: Y
+  |
+  o  0: A
+  
+  $ cd ..
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -602,6 +602,10 @@
     finally:
         tr.release()
 
+ at contextlib.contextmanager
+def nullcontextmanager():
+    yield
+
 class _lrucachenode(object):
     """A node in a doubly linked list.
 
diff --git a/mercurial/dirstateguard.py b/mercurial/dirstateguard.py
--- a/mercurial/dirstateguard.py
+++ b/mercurial/dirstateguard.py
@@ -43,6 +43,16 @@
             # ``release(tr, ....)``.
             self._abort()
 
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        try:
+            if exc_type is None:
+                self.close()
+        finally:
+            self.release()
+
     def close(self):
         if not self._active: # already inactivated
             msg = (_("can't close already inactivated backup: %s")
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -479,12 +479,17 @@
                 editopt = True
             editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
             revtoreuse = max(self.state)
-            newnode = concludenode(repo, revtoreuse, p1, self.external,
-                                   commitmsg=commitmsg,
-                                   extrafn=_makeextrafn(self.extrafns),
-                                   editor=editor,
-                                   keepbranches=self.keepbranchesf,
-                                   date=self.date)
+
+            dsguard = None
+            if ui.configbool('rebase', 'singletransaction'):
+                dsguard = dirstateguard.dirstateguard(repo, 'rebase')
+            with util.acceptintervention(dsguard):
+                newnode = concludenode(repo, revtoreuse, p1, self.external,
+                                       commitmsg=commitmsg,
+                                       extrafn=_makeextrafn(self.extrafns),
+                                       editor=editor,
+                                       keepbranches=self.keepbranchesf,
+                                       date=self.date)
             if newnode is None:
                 newrev = self.dest
             else:
@@ -711,10 +716,16 @@
                 return retcode
 
         tr = None
-        if ui.configbool('rebase', 'singletransaction'):
+        dsguard = None
+
+        singletr = ui.configbool('rebase', 'singletransaction')
+        if singletr:
             tr = repo.transaction('rebase')
         with util.acceptintervention(tr):
-            rbsrt._performrebase(tr)
+            if singletr:
+                dsguard = dirstateguard.dirstateguard(repo, 'rebase')
+            with util.acceptintervention(dsguard):
+                rbsrt._performrebase(tr)
 
         rbsrt._finishrebase()
 
@@ -841,8 +852,10 @@
     '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
     but also store useful information in extra.
     Return node of committed revision.'''
-    dsguard = dirstateguard.dirstateguard(repo, 'rebase')
-    try:
+    dsguard = util.nullcontextmanager()
+    if not repo.ui.configbool('rebase', 'singletransaction'):
+        dsguard = dirstateguard.dirstateguard(repo, 'rebase')
+    with dsguard:
         repo.setparents(repo[p1].node(), repo[p2].node())
         ctx = repo[rev]
         if commitmsg is None:
@@ -864,10 +877,7 @@
                                   date=date, extra=extra, editor=editor)
 
         repo.dirstate.setbranch(repo[newnode].branch())
-        dsguard.close()
         return newnode
-    finally:
-        release(dsguard)
 
 def rebasenode(repo, rev, p1, base, state, collapse, dest):
     'Rebase a single revision rev on top of p1 using base as merge ancestor'



To: durham, #hg-reviewers, martinvonz
Cc: martinvonz, mercurial-devel


More information about the Mercurial-devel mailing list