D6479: shelve: first prototype of storing/restoring unresolved changes

navaneeth.suresh (Navaneeth Suresh) phabricator at mercurial-scm.org
Sun Jun 16 11:13:38 EDT 2019


navaneeth.suresh marked 7 inline comments as done.
navaneeth.suresh updated this revision to Diff 15534.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6479?vs=15517&id=15534

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6479/new/

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

AFFECTED FILES
  hgext/shelve.py
  mercurial/configitems.py
  tests/test-shelve-unresolved.t
  tests/test-shelve.t

CHANGE DETAILS

diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -85,6 +85,7 @@
       --stat                output diffstat-style summary of changes (provide
                             the names of the shelved changes as positional
                             arguments)
+      --unresolved          unshelve mergestate with unresolved files
    -I --include PATTERN [+] include names matching the given patterns
    -X --exclude PATTERN [+] exclude names matching the given patterns
       --mq                  operate on patch repository
diff --git a/tests/test-shelve-unresolved.t b/tests/test-shelve-unresolved.t
new file mode 100644
--- /dev/null
+++ b/tests/test-shelve-unresolved.t
@@ -0,0 +1,473 @@
+#testcases extrastorage usualstorage
+
+  $ addunresolvedmerge() {
+  >   echo A >> $1
+  >   echo A >> $2
+  >   hg ci -m A
+  >   echo B >> $1
+  >   echo B >> $2
+  >   hg ci -m B
+  >   hg up $3
+  >   echo C >> $1
+  >   echo C >> $2
+  >   hg ci -m C
+  >   hg merge -r $(($3+1))
+  > }
+
+Test shelve with unresolved mergestate
+
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > shelve =
+  > EOF
+
+#if extrastorage
+
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > store-in-extra = True
+  > EOF
+
+#endif
+
+  $ hg init shelve-unresolved
+  $ cd shelve-unresolved
+  $ echo A >> file1
+  $ echo A >> file2
+  $ hg ci -Am A
+  adding file1
+  adding file2
+  $ echo foo >> bar
+  $ hg add bar
+
+-- should abort on absence of mergestate
+  $ hg shelve --unresolved
+  abort: no active mergestate found
+  [255]
+
+  $ hg forget bar
+  $ echo B >> file1
+  $ echo B >> file2
+  $ hg ci -m B
+  $ hg up 0
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo C >> file1
+  $ echo C >> file2
+  $ hg ci -m C
+  created new head
+  $ hg merge
+  merging file1
+  merging file2
+  warning: conflicts while merging file1! (edit, then use 'hg resolve --mark')
+  warning: conflicts while merging file2! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 2 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
+  [1]
+
+-- let's partially solve the conflicts
+  $ cat > file1 <<EOF
+  > A
+  > B
+  > C
+  > EOF
+  $ hg resolve -m file1
+
+-- mark file2 as resolved to check abort
+  $ hg resolve -m file2
+  (no more unresolved files)
+  $ hg log -G
+  @  changeset:   2:69004294ad57
+  |  tag:         tip
+  |  parent:      0:c32ef6121744
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     C
+  |
+  | @  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+  $ cat file1
+  A
+  B
+  C
+  $ hg diff
+  diff -r 69004294ad57 file1
+  --- a/file1	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/file1	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,2 +1,3 @@
+   A
+  +B
+   C
+  diff -r 69004294ad57 file2
+  --- a/file2	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/file2	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,2 +1,6 @@
+   A
+  +<<<<<<< working copy: 69004294ad57 - test: C
+   C
+  +=======
+  +B
+  +>>>>>>> merge rev:    fd9a4049234b - test: B
+
+-- should abort on absence of conflicts
+  $ hg shelve
+  abort: mergestate found
+  try with --unresolved to shelve conflicts
+  [255]
+  $ hg shelve --unresolved
+  abort: no unresolved files found in the mergestate
+  [255]
+  $ hg resolve -u file2
+  $ hg resolve -l
+  R file1
+  U file2
+
+-- should suggest --unresolved on shelving with mergestate
+  $ hg shelve
+  abort: mergestate found
+  try with --unresolved to shelve conflicts
+  [255]
+
+  $ hg shelve --unresolved
+  shelved as default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cat file1
+  A
+  C
+  $ hg log -G
+  @  changeset:   2:69004294ad57
+  |  tag:         tip
+  |  parent:      0:c32ef6121744
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     C
+  |
+  | o  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+  $ hg shelve --list
+  default         (1s ago)    changes to: C (extrastorage !)
+  default (unresolved)         (1s ago)    changes to: C
+  $ hg shelve --patch
+  default         (1s ago)    changes to: C (extrastorage !)
+  default (unresolved)         (1s ago)    changes to: C
+  
+  diff --git a/file1 b/file1
+  --- a/file1
+  +++ b/file1
+  @@ -1,2 +1,3 @@
+   A
+  +B
+   C
+  diff --git a/file2 b/file2
+  --- a/file2
+  +++ b/file2
+  @@ -1,2 +1,6 @@
+   A
+  +<<<<<<< working copy: 69004294ad57 - test: C
+   C
+  +=======
+  +B
+  +>>>>>>> merge rev:    fd9a4049234b - test: B
+
+-- now, fix an urgent bug
+  $ echo fixed >> bug
+  $ ls
+  bar
+  bug
+  file1
+  file1.orig
+  file2
+  file2.orig
+  $ hg add bug
+  $ hg ci -m "fix bug"
+  $ hg log -G
+  @  changeset:   3:a53a9a7475b3
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     fix bug
+  |
+  o  changeset:   2:69004294ad57
+  |  parent:      0:c32ef6121744
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     C
+  |
+  | o  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+-- let's get back to the old mergestate
+-- we need to update to one of the merge parents. otherwise, abort.
+  $ hg unshelve --unresolved
+  unshelving change 'default'
+  abort: dirstate is not on either of the merge parents.
+  use hg update to one of the merge parents.
+  [255]
+
+  $ hg up 2
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ cat file2
+  A
+  C
+
+-- flag --unshelve is not passed. but, the last shelve is unresolved
+  $ hg unshelve
+  unshelving change 'default'
+  abort: default is an unresolved shelve, use --unresolved to unshelve it
+  [255]
+
+  $ hg unshelve --unresolved
+  unshelving change 'default'
+
+  $ hg log -G
+  o  changeset:   3:a53a9a7475b3
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     fix bug
+  |
+  @  changeset:   2:69004294ad57
+  |  parent:      0:c32ef6121744
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     C
+  |
+  | @  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+  $ cat file1
+  A
+  B
+  C
+  $ hg diff
+  diff -r 69004294ad57 file1
+  --- a/file1	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/file1	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,2 +1,3 @@
+   A
+  +B
+   C
+  diff -r 69004294ad57 file2
+  --- a/file2	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/file2	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,2 +1,6 @@
+   A
+  +<<<<<<< working copy: 69004294ad57 - test: C
+   C
+  +=======
+  +B
+  +>>>>>>> merge rev:    fd9a4049234b - test: B
+  $ cat file2
+  A
+  <<<<<<< working copy: 69004294ad57 - test: C
+  C
+  =======
+  B
+  >>>>>>> merge rev:    fd9a4049234b - test: B
+  $ hg resolve -l
+  R file1
+  U file2
+
+-- flag --unresolved is passed but the top most shelve is not unresolved
+  $ hg shelve --unresolved
+  shelved as default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ echo garbage >> bug
+  $ hg st
+  ? bar
+  ? bug
+  ? file1.orig
+  ? file2.orig
+  $ hg add bug
+  $ hg shelve
+  shelved as default-01
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg unshelve --unresolved
+  unshelving change 'default-01'
+  abort: default-01 is not an unresolved shelve
+  
+  [255]
+
+-- now, unshelve default
+  $ hg unshelve -n default --unresolved
+
+-- commit the merge after completing conflict resolution
+  $ cat >> file2 <<EOF
+  > A
+  > B
+  > C
+  > EOF
+  $ hg resolve -m file2
+  (no more unresolved files)
+  $ hg ci -m merge
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  checked 5 changesets with 9 changes to 3 files
+  $ hg log -G
+  @    changeset:   4:745dca2ee1f1
+  |\   tag:         tip
+  | |  parent:      2:69004294ad57
+  | |  parent:      1:fd9a4049234b
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     merge
+  | |
+  | | o  changeset:   3:a53a9a7475b3
+  | |/   user:        test
+  | |    date:        Thu Jan 01 00:00:00 1970 +0000
+  | |    summary:     fix bug
+  | |
+  | o  changeset:   2:69004294ad57
+  | |  parent:      0:c32ef6121744
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     C
+  | |
+  o |  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+
+-- flag --unresolved is passed but we don’t have any unresolved shelve
+  $ hg unshelve --unresolved
+  unshelving change 'default-01'
+  abort: default-01 is not an unresolved shelve
+  
+  [255]
+
+-- when working directory is dirty
+  $ addunresolvedmerge file1 file2 5
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  created new head
+  merging file1
+  merging file2
+  warning: conflicts while merging file1! (edit, then use 'hg resolve --mark')
+  warning: conflicts while merging file2! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 2 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
+  [1]
+
+  $ hg shelve --unresolved
+  shelved as default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ echo dirt >> bar
+  $ hg add bar
+  $ hg unshelve --unresolved
+  unshelving change 'default'
+  abort: uncommitted changes
+  [255]
+
+--- unshelve --unresolved when there is another merge going on
+  $ hg ci -m dirt
+  $ hg up 7
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo foo >> bug
+  $ hg add bug
+  $ hg ci -m foo2
+  created new head
+  $ hg log -G
+  @  changeset:   9:c74a624102ed
+  |  tag:         tip
+  |  parent:      7:974ec4298b79
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     foo2
+  |
+  | o  changeset:   8:4acf09fb3a59
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     dirt
+  |
+  o  changeset:   7:974ec4298b79
+  |  parent:      5:db68c6c84fe6
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     C
+  |
+  | o  changeset:   6:e236d497f76b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   5:db68c6c84fe6
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     A
+  |
+  o    changeset:   4:745dca2ee1f1
+  |\   parent:      2:69004294ad57
+  | |  parent:      1:fd9a4049234b
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     merge
+  | |
+  | | o  changeset:   3:a53a9a7475b3
+  | |/   user:        test
+  | |    date:        Thu Jan 01 00:00:00 1970 +0000
+  | |    summary:     fix bug
+  | |
+  | o  changeset:   2:69004294ad57
+  | |  parent:      0:c32ef6121744
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     C
+  | |
+  o |  changeset:   1:fd9a4049234b
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     B
+  |
+  o  changeset:   0:c32ef6121744
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     A
+  
+  $ hg merge -r 8
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+  $ hg unshelve --unresolved
+  unshelving change 'default'
+  abort: outstanding uncommitted merge
+  [255]
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -628,6 +628,9 @@
 coreconfigitem('experimental', 'sparse-read.min-gap-size',
     default='65K',
 )
