Patchwork D6479: unshelve: first prototype of restoring unresolved changes

login
register
mail settings
Submitter phabricator
Date June 10, 2019, 5:12 p.m.
Message ID <87d0addb59e623ba0db73293330a056d@localhost.localdomain>
Download mbox | patch
Permalink /patch/40406/
State Not Applicable
Headers show

Comments

phabricator - June 10, 2019, 5:12 p.m.
navaneeth.suresh updated this revision to Diff 15423.
navaneeth.suresh marked 2 inline comments as done.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS




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

Patch

diff --git a/tests/test-shelve-unresolved.t b/tests/test-shelve-unresolved.t
--- a/tests/test-shelve-unresolved.t
+++ b/tests/test-shelve-unresolved.t
@@ -1,3 +1,17 @@ 
+  $ 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
@@ -156,3 +170,283 @@ 
   +=======
   +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 --unsresolved 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
+  abort: cannot unshelve while merging
+  [255]
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -714,6 +714,16 @@ 
         ui.status(_('marked working directory as branch %s\n')
                   % branchtorestore)
 
+def restoreunresolvedshelve(repo, ui, basename, pctx, shelvectx):
+    p1, p2 = shelvectx.parents()
+    with repo.dirstate.parentchange():
+            repo.dirstate.setparents(p1.node(), p2.node())
+
+    # Replace `merge/` with `merge-unresolved/<basename>/` to
+    # restore the status of resolved files in shelvectx.
+    util.rename(repo.vfs.join('merge-unresolved/%s/' % basename),
+                repo.vfs.join('merge'))
+
 def unshelvecleanup(ui, repo, name, opts):
     """remove related files after an unshelve"""
     if not opts.get('keep'):
@@ -918,7 +928,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):
@@ -964,6 +976,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)
@@ -1019,6 +1032,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
@@ -1039,18 +1054,34 @@ 
         tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
                                                          tmpwctx)
         repo, shelvectx = _unshelverestorecommit(ui, repo, tr, basename)
+        unresolvedshelve = shelvectx.extra().get('unresolved-merge')
         _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:
+            restoreunresolvedshelve(repo, ui, basename, pctx, shelvectx)
         restorebranch(ui, repo, branchtorestore)
         _forgetunknownfiles(repo, shelvectx, addedbefore)