copy: add option to unmark file as copied
To unmark a file as copied, the user currently has to do this:
hg forget <dest>
hg add <dest>
The new command simplifies that to:
hg copy --forget <dest>
That's not a very big improvement, but I'm planning to also teach `hg
copy [--forget]` a `--at-rev` argument for marking/unmarking copies
after commit (usually with `--at-rev .`).
Differential Revision: https://phab.mercurial-scm.org/D8029
--- a/mercurial/cmdutil.py Tue Feb 11 11:18:52 2020 +0100
+++ b/mercurial/cmdutil.py Fri Dec 20 15:50:13 2019 -0800
@@ -1410,12 +1410,15 @@
def copy(ui, repo, pats, opts, rename=False):
+ check_incompatible_arguments(opts, b'forget', [b'dry_run'])
+
# called with the repo lock held
#
# hgsep => pathname that uses "/" to separate directories
# ossep => pathname that uses os.sep to separate directories
cwd = repo.getcwd()
targets = {}
+ forget = opts.get(b"forget")
after = opts.get(b"after")
dryrun = opts.get(b"dry_run")
ctx = repo[None]
@@ -1423,6 +1426,24 @@
uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
+ if forget:
+ match = scmutil.match(wctx, pats, opts)
+
+ current_copies = wctx.p1copies()
+ current_copies.update(wctx.p2copies())
+
+ for f in wctx.walk(match):
+ if f in current_copies:
+ wctx[f].markcopied(None)
+ elif match.exact(f):
+ ui.warn(
+ _(
+ b'%s: not unmarking as copy - file is not marked as copied\n'
+ )
+ % uipathfn(f)
+ )
+ return
+
def walkpat(pat):
srcs = []
m = scmutil.match(ctx, [pat], opts, globbed=True)
--- a/mercurial/commands.py Tue Feb 11 11:18:52 2020 +0100
+++ b/mercurial/commands.py Fri Dec 20 15:50:13 2019 -0800
@@ -2309,6 +2309,7 @@
@command(
b'copy|cp',
[
+ (b'', b'forget', None, _(b'unmark a file as copied')),
(b'A', b'after', None, _(b'record a copy that has already occurred')),
(
b'f',
@@ -2333,8 +2334,11 @@
exist in the working directory. If invoked with -A/--after, the
operation is recorded, but no copying is performed.
- This command takes effect with the next commit. To undo a copy
- before that, see :hg:`revert`.
+ To undo marking a file as copied, use --forget. With that option,
+ all given (positional) arguments are unmarked as copies. The destination
+ file(s) will be left in place (still tracked).
+
+ This command takes effect with the next commit.
Returns 0 on success, 1 if errors are encountered.
"""
--- a/relnotes/next Tue Feb 11 11:18:52 2020 +0100
+++ b/relnotes/next Fri Dec 20 15:50:13 2019 -0800
@@ -12,6 +12,8 @@
commits that are being merged, when there are conflicts. Also works
for conflicts caused by e.g. `hg graft`.
+ * `hg copy --forget` can be used to unmark a file as copied.
+
== New Experimental Features ==
--- a/tests/test-completion.t Tue Feb 11 11:18:52 2020 +0100
+++ b/tests/test-completion.t Fri Dec 20 15:50:13 2019 -0800
@@ -257,7 +257,7 @@
commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
config: untrusted, edit, local, global, template
continue: dry-run
- copy: after, force, include, exclude, dry-run
+ copy: forget, after, force, include, exclude, dry-run
debugancestor:
debugapplystreamclonebundle:
debugbuilddag: mergeable-file, overwritten-file, new-file
--- a/tests/test-copy.t Tue Feb 11 11:18:52 2020 +0100
+++ b/tests/test-copy.t Fri Dec 20 15:50:13 2019 -0800
@@ -262,5 +262,62 @@
xyzzy: not overwriting - file exists
('hg copy --after' to record the copy)
[1]
+ $ hg co -qC .
+ $ rm baz xyzzy
+
+
+Test unmarking copy of a single file
+
+# Set up by creating a copy
+ $ hg cp bar baz
+# Test uncopying a non-existent file
+ $ hg copy --forget non-existent
+ non-existent: $ENOENT$
+# Test uncopying an tracked but unrelated file
+ $ hg copy --forget foo
+ foo: not unmarking as copy - file is not marked as copied
+# Test uncopying a copy source
+ $ hg copy --forget bar
+ bar: not unmarking as copy - file is not marked as copied
+# baz should still be marked as a copy
+ $ hg st -C
+ A baz
+ bar
+# Test the normal case
+ $ hg copy --forget baz
+ $ hg st -C
+ A baz
+# Test uncopy with matching an non-matching patterns
+ $ hg cp bar baz --after
+ $ hg copy --forget bar baz
+ bar: not unmarking as copy - file is not marked as copied
+ $ hg st -C
+ A baz
+# Test uncopy with no exact matches
+ $ hg cp bar baz --after
+ $ hg copy --forget .
+ $ hg st -C
+ A baz
+ $ hg forget baz
+ $ rm baz
+
+Test unmarking copy of a directory
+
+ $ mkdir dir
+ $ echo foo > dir/foo
+ $ echo bar > dir/bar
+ $ hg add dir
+ adding dir/bar
+ adding dir/foo
+ $ hg ci -m 'add dir/'
+ $ hg cp dir dir2
+ copying dir/bar to dir2/bar
+ copying dir/foo to dir2/foo
+ $ touch dir2/untracked
+ $ hg copy --forget dir2
+ $ hg st -C
+ A dir2/bar
+ A dir2/foo
+ ? dir2/untracked
$ cd ..