+coreconfigitem('experimental', 'store-in-extra',
+    default=False,
+)
 coreconfigitem('experimental', 'treemanifest',
     default=False,
 )
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -432,6 +432,45 @@
         cmdutil.exportfile(repo, [node], fp, opts=mdiff.diffopts(git=True),
                            match=match)
 
+def _encodemergerecords(records):
+    """Encode mergestate records to store in changeset extras.
+    Takes list of tuples as input and returns str.
+    """
+    items = [
+        '%s\033%s' % (rtype, record)
+        for rtype, record in sorted(records)
+    ]
+    return "\n".join(items)
+
+def _decodemergerecords(data):
+    """Decode mergestate record from changeset extras to return
+    a list of tuples.
+    """
+    records = []
+    for l in data.split('\n'):
+        rtype, record = l.split('\033')
+        records.append((rtype, record))
+    return records
+
+def _storeunresolvedmerge(ui, repo, name=None, extra=None):
+    """Store the mergestate information in changeset extra
+    if config option `experimental.store-in-extra` is set True.
+
+    Otherwise, move the usual mergestate information from
+    `.hg/merge` to `.hg/merge-unresolved/<name>`.
+
+    This will clear the mergestate and also stores the mergestate
+    information for later restoration.
+    """
+    if ui.config('experimental', 'store-in-extra'):
+        ms = merge.mergestate.read(repo)
+        extra['mergerecords'] = _encodemergerecords(ms._readrecords())
+        ms.reset()
+    else:
+        if not repo.vfs.exists('merge-unresolved'):
+            repo.vfs.mkdir('merge-unresolved')
+        repo.vfs.rename('merge', 'merge-unresolved/%s' % name)
+
 def _includeunknownfiles(repo, pats, opts, extra):
     s = repo.status(match=scmutil.match(repo[None], pats, opts),
                     unknown=True)
@@ -439,6 +478,18 @@
         extra['shelve_unknown'] = '\0'.join(s.unknown)
         repo[None].add(s.unknown)
 
+def _isunresolvedshelve(ui, repo, sname=None, shelvectx=None):
+    """Checks whether the given shelve is unresolved or not"""
+    if shelvectx is not None:
+        return shelvectx.extra().get('unresolved-merge')
+
+    if not ui.config('experimental', 'store-in-extra'):
+        return repo.vfs.exists('merge-unresolved/%s' % sname)
+
+    #TODO: add functionality to distinguish unresolved shelves
+    # on doing `hg shelve --list` when `experimental.store-in-extra`
+    # set True
+
 def _finishshelve(repo, tr):
     if phases.supportinternal(repo):
         tr.close()
@@ -454,10 +505,19 @@
 def _docreatecmd(ui, repo, pats, opts):
     wctx = repo[None]
     parents = wctx.parents()
-    if len(parents) > 1:
-        raise error.Abort(_('cannot shelve while merging'))
+    unresolved = opts.get('unresolved')
     parent = parents[0]
     origbranch = wctx.branch()
+    ms = merge.mergestate.read(repo)
+    if unresolved:
+        if not ms.active():
+                raise error.Abort(_('no active mergestate found'))
+        elif not list(ms.unresolved()):
+            raise error.Abort(_('no unresolved '
+                                'files found in the mergestate'))
+    elif ms.active():
+        raise error.Abort(_('mergestate found\n'
+                            'try with --unresolved to shelve conflicts'))
 
     if parent.node() != nodemod.nullid:
         desc = "changes to: %s" % parent.description().split('\n', 1)[0]
@@ -482,6 +542,9 @@
         name = getshelvename(repo, parent, opts)
         activebookmark = _backupactivebookmark(repo)
         extra = {'internal': 'shelve'}
+        if unresolved:
+            extra['unresolved-merge'] = True
+            _storeunresolvedmerge(ui, repo, name, extra)
         if includeunknown:
             _includeunknownfiles(repo, pats, opts, extra)
 
@@ -577,6 +640,7 @@
     """subcommand that displays the list of shelves"""
     pats = set(pats)
     width = 80
+    namewidth = 16
     if not ui.plain():
         width = ui.termwidth()
     namelabel = 'shelve.newest'
@@ -585,13 +649,16 @@
         sname = util.split(name)[1]
         if pats and sname not in pats:
             continue
+        if _isunresolvedshelve(ui, repo, sname):
+            sname += ' (unresolved)'
+            namewidth += len(' (unresolved)')
         ui.write(sname, label=namelabel)
         namelabel = 'shelve.name'
         if ui.quiet:
             ui.write('\n')
             continue
-        ui.write(' ' * (16 - len(sname)))
-        used = 16
+        ui.write(' ' * (namewidth - len(sname)))
+        used = namewidth
         date = dateutil.makedate(mtime)
         age = '(%s)' % templatefilters.age(date, abbrev=True)
         ui.write(age, label='shelve.age')
@@ -694,6 +761,26 @@
         ui.status(_('marked working directory as branch %s\n')
                   % branchtorestore)
 
+def restoreunresolvedshelve(ui, repo, shelvectx, basename):
+    """Change the parents of the dirstate to the parents of the stored
+    unresolved shelvectx.
+
+    Rewrite the mergestate from changeset extra if
+    `experimental.store-in-extra` is set True.
+
+    Otherwise, replace `.hg/merge` with `.hg/merge-unresolved/<basename>`
+    to restore the status of the resolved files in the shelvectx.
+    """
+    p1, p2 = shelvectx.parents()
+    repo.dirstate.setparents(p1.node(), p2.node())
+
+    if ui.config('experimental', 'store-in-extra'):
+        records = shelvectx.extra().get('mergerecords')
+        ms = merge.mergestate.clean(repo)
+        ms._writerecordsv2(_decodemergerecords(records))
+    else:
+        repo.vfs.rename('merge-unresolved/%s' % basename, 'merge')
+
 def unshelvecleanup(ui, repo, name, opts):
     """remove related files after an unshelve"""
     if not opts.get('keep'):
@@ -898,7 +985,9 @@
            _('restore shelved change with given name'), _('NAME')),
           ('t', 'tool', '', _('specify merge tool')),
           ('', 'date', '',
-           _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
+           _('set date for temporary commits (DEPRECATED)'), _('DATE')),
+          ('', 'unresolved', None,
+           _('unshelve mergestate with unresolved files'))],
          _('hg unshelve [[-n] SHELVED]'),
          helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def unshelve(ui, repo, *shelved, **opts):
@@ -944,6 +1033,7 @@
     opts = pycompat.byteskwargs(opts)
     abortf = opts.get('abort')
     continuef = opts.get('continue')
+    unresolved = opts.get('unresolved')
     if not abortf and not continuef:
         cmdutil.checkunfinished(repo)
     shelved = list(shelved)
@@ -999,6 +1089,8 @@
 
     if not shelvedfile(repo, basename, patchextension).exists():
         raise error.Abort(_("shelved change '%s' not found") % basename)
+    if unresolved:
+        cmdutil.bailifchanged(repo)
 
     repo = repo.unfiltered()
     lock = tr = None
@@ -1019,18 +1111,35 @@
         tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
                                                          tmpwctx)
         repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
+        unresolvedshelve = _isunresolvedshelve(ui, repo, basename, shelvectx)
         _checkunshelveuntrackedproblems(ui, repo, shelvectx)
         branchtorestore = ''
         if shelvectx.branch() != shelvectx.p1().branch():
             branchtorestore = shelvectx.branch()
 
-        shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
-                                          basename, pctx, tmpwctx,
-                                          shelvectx, branchtorestore,
-                                          activebookmark)
+        if unresolved:
+            if not unresolvedshelve:
+                raise error.Abort(_('%s is not an unresolved shelve\n') %
+                                    basename)
+            p1, p2 = shelvectx.parents()
+            if pctx.node() not in [p1.node(), p2.node()]:
+                raise error.Abort(_('dirstate is not on either of the merge'
+                                    ' parents.\nuse hg update to one of the'
+                                    ' merge parents.'))
+        elif unresolvedshelve:
+            raise error.Abort(_('%s is an unresolved shelve, use'
+                                ' --unresolved to unshelve it') % basename)
+        else:
+            shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
+                                            basename, pctx, tmpwctx,
+                                            shelvectx, branchtorestore,
+                                            activebookmark)
         overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
         with ui.configoverride(overrides, 'unshelve'):
             mergefiles(ui, repo, pctx, shelvectx)
+        if unresolved:
+            with repo.dirstate.parentchange():
+                restoreunresolvedshelve(ui, repo, shelvectx, basename)
         restorebranch(ui, repo, branchtorestore)
         _forgetunknownfiles(repo, shelvectx, addedbefore)
 
@@ -1068,7 +1177,9 @@
            _('interactive mode, only works while creating a shelve')),
           ('', 'stat', None,
            _('output diffstat-style summary of changes (provide the names of '
-             'the shelved changes as positional arguments)')
+             'the shelved changes as positional arguments)')),
+          ('', 'unresolved', None,
+           _('unshelve mergestate with unresolved files')
            )] + cmdutil.walkopts,
          _('hg shelve [OPTION]... [FILE]...'),
          helpcategory=command.CATEGORY_WORKING_DIRECTORY)



To: navaneeth.suresh, #hg-reviewers
Cc: pulkit, mercurial-devel


More information about the Mercurial-devel mailing list