uncommit: abort if an explicitly given file cannot be uncommitted (BC)
authorMatt Harbison <matt_harbison@yahoo.com>
Tue, 02 Apr 2019 22:42:01 -0400
changeset 4506 79de4e86d9a4
parent 4505 cc2bbe2701a3
child 4509 5875079f2ff5
child 4515 bea4c5c3b50c
uncommit: abort if an explicitly given file cannot be uncommitted (BC) This corresponds to f4147ca63d39 in the core uncommit extension.
CHANGELOG
hgext3rd/evolve/cmdrewrite.py
tests/test-uncommit.t
--- a/CHANGELOG	Thu Apr 11 17:45:36 2019 +0800
+++ b/CHANGELOG	Tue Apr 02 22:42:01 2019 -0400
@@ -12,6 +12,7 @@
   * evolve: share evolve related cache between `shares`
   * evolve: improved compatibility with narrow repositories,
   * evolve: preserve --[no-]update value over --continue,
+  * uncommit: abort if an explicitly given file cannot be uncommitted
 
 8.4.1 - in progress
 -------------------
--- a/hgext3rd/evolve/cmdrewrite.py	Thu Apr 11 17:45:36 2019 +0800
+++ b/hgext3rd/evolve/cmdrewrite.py	Tue Apr 02 22:42:01 2019 -0400
@@ -520,17 +520,47 @@
         if disallowunstable and not onahead:
             raise error.Abort(_("cannot uncommit in the middle of a stack"))
 
+        match = scmutil.match(old, pats, opts)
+
+        # Check all explicitly given files; abort if there's a problem.
+        if match.files():
+            s = old.status(old.p1(), match, listclean=True)
+            eligible = set(s.added) | set(s.modified) | set(s.removed)
+
+            badfiles = set(match.files()) - eligible
+
+            # Naming a parent directory of an eligible file is OK, even
+            # if not everything tracked in that directory can be
+            # uncommitted.
+            if badfiles:
+                badfiles -= set([f for f in util.dirs(eligible)])
+
+            try:
+                uipathfn = scmutil.getuipathfn(repo)
+            except AttributeError:
+                uipathfn = match.rel   # <= 4.9
+
+            for f in sorted(badfiles):
+                if f in s.clean:
+                    hint = _(b"file was not changed in working directory "
+                             b"parent")
+                elif repo.wvfs.exists(f):
+                    hint = _(b"file was untracked in working directory parent")
+                else:
+                    hint = _(b"file does not exist")
+
+                raise error.Abort(_(b'cannot uncommit "%s"')
+                                  % uipathfn(f), hint=hint)
+
         # Recommit the filtered changeset
         tr = repo.transaction('uncommit')
         if interactive:
             opts['all'] = True
-            match = scmutil.match(old, pats, opts)
             newid = _interactiveuncommit(ui, repo, old, match)
         else:
             newid = None
             includeorexclude = opts.get('include') or opts.get('exclude')
             if (pats or includeorexclude or opts.get('all')):
-                match = scmutil.match(old, pats, opts)
                 if not (opts['message'] or opts['logfile']):
                     opts['message'] = old.description()
                 message = cmdutil.logmessage(ui, opts)
--- a/tests/test-uncommit.t	Thu Apr 11 17:45:36 2019 +0800
+++ b/tests/test-uncommit.t	Tue Apr 02 22:42:01 2019 -0400
@@ -514,3 +514,22 @@
   (use 'hg prune .' to remove it)
   $ hg status
   ? foo
+
+Bad explicit paths abort, like the bundled commit extension
+
+  $ hg uncommit foo
+  abort: cannot uncommit "foo"
+  (file was untracked in working directory parent)
+  [255]
+
+  $ hg ci -Aqm 'add foo'
+  $ hg uncommit bar
+  abort: cannot uncommit "bar"
+  (file does not exist)
+  [255]
+  $ hg uncommit d
+  abort: cannot uncommit "d"
+  (file was not changed in working directory parent)
+  [255]
+
+  $ hg status