diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2547,15 +2547,32 @@ def graft(ui, repo, *revs, **opts): if not revs: return -1 + # analyze revs for earlier grafts + ids = {} + for ctx in repo.set("%ld", revs): + ids[ctx.hex()] = ctx.rev() + n = ctx.extra().get('source') + if n: + ids[n] = ctx.rev() + # check ancestors for earlier grafts ui.debug('scanning for duplicate grafts\n') for ctx in repo.set("::. - ::%ld", revs): n = ctx.extra().get('source') - if n and n in repo: + if n in ids: r = repo[n].rev() if r in revs: ui.warn(_('skipping already grafted revision %s\n') % r) revs.remove(r) + elif ids[n] in revs: + ui.warn(_('skipping already grafted revision %s ' + '(same origin %d)\n') % (ids[n], r)) + revs.remove(ids[n]) + elif ctx.hex() in ids: + r = ids[ctx.hex()] + ui.warn(_('skipping already grafted revision %s ' + '(was grafted from %d)\n') % (r, ctx.rev())) + revs.remove(r) if not revs: return -1 diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -255,3 +255,25 @@ Graft again onto another branch should p 2 +Disallow grafting an already grafted cset onto its original branch + $ hg up -q 6 + $ hg graft 7 + skipping already grafted revision 7 (was grafted from 2) + [255] + +Disallow grafting already grafted csets with the same origin onto each other + $ hg up -q 13 + $ hg graft 2 + skipping already grafted revision 2 + [255] + $ hg graft 7 + skipping already grafted revision 7 (same origin 2) + [255] + + $ hg up -q 7 + $ hg graft 2 + skipping already grafted revision 2 + [255] + $ hg graft tip + skipping already grafted revision 13 (same origin 2) + [255]