diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -673,8 +673,7 @@ ('a', 'abort', False, _('abort an interrupted rebase')), ('', 'auto-orphans', '', _('automatically rebase orphan revisions ' 'in the specified revset (EXPERIMENTAL)')), - ] + - cmdutil.formatteropts, + ] + cmdutil.dryrunopts + cmdutil.formatteropts, _('[-s REV | -b REV] [-d REV] [OPTION]')) def rebase(ui, repo, **opts): """move changeset (and descendants) to a different branch @@ -798,6 +797,13 @@ """ inmemory = ui.configbool('rebase', 'experimental.inmemory') + dryrun = opts.get(r'dry_run') + if dryrun: + if opts.get(r'abort'): + raise error.Abort(_('cannot specify both --dry-run and --abort')) + if opts.get(r'continue'): + raise error.Abort(_('cannot specify both --dry-run and --continue')) + if (opts.get(r'continue') or opts.get(r'abort') or repo.currenttransaction() is not None): # in-memory rebase is not compatible with resuming rebases. @@ -814,7 +820,18 @@ opts[r'rev'] = [revsetlang.formatspec('%ld and orphan()', userrevs)] opts[r'dest'] = '_destautoorphanrebase(SRC)' - if inmemory: + if dryrun: + try: + overrides = {('rebase', 'singletransaction'): True} + with ui.configoverride(overrides, 'rebase'): + _origrebase(ui, repo, inmemory=True, dryrun=dryrun, **opts) + except error.InMemoryMergeConflictsError: + ui.status(_('hit a merge conflict\n')) + else: + ui.status(_('there will be no conflict, you can rebase\n')) + finally: + _origrebase(ui, repo, abort=True) + elif inmemory: try: # in-memory merge doesn't support conflicts, so if we hit any, abort # and re-run as an on-disk merge. @@ -824,12 +841,12 @@ except error.InMemoryMergeConflictsError: ui.warn(_('hit merge conflicts; re-running rebase without in-memory' ' merge\n')) - _origrebase(ui, repo, **{r'abort': True}) + _origrebase(ui, repo, abort=True) return _origrebase(ui, repo, inmemory=False, **opts) else: return _origrebase(ui, repo, **opts) -def _origrebase(ui, repo, inmemory=False, **opts): +def _origrebase(ui, repo, inmemory=False, dryrun=None, **opts): opts = pycompat.byteskwargs(opts) rbsrt = rebaseruntime(repo, ui, inmemory, opts) @@ -902,7 +919,8 @@ dsguard = dirstateguard.dirstateguard(repo, 'rebase') with util.acceptintervention(dsguard): rbsrt._performrebase(tr) - rbsrt._finishrebase() + if not dryrun: + rbsrt._finishrebase() def _definedestmap(ui, repo, inmemory, destf=None, srcf=None, basef=None, revf=None, destspace=None): diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t --- a/tests/test-rebase-inmemory.t +++ b/tests/test-rebase-inmemory.t @@ -155,4 +155,169 @@ |/ o 0: b173517d0057 'a' +Test dry-run rebasing + $ hg init skrepo + $ cd skrepo + $ echo a>a + $ hg ci -Aqma + $ echo b>b + $ hg ci -Aqmb + $ echo c>c + $ hg ci -Aqmc + $ echo d>d + $ hg ci -Aqmd + $ echo e>e + $ hg ci -Aqme + $ hg up 1 -q + $ echo f>f + $ hg ci -Amf + adding f + created new head + $ echo g>g + $ hg ci -Aqmg + $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" + @ 6:baf10c5166d4 test + | g + | + o 5:6343ca3eff20 test + | f + | + | o 4:e860deea161a test + | | e + | | + | o 3:055a42cdd887 test + | | d + | | + | o 2:177f92b77385 test + |/ c + | + o 1:d2ae7f538514 test + | b + | + o 0:cb9a9f314b8b test + a + +Make sure it throws error while passing --continue or --abort with --dry-run + $ hg rebase -s 2 -d 6 -n --continue + abort: cannot specify both --dry-run and --continue + [255] + $ hg rebase -s 2 -d 6 -n --abort + abort: cannot specify both --dry-run and --abort + [255] + +Check dryrun gives correct results when there is no conflict in rebasing + $ hg rebase -s 2 -d 6 -n + rebasing 2:177f92b77385 "c" + rebasing 3:055a42cdd887 "d" + rebasing 4:e860deea161a "e" + there will be no conflict, you can rebase + rebase aborted + + $ hg diff + $ hg status + + $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" + @ 6:baf10c5166d4 test + | g + | + o 5:6343ca3eff20 test + | f + | + | o 4:e860deea161a test + | | e + | | + | o 3:055a42cdd887 test + | | d + | | + | o 2:177f92b77385 test + |/ c + | + o 1:d2ae7f538514 test + | b + | + o 0:cb9a9f314b8b test + a + +Check dryrun working with --collapse when there is no conflict + $ hg rebase -s 2 -d 6 -n --collapse + rebasing 2:177f92b77385 "c" + rebasing 3:055a42cdd887 "d" + rebasing 4:e860deea161a "e" + there will be no conflict, you can rebase + rebase aborted + +Check dryrun gives correct results when there is conflict in rebasing +Make a conflict: + $ hg up 6 -q + $ echo conflict>e + $ hg ci -Aqm "conflict with e" + $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" + @ 7:d2c195b28050 test + | conflict with e + | + o 6:baf10c5166d4 test + | g + | + o 5:6343ca3eff20 test + | f + | + | o 4:e860deea161a test + | | e + | | + | o 3:055a42cdd887 test + | | d + | | + | o 2:177f92b77385 test + |/ c + | + o 1:d2ae7f538514 test + | b + | + o 0:cb9a9f314b8b test + a + + $ hg rebase -s 2 -d 7 -n + rebasing 2:177f92b77385 "c" + rebasing 3:055a42cdd887 "d" + rebasing 4:e860deea161a "e" + merging e + transaction abort! + rollback completed + hit a merge conflict + rebase aborted + $ hg diff + $ hg status + $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" + @ 7:d2c195b28050 test + | conflict with e + | + o 6:baf10c5166d4 test + | g + | + o 5:6343ca3eff20 test + | f + | + | o 4:e860deea161a test + | | e + | | + | o 3:055a42cdd887 test + | | d + | | + | o 2:177f92b77385 test + |/ c + | + o 1:d2ae7f538514 test + | b + | + o 0:cb9a9f314b8b test + a + +Check dryrun working with --collapse when there is conflicts + $ hg rebase -s 2 -d 7 -n --collapse + rebasing 2:177f92b77385 "c" + rebasing 3:055a42cdd887 "d" + rebasing 4:e860deea161a "e" + merging e + hit a merge conflict + rebase aborted