Patchwork [4,of,4] shelve: find shelvedctx from bundle even if they are already in the repo

login
register
mail settings
Submitter Boris Feld
Date Sept. 27, 2018, 4:49 p.m.
Message ID <850324b80f9c305a14ea.1538066992@localhost.localdomain>
Download mbox | patch
Permalink /patch/35134/
State Accepted
Headers show

Comments

Boris Feld - Sept. 27, 2018, 4:49 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1537458425 -7200
#      Thu Sep 20 17:47:05 2018 +0200
# Node ID 850324b80f9c305a14ea37740dabd3abbc6e4f1f
# Parent  4deea424746d21e029caf45b10ad3cef311e92d0
# EXP-Topic revlog-duplicates
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 850324b80f9c
shelve: find shelvedctx from bundle even if they are already in the repo

We use the new "duplicates" node tracking to find the tip of the bundle even if
it already exists in the repository.

Such logic is not supposed to be needed in theory. If the shelve was made using
internal-phase, we already know its node. Otherwise, the bundle content should
have been stripped. However, handling it makes the shelve code more robust and
provide a good example of "revduplicates" usage.

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -144,11 +144,17 @@  class shelvedfile(object):
             if not phases.supportinternal(self.repo):
                 targetphase = phases.secret
             gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
-            bundle2.applybundle(self.repo, gen, self.repo.currenttransaction(),
+            pretip = self.repo['tip']
+            tr = self.repo.currenttransaction()
+            bundle2.applybundle(self.repo, gen, tr,
                                 source='unshelve',
                                 url='bundle:' + self.vfs.join(self.fname),
                                 targetphase=targetphase)
-            return self.repo['tip']
+            shelvectx = self.repo['tip']
+            if pretip == shelvectx:
+                shelverev = tr.changes['revduplicates'][-1]
+                shelvectx = self.repo[shelverev]
+            return shelvectx
         finally:
             fp.close()
 
diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -1858,16 +1858,34 @@  mercurial does not crash
 
 #if phasebased
 
-Unshelve without .shelve metadata:
+Unshelve with some metadata file missing
+----------------------------------------
 
   $ hg shelve
   shelved as default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo 3 > a
+
+Test with the `.shelve` missing, but the changeset still in the repo (non-natural case)
+
+  $ rm .hg/shelved/default.shelve
+  $ hg unshelve
+  unshelving change 'default'
+  temporarily committing pending changes (restore with 'hg unshelve --abort')
+  rebasing shelved changes
+  merging a
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+  $ hg unshelve --abort
+  unshelve of 'default' aborted
+
+Unshelve without .shelve metadata (can happen when upgrading a repository with old shelve)
+
   $ cat .hg/shelved/default.shelve
   node=82e0cb9893247d12667017593ce1e5655860f1ac
   $ hg strip --hidden --rev 82e0cb989324 --no-backup
   $ rm .hg/shelved/default.shelve
-  $ echo 3 > a
   $ hg unshelve
   unshelving change 'default'
   temporarily committing pending changes (restore with 'hg unshelve --abort')
@@ -1878,6 +1896,8 @@  Unshelve without .shelve metadata:
   [1]
   $ cat .hg/shelved/default.shelve
   node=82e0cb9893247d12667017593ce1e5655860f1ac
+  $ hg unshelve --abort
+  unshelve of 'default' aborted
 
 #endif