Patchwork D6596: unshelve: make unshelve accept files (issue6162)

login
register
mail settings
Submitter phabricator
Date July 4, 2019, 3 p.m.
Message ID <differential-rev-PHID-DREV-rju6zcgmuzkr4slubbb2-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/40756/
State New
Headers show

Comments

phabricator - July 4, 2019, 3 p.m.
navaneeth.suresh created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
navaneeth.suresh updated this revision to Diff 15738.
pulkit added a comment.
navaneeth.suresh updated this revision to Diff 15739.
navaneeth.suresh marked an inline comment as done.
navaneeth.suresh updated this revision to Diff 15757.
navaneeth.suresh retitled this revision from "unshelve: add interactive mode (issue6162)" to "unshelve: make unshelve accept files (issue6162)".
navaneeth.suresh edited the summary of this revision.
navaneeth.suresh marked 2 inline comments as done.
navaneeth.suresh marked an inline comment as done.


  Didn't look at the actual implementation yet.

INLINE COMMENTS

> shelve.py:990
> +        filesinclude = []
> +        if interactive:
> +            for file in files:

The interactive flag should work the same way as it work for revert, commit and shelve commands. That's either ask hunk by hunk or pop up a curses UI.

As you suggested before, maybe we can have `-f` flag to specify files to unshelve.

> pulkit wrote in shelve.py:990
> The interactive flag should work the same way as it work for revert, commit and shelve commands. That's either ask hunk by hunk or pop up a curses UI.
> 
> As you suggested before, maybe we can have `-f` flag to specify files to unshelve.

will fix this in the next-to-next revision.

> navaneeth.suresh wrote in shelve.py:990
> will fix this in the next-to-next revision.

To have this patch in a good state to be reviewed, it will be nice you take out the addition of interactive flag to the patch where you add that functionality.

> pulkit wrote in shelve.py:990
> To have this patch in a good state to be reviewed, it will be nice you take out the addition of interactive flag to the patch where you add that functionality.

Updated the patch by replacing the `--interactive` flag with `--files`.

> test-shelve.t:1204
> +  e
> +  $ hg shelve --patch
> +  default         (1s ago)    changes to: b

add a comment here specifying that shelve should not contain `c` now.

REVISION SUMMARY
  Until now, there is no way to `unshelve` selected files only from
  the stored shelve as given in issue6162. This patch makes `unshelve`
  perform with certain files only.

REPOSITORY
  rHG Mercurial

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




To: navaneeth.suresh, #hg-reviewers
Cc: mercurial-devel
phabricator - July 4, 2019, 3 p.m.
pulkit added inline comments.

INLINE COMMENTS

> navaneeth.suresh wrote in shelve.py:990
> will fix this in the next-to-next revision.

To have this patch in a good state to be reviewed, it will be nice you take out the addition of interactive flag to the patch where you add that functionality.

REPOSITORY
  rHG Mercurial

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

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

To: navaneeth.suresh, #hg-reviewers
Cc: pulkit, mercurial-devel
phabricator - July 4, 2019, 3 p.m.
navaneeth.suresh added inline comments.
navaneeth.suresh marked 2 inline comments as done.

INLINE COMMENTS

> pulkit wrote in shelve.py:990
> To have this patch in a good state to be reviewed, it will be nice you take out the addition of interactive flag to the patch where you add that functionality.

Updated the patch by replacing the `--interactive` flag with `--files`.

REPOSITORY
  rHG Mercurial

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

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

To: navaneeth.suresh, #hg-reviewers
Cc: pulkit, mercurial-devel
phabricator - July 6, 2019, 11:38 p.m.
pulkit added inline comments.

INLINE COMMENTS

> shelve.py:842
>              repo.setparents(tmpwctx.node(), nodemod.nullid)
>              newnode = repo.commit(text=shelvectx.description(),
>                                    extra=shelvectx.extra(),

We can do filtering of files to unshelve here.

Before this `repo.commit` we have all the changes, we first commit which are needed to be unshelve, then create a shelve of rest of the changes.

REPOSITORY
  rHG Mercurial

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

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

To: navaneeth.suresh, #hg-reviewers
Cc: pulkit, mercurial-devel
phabricator - July 11, 2019, 1:18 p.m.
pulkit added a comment.


  It will be nice to add information to commit message about how thing unshelving of a subset works.

INLINE COMMENTS

> shelve.py:961
>          restorebranch(ui, repo, branchtorestore)
> -        _forgetunknownfiles(repo, shelvectx, addedbefore)
> +        if not filesinclude or (filesinclude and allfiles == filesinclude):
> +            _forgetunknownfiles(repo, shelvectx, addedbefore)

Can you explain why we are not processing this if files are present?

REPOSITORY
  rHG Mercurial

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

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

To: navaneeth.suresh, #hg-reviewers
Cc: pulkit, mercurial-devel
phabricator - July 11, 2019, 1:24 p.m.
navaneeth.suresh added inline comments.
navaneeth.suresh marked 2 inline comments as done.

INLINE COMMENTS

> pulkit wrote in shelve.py:961
> Can you explain why we are not processing this if files are present?

okay. on unshelving with `--files` flag, we don't want to clear the shelvedstate unless all the files in the shelvectx is same as the files which are requested by the user. on unshelving without `--files` flag, we can clear the shelvedstate right away. that's why i have used this condition.

REPOSITORY
  rHG Mercurial

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

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

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

Patch

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,62 @@ 
   [255]
 
   $ cd ..
+
+-- make unshelve accept files
+
+  $ 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 -f c
+  unshelving change 'default'
+  rebasing shelved changes
+  $ 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, files, 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()
@@ -942,15 +984,30 @@ 
                                           basename, pctx, tmpwctx,
                                           shelvectx, branchtorestore,
                                           activebookmark)
+        allfiles = shelvectx.files()
+        filesinclude = opts.get('files', [])
+        filesexclude = list(set(allfiles) - set(filesinclude))
+        if filesinclude:
+            match = scmutil.match(shelvectx, filesinclude, {})
+            match2 = scmutil.match(shelvectx, filesexclude, {})
+            shelvectxbackup = shelvectx
+            # shelvectx is applied on the repo and shelvectxnew is
+            # saved for later.
+            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 filesinclude or (filesinclude and allfiles == 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')),
+          ('f', 'files', [],
+           _('perform unshelve on selected files'), _('FILE')),
           ('k', 'keep', None,
            _('keep shelve after unshelving')),
           ('n', 'name', '',
@@ -6165,7 +6167,7 @@ 
           ('t', 'tool', '', _('specify merge tool')),
           ('', 'date', '',
            _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
-         _('hg unshelve [[-n] SHELVED]'),
+         _('hg unshelve [-f FILE] [-n SHELVED]'),
          helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def unshelve(ui, repo, *shelved, **opts):
     """restore a shelved change to the working directory