Patchwork [09,of,10,shelve-ext,v2] shelve: add logic to preserve active bookmarks

login
register
mail settings
Submitter Kostia Balytskyi
Date Jan. 19, 2017, 3:10 p.m.
Message ID <088c9191d662d5c00033.1484838636@devvm1416.lla2.facebook.com>
Download mbox | patch
Permalink /patch/18260/
State Deferred
Headers show

Comments

Kostia Balytskyi - Jan. 19, 2017, 3:10 p.m.
# HG changeset patch
# User Kostia Balytskyi <ikostia@fb.com>
# Date 1484740179 28800
#      Wed Jan 18 03:49:39 2017 -0800
# Node ID 088c9191d662d5c0003310119c51540926a815f7
# Parent  94a237a046059ef246aacb2c3ad809c9f0bdbe70
shelve: add logic to preserve active bookmarks

This adds an explicit active-bookmark-handling logic
to *both* traditional and obs-based shelve. Although it
is possible to only add it to obs-based, I think it would
be ugly and I see no harm in explicitly handling bookmarks
in addition to reliance on trasnactions.

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -29,6 +29,7 @@  import time
 
 from mercurial.i18n import _
 from mercurial import (
+    bookmarks,
     bundle2,
     bundlerepo,
     changegroup,
@@ -188,6 +189,8 @@  class shelvedstate(object):
     _nokeep = 'nokeep'
     _obsbased = 'obsbased'
     _traditional = 'traditional'
+    # colon is essential to differentiate from a real bookmark name
+    _noactivebook = ':no-active-bookmark'
 
     def __init__(self, ui, repo):
         self.ui = ui
@@ -210,6 +213,7 @@  class shelvedstate(object):
             branchtorestore = fp.readline().strip()
             keep = fp.readline().strip() == cls._keep
             obsshelve = fp.readline().strip() == cls._obsbased
+            activebook = fp.readline().strip()
         except (ValueError, TypeError) as err:
             raise error.CorruptedState(str(err))
         finally:
@@ -225,6 +229,9 @@  class shelvedstate(object):
             obj.branchtorestore = branchtorestore
             obj.keep = keep
             obj.obsshelve = obsshelve
+            obj.activebookmark = ''
+            if activebook != cls._noactivebook:
+                obj.activebookmark = activebook
         except error.RepoLookupError as err:
             raise error.CorruptedState(str(err))
 
@@ -232,7 +239,7 @@  class shelvedstate(object):
 
     @classmethod
     def save(cls, repo, name, originalwctx, pendingctx, nodestoprune,
-             branchtorestore, keep=False, obsshelve=False):
+             branchtorestore, keep=False, obsshelve=False, activebook=''):
         fp = repo.vfs(cls._filename, 'wb')
         fp.write('%i\n' % cls._version)
         fp.write('%s\n' % name)
@@ -245,6 +252,7 @@  class shelvedstate(object):
         fp.write('%s\n' % branchtorestore)
         fp.write('%s\n' % (cls._keep if keep else cls._nokeep))
         fp.write('%s\n' % (cls._obsbased if obsshelve else cls._traditional))
+        fp.write('%s\n' % (activebook or cls._noactivebook))
         fp.close()
 
     @classmethod
@@ -283,6 +291,16 @@  def cleanupoldbackups(repo):
                 if err.errno != errno.ENOENT:
                     raise
 
+def _backupactivebookmark(repo):
+    activebookmark = repo._activebookmark
+    if activebookmark:
+        bookmarks.deactivate(repo)
+    return activebookmark
+
+def _restoreactivebookmark(repo, mark):
+    if mark:
+        bookmarks.activate(repo, mark)
+
 def _aborttransaction(repo):
     '''Abort current transaction for shelve/unshelve, but keep dirstate
     '''
@@ -402,7 +420,9 @@  def _includeunknownfiles(repo, pats, opt
         extra['shelve_unknown'] = '\0'.join(s.unknown)
         repo[None].add(s.unknown)
 
-def _finishshelve(ui, repo, tr, node):
+def _finishshelve(ui, repo, tr, node, activebookmark):
+    if activebookmark:
+        bookmarks.activate(repo, activebookmark)
     if isobsshelve(repo, ui):
         obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
         tr.close()
@@ -426,7 +446,7 @@  def _docreatecmd(ui, repo, pats, opts):
     if not opts.get('message'):
         opts['message'] = desc
 
-    lock = tr = None
+    lock = tr = activebookmark = None
     try:
         lock = repo.lock()
 
@@ -442,6 +462,7 @@  def _docreatecmd(ui, repo, pats, opts):
                           not opts.get('addremove', False))
 
         name = getshelvename(repo, parent, opts)
+        activebookmark = _backupactivebookmark(repo)
         extra = {}
         if includeunknown:
             _includeunknownfiles(repo, pats, opts, extra)
@@ -456,7 +477,8 @@  def _docreatecmd(ui, repo, pats, opts):
             node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
         else:
             node = cmdutil.dorecord(ui, repo, commitfunc, None,
-                                    False, cmdutil.recordfilter, *pats, **opts)
+                                    False, cmdutil.recordfilter, *pats,
+                                    **opts)
         if not node:
             _nothingtoshelvemessaging(ui, repo, pats, opts)
             return 1
@@ -473,8 +495,9 @@  def _docreatecmd(ui, repo, pats, opts):
         if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
             repo.dirstate.setbranch(origbranch)
 
-        _finishshelve(ui, repo, tr, node)
+        _finishshelve(ui, repo, tr, node, activebookmark)
     finally:
+        _restoreactivebookmark(repo, activebookmark)
         lockmod.release(tr, lock)
 
 def _isbareshelve(pats, opts):
@@ -697,6 +720,7 @@  def unshelvecontinue(ui, repo, state, op
         restorebranch(ui, repo, state.branchtorestore)
 
         state.prunenodes()
+        _restoreactivebookmark(repo, state.activebookmark)
         shelvedstate.clear(repo)
         unshelvecleanup(ui, repo, state.name, opts)
         ui.status(_("unshelve of '%s' complete\n") % state.name)
@@ -741,7 +765,8 @@  def _unshelverestorecommit(ui, repo, bas
     return repo, shelvectx
 
 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx,
-                          tmpwctx, shelvectx, branchtorestore, obsshelve):
+                          tmpwctx, shelvectx, branchtorestore, obsshelve,
+                          activebookmark):
     """Rebase restored commit from its original location to a destination"""
     # If the shelve is not immediately on top of the commit
     # we'll be merging with, rebase it to be on top.
@@ -778,7 +803,8 @@  def _rebaserestoredcommit(ui, repo, opts
         nodestoprune = [repo.changelog.node(rev)
                         for rev in xrange(oldtiprev, len(repo))]
         shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoprune,
-                          branchtorestore, opts.get('keep'), obsshelve)
+                          branchtorestore, opts.get('keep'), obsshelve,
+                          activebookmark)
 
         util.rename(repo.join('rebasestate'),
                     repo.join('unshelverebasestate'))
@@ -805,7 +831,8 @@  def _forgetunknownfiles(repo, shelvectx,
     toforget = (addedafter & shelveunknown) - addedbefore
     repo[None].forget(toforget)
 
-def _finishunshelve(repo, oldtiprev, tr, obsshelve):
+def _finishunshelve(repo, oldtiprev, tr, obsshelve, activebookmark):
+    _restoreactivebookmark(repo, activebookmark)
     if obsshelve:
         tr.close()
         return
@@ -958,6 +985,7 @@  def _dounshelve(ui, repo, *shelved, **op
         # and shelvectx is the unshelved changes. Then we merge it all down
         # to the original pctx.
 
+        activebookmark = _backupactivebookmark(repo)
         tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
                                                          tmpwctx)
 
@@ -973,7 +1001,7 @@  def _dounshelve(ui, repo, *shelved, **op
             shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
                                               basename, pctx, tmpwctx,
                                               shelvectx, branchtorestore,
-                                              obsshelve)
+                                              obsshelve, activebookmark)
             mergefiles(ui, repo, pctx, shelvectx)
         restorebranch(ui, repo, branchtorestore)
         _forgetunknownfiles(repo, shelvectx, addedbefore)
@@ -982,7 +1010,7 @@  def _dounshelve(ui, repo, *shelved, **op
             _obsoleteredundantnodes(repo, tr, pctx, shelvectx, tmpwctx)
 
         shelvedstate.clear(repo)
-        _finishunshelve(repo, oldtiprev, tr, obsshelve)
+        _finishunshelve(repo, oldtiprev, tr, obsshelve, activebookmark)
         unshelvecleanup(ui, repo, basename, opts)
     finally:
         if tr: