Patchwork [05,of,10,shelve-ext,v2] shelve: add obs-based shelve functionality

login
register
mail settings
Submitter Kostia Balytskyi
Date Jan. 19, 2017, 3:10 p.m.
Message ID <44425c4e86b2589184e2.1484838632@devvm1416.lla2.facebook.com>
Download mbox | patch
Permalink /patch/18256/
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 44425c4e86b2589184e23bed798999c15788b54b
# Parent  ceb709491816f84789b77a18bfcab15eaa9860fe
shelve: add obs-based shelve functionality

Obsolescense-based shelve works in a following way:
1. In order to shelve some changes, it creates a commit, records its
node into a .oshelve file and prunes created commit.
2. In order to finish a shelve operation, transaction is just
closed and not aborted.

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -373,10 +373,15 @@  def _nothingtoshelvemessaging(ui, repo, 
     else:
         ui.status(_("nothing changed\n"))
 
-def _shelvecreatedcommit(repo, node, name):
-    bases = list(mutableancestors(repo[node]))
-    shelvedfile(repo, name, 'hg').writebundle(bases, node)
-    cmdutil.export(repo, [node],
+def _shelvecreatedcommit(ui, repo, node, name, tr):
+    if isobsshelve(repo, ui):
+        shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({
+            'node': nodemod.hex(node)
+        })
+    else:
+        bases = list(mutableancestors(repo[node]))
+        shelvedfile(repo, name, 'hg').writebundle(bases, node)
+    cmdutil.export(repo.unfiltered(), [node],
                    fp=shelvedfile(repo, name, patchextension).opener('wb'),
                    opts=mdiff.diffopts(git=True))
 
@@ -387,8 +392,13 @@  def _includeunknownfiles(repo, pats, opt
         extra['shelve_unknown'] = '\0'.join(s.unknown)
         repo[None].add(s.unknown)
 
-def _finishshelve(repo):
-    _aborttransaction(repo)
+def _finishshelve(ui, repo, tr, node):
+    if isobsshelve(repo, ui):
+        obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
+        tr.close()
+        tr.release()
+    else:
+        _aborttransaction(repo)
 
 def _docreatecmd(ui, repo, pats, opts):
     wctx = repo[None]
@@ -410,9 +420,12 @@  def _docreatecmd(ui, repo, pats, opts):
     try:
         lock = repo.lock()
 
-        # use an uncommitted transaction to generate the bundle to avoid
-        # pull races. ensure we don't print the abort message to stderr.
-        tr = repo.transaction('commit', report=lambda x: None)
+        # depending on whether shelve is traditional or
+        # obsolescense-based, we either abort or commit this
+        # transaction in the end. If we abort it, we don't
+        # want to print anything to stderr
+        report = None if isobsshelve(repo, ui) else (lambda x: None)
+        tr = repo.transaction('commit', report=report)
 
         interactive = opts.get('interactive', False)
         includeunknown = (opts.get('unknown', False) and
@@ -438,16 +451,19 @@  def _docreatecmd(ui, repo, pats, opts):
             _nothingtoshelvemessaging(ui, repo, pats, opts)
             return 1
 
-        _shelvecreatedcommit(repo, node, name)
+        _shelvecreatedcommit(ui, repo, node, name, tr)
 
         if ui.formatted():
             desc = util.ellipsis(desc, ui.termwidth())
         ui.status(_('shelved as %s\n') % name)
-        hg.update(repo, parent.node())
+        # current wc parent may be already obsolete becuase
+        # it might have been created previously and shelve just
+        # reuses it
+        hg.update(repo.unfiltered(), parent.node())
         if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts):
             repo.dirstate.setbranch(origbranch)
 
-        _finishshelve(repo)
+        _finishshelve(ui, repo, tr, node)
     finally:
         lockmod.release(tr, lock)