D6596: unshelve: make unshelve accept files (issue6162)

navaneeth.suresh (Navaneeth Suresh) phabricator at mercurial-scm.org
Thu Jul 4 11:00:26 EDT 2019


navaneeth.suresh marked an inline comment as done.
navaneeth.suresh updated this revision to Diff 15739.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6596?vs=15738&id=15757

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

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

AFFECTED FILES
  mercurial/commands.py
  mercurial/shelve.py
  tests/test-completion.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
@@ -1155,3 +1155,67 @@
   [255]
 
   $ cd ..
+
+-- unshelve --interactive
+
+  $ hg init a
+  $ cd a
+  $ echo > b
+  $ hg ci -Am b
+  adding b
+  $ echo > c
+  $ echo > d
+  $ hg add .
+  adding c
+  adding d
+  $ hg shelve
+  shelved as default
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo > e
+  $ hg add e
+  $ hg ci -m e
+  $ hg shelve --patch
+  default         (1s ago)    changes to: b
+  
+  diff --git a/c b/c
+  new file mode 100644
+  --- /dev/null
+  +++ b/c
+  @@ -0,0 +1,1 @@
+  +
+  diff --git a/d b/d
+  new file mode 100644
+  --- /dev/null
+  +++ b/d
+  @@ -0,0 +1,1 @@
+  +
+  $ hg unshelve -i<<EOF
+  > y
+  > n
+  > EOF
+  unshelving change 'default'
+  rebasing shelved changes
+  unshelve changes in file c (Yn)? y
+  unshelve changes in file d (Yn)? n
+  $ ls
+  b
+  c
+  e
+-- shelve should not contain `c` now
+  $ hg shelve --patch
+  default         (1s ago)    changes to: b
+  
+  diff --git a/d b/d
+  new file mode 100644
+  --- /dev/null
+  +++ b/d
+  @@ -0,0 +1,1 @@
+  +
+  $ hg unshelve
+  unshelving change 'default'
+  $ ls
+  b
+  c
+  d
+  e
+  $ hg shelve --list
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -349,7 +349,7 @@
   tags: template
   tip: patch, git, style, template
   unbundle: update
-  unshelve: abort, continue, keep, name, tool, date
+  unshelve: abort, continue, interactive, keep, name, tool, date
   update: clean, check, merge, date, rev, tool
   verify: full
   version: template
diff --git a/mercurial/shelve.py b/mercurial/shelve.py
--- a/mercurial/shelve.py
+++ b/mercurial/shelve.py
@@ -34,6 +34,8 @@
     bundlerepo,
     changegroup,
     cmdutil,
+    context,
+    copies as copiesmod,
     discovery,
     error,
     exchange,
@@ -747,6 +749,46 @@
     tmpwctx = repo[node]
     return tmpwctx, addedbefore
 
+def _commitfiltered(repo, ctx, match, keepcommit):
+    """Recommit ctx with changed files not in match. Return the new
+    node identifier, or None if nothing changed.
+    """
+    base = ctx.p1()
+    # ctx
+    initialfiles = set(ctx.files())
+    files = set(f for f in initialfiles if match(f))
+
+    # return the p1 so that we don't create an obsmarker later
+    if not keepcommit:
+        return ctx.p1().node()
+
+    # Filter copies
+    copied = copiesmod.pathcopies(base, ctx)
+    copied = dict((dst, src) for dst, src in copied.iteritems()
+                  if dst in files)
+    def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()):
+        if path not in contentctx:
+            return None
+        fctx = contentctx[path]
+        mctx = context.memfilectx(repo, memctx, fctx.path(), fctx.data(),
+                                  fctx.islink(),
+                                  fctx.isexec(),
+                                  copysource=copied.get(path))
+        return mctx
+
+    if not files:
+        repo.ui.status(_("note: keeping empty commit\n"))
+
+    new = context.memctx(repo,
+                         parents=[base.node(), nodemod.nullid],
+                         text=ctx.description(),
+                         files=files,
+                         filectxfn=filectxfn,
+                         user=ctx.user(),
+                         date=ctx.date(),
+                         extra=ctx.extra())
+    return repo[repo.commitctx(new)]
+
 def _unshelverestorecommit(ui, repo, tr, basename):
     """Recreate commit in the repository during the unshelve"""
     repo = repo.unfiltered()
@@ -852,6 +894,7 @@
     opts = pycompat.byteskwargs(opts)
     abortf = opts.get('abort')
     continuef = opts.get('continue')
+    interactive = opts.get('interactive')
     if not abortf and not continuef:
         cmdutil.checkunfinished(repo)
     shelved = list(shelved)
@@ -942,15 +985,37 @@
                                           basename, pctx, tmpwctx,
                                           shelvectx, branchtorestore,
                                           activebookmark)
+        files = shelvectx.files()
+        filesinclude = []
+        filesexclude = []
+        if interactive:
+            for file in files:
+                choice = ui.promptchoice(
+                    _('unshelve changes in file %s (Yn)?$$ &Yes $$ &No')
+                    % file)
+                if choice == 0:
+                    filesinclude.append(file)
+                else:
+                    filesexclude.append(file)
+
+            match = scmutil.match(shelvectx, filesinclude, {})
+            match2 = scmutil.match(shelvectx, filesexclude, {})
+            shelvectxbackup = shelvectx
+            shelvectx = _commitfiltered(repo, shelvectx, match,
+                                        keepcommit=True)
+            shelvectxnew = _commitfiltered(repo, shelvectxbackup, match2,
+                                           keepcommit=True)
+            _shelvecreatedcommit(repo, shelvectxnew.node(), basename, match2)
         overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
         with ui.configoverride(overrides, 'unshelve'):
             mergefiles(ui, repo, pctx, shelvectx)
         restorebranch(ui, repo, branchtorestore)
-        _forgetunknownfiles(repo, shelvectx, addedbefore)
+        if not interactive or (interactive and files == filesinclude):
+            _forgetunknownfiles(repo, shelvectx, addedbefore)
 
-        shelvedstate.clear(repo)
-        _finishunshelve(repo, oldtiprev, tr, activebookmark)
-        unshelvecleanup(ui, repo, basename, opts)
+            shelvedstate.clear(repo)
+            _finishunshelve(repo, oldtiprev, tr, activebookmark)
+            unshelvecleanup(ui, repo, basename, opts)
     finally:
         if tr:
             tr.release()
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -6158,6 +6158,8 @@
            _('abort an incomplete unshelve operation')),
           ('c', 'continue', None,
            _('continue an incomplete unshelve operation')),
+          ('i', 'interactive', None,
+           _('use interactive mode')),
           ('k', 'keep', None,
            _('keep shelve after unshelving')),
           ('n', 'name', '',



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


More information about the Mercurial-devel mailing list