diff -r 8be0c63535b5 -r 7c4b98a4e536 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Fri Dec 20 15:50:13 2019 -0800 +++ b/mercurial/cmdutil.py Tue Jan 28 14:07:57 2020 -0800 @@ -1427,14 +1427,33 @@ 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): + rev = opts[b'at_rev'] + if rev: + ctx = scmutil.revsingle(repo, rev) + else: + ctx = repo[None] + if ctx.rev() is None: + new_ctx = ctx + else: + if len(ctx.parents()) > 1: + raise error.Abort(_(b'cannot unmark copy in merge commit')) + # avoid cycle context -> subrepo -> cmdutil + from . import context + + rewriteutil.precheck(repo, [ctx.rev()], b'uncopy') + new_ctx = context.overlayworkingctx(repo) + new_ctx.setbase(ctx.p1()) + mergemod.graft(repo, ctx, wctx=new_ctx) + + 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: - wctx[f].markcopied(None) + new_ctx[f].markcopied(None) elif match.exact(f): ui.warn( _( @@ -1442,8 +1461,25 @@ ) % uipathfn(f) ) + + if ctx.rev() is not None: + with repo.lock(): + mem_ctx = new_ctx.tomemctx_for_amend(ctx) + new_node = mem_ctx.commit() + + if repo.dirstate.p1() == ctx.node(): + with repo.dirstate.parentchange(): + scmutil.movedirstate(repo, repo[new_node]) + replacements = {ctx.node(): [new_node]} + scmutil.cleanupnodes( + repo, replacements, b'uncopy', fixphase=True + ) + return + if opts.get(b'at_rev'): + raise error.Abort(_("--at-rev is only supported with --forget")) + def walkpat(pat): srcs = [] m = scmutil.match(ctx, [pat], opts, globbed=True)