diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1694,6 +1694,25 @@ return errors != 0 +def uncopy(ui, repo, pats, opts): + ctx = repo[None] + + match = scmutil.match(ctx, pats, opts) + + current_copies = ctx.p1copies() + current_copies.update(ctx.p2copies()) + + uipathfn = scmutil.getuipathfn(repo) + for f in ctx.walk(match): + if f in current_copies: + ctx[f].markcopied(None) + elif match.exact(f): + ui.warn( + _(b'%s: not uncopying - file is not marked as copied\n') + % uipathfn(f) + ) + + ## facility to let extension process additional data into an import patch # list of identifier to be executed in order extrapreimport = [] # run before commit diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -7492,6 +7492,19 @@ @command( + b'uncopy', + walkopts, + _(b'[OPTION]... DEST...'), + helpcategory=command.CATEGORY_FILE_CONTENTS, +) +def uncopy(ui, repo, *pats, **opts): + """unmark files as copied""" + opts = pycompat.byteskwargs(opts) + with repo.wlock(False): + return cmdutil.uncopy(ui, repo, pats, opts) + + +@command( b'unshelve', [ (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')), diff --git a/relnotes/next b/relnotes/next --- a/relnotes/next +++ b/relnotes/next @@ -1,5 +1,7 @@ == New Features == + * `hg uncopy` can be used to unmark a file as copied. + == New Experimental Features == diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -54,6 +54,7 @@ tags tip unbundle + uncopy unshelve update verify @@ -356,6 +357,7 @@ tags: template tip: patch, git, style, template unbundle: update + uncopy: include, exclude unshelve: abort, continue, interactive, keep, name, tool, date update: clean, check, merge, date, rev, tool verify: full diff --git a/tests/test-copy.t b/tests/test-copy.t --- a/tests/test-copy.t +++ b/tests/test-copy.t @@ -262,5 +262,62 @@ xyzzy: not overwriting - file exists ('hg copy --after' to record the copy) [1] + $ hg co -qC . + $ rm baz xyzzy + + +Test uncopy of a single file + +# Set up by creating a copy + $ hg cp bar baz +# Test uncopying a non-existent file + $ hg uncopy non-existent + non-existent: $ENOENT$ +# Test uncopying an tracked but unrelated file + $ hg uncopy foo + foo: not uncopying - file is not marked as copied +# Test uncopying a copy source + $ hg uncopy bar + bar: not uncopying - 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 uncopy baz + $ hg st -C + A baz +# Test uncopy with matching an non-matching patterns + $ hg cp bar baz --after + $ hg uncopy bar baz + bar: not uncopying - file is not marked as copied + $ hg st -C + A baz +# Test uncopy with no exact matches + $ hg cp bar baz --after + $ hg uncopy . + $ hg st -C + A baz + $ hg forget baz + $ rm baz + +Test uncopy 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 uncopy dir2 + $ hg st -C + A dir2/bar + A dir2/foo + ? dir2/untracked $ cd .. diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t --- a/tests/test-globalopts.t +++ b/tests/test-globalopts.t @@ -337,6 +337,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: @@ -469,6 +470,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: diff --git a/tests/test-help-hide.t b/tests/test-help-hide.t --- a/tests/test-help-hide.t +++ b/tests/test-help-hide.t @@ -41,6 +41,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: @@ -177,6 +178,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -93,6 +93,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: @@ -221,6 +222,7 @@ copy mark files as copied for the next commit diff diff repository (or selected files) grep search for a pattern in specified files + uncopy unmark files as copied Change navigation: @@ -2754,6 +2756,13 @@ apply one or more bundle files + + uncopy + + + unmark files as copied + + unshelve diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t --- a/tests/test-hgweb-json.t +++ b/tests/test-hgweb-json.t @@ -2226,6 +2226,10 @@ "topic": "unbundle" }, { + "summary": "unmark files as copied", + "topic": "uncopy" + }, + { "summary": "restore a shelved change to the working directory", "topic": "unshelve" },