rebase: add --confirm option
This feature adds a functionality in rebase to confirm before applying
changes.
When there is no conflict and user confirm to apply actions, we just
finish the unfinished rebase. But when there is a conflict and user
confirm to apply actions then we can't just finish rebasing using
rbsrt._finishrebase() because in-memory merge doesn't support conflicts, so
we have to abort and run on-disk merge in this case.
And if user doesn't confirm to apply actions then simply abort the rebase.
Differential Revision: https://phab.mercurial-scm.org/D3870
--- a/hgext/rebase.py Wed Jul 11 16:29:23 2018 -0700
+++ b/hgext/rebase.py Sat Jun 30 12:42:49 2018 +0530
@@ -677,7 +677,7 @@
('a', 'abort', False, _('abort an interrupted rebase')),
('', 'auto-orphans', '', _('automatically rebase orphan revisions '
'in the specified revset (EXPERIMENTAL)')),
- ] + cmdutil.dryrunopts + cmdutil.formatteropts,
+ ] + cmdutil.dryrunopts + cmdutil.formatteropts + cmdutil.confirmopts,
_('[-s REV | -b REV] [-d REV] [OPTION]'))
def rebase(ui, repo, **opts):
"""move changeset (and descendants) to a different branch
@@ -808,6 +808,14 @@
raise error.Abort(_('cannot specify both --dry-run and --abort'))
if opts.get('continue'):
raise error.Abort(_('cannot specify both --dry-run and --continue'))
+ if opts.get('confirm'):
+ dryrun = True
+ if opts.get('dry_run'):
+ raise error.Abort(_('cannot specify both --confirm and --dry-run'))
+ if opts.get('abort'):
+ raise error.Abort(_('cannot specify both --confirm and --abort'))
+ if opts.get('continue'):
+ raise error.Abort(_('cannot specify both --confirm and --continue'))
if (opts.get('continue') or opts.get('abort') or
repo.currenttransaction() is not None):
@@ -844,8 +852,14 @@
def _dryrunrebase(ui, repo, opts):
rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
- ui.status(_('starting dry-run rebase; repository will not be changed\n'))
+ confirm = opts.get('confirm')
+ if confirm:
+ ui.status(_('starting rebase...\n'))
+ else:
+ ui.status(_('starting dry-run rebase; repository will not be '
+ 'changed\n'))
with repo.wlock(), repo.lock():
+ needsabort = True
try:
overrides = {('rebase', 'singletransaction'): True}
with ui.configoverride(overrides, 'rebase'):
@@ -853,15 +867,35 @@
leaveunfinished=True)
except error.InMemoryMergeConflictsError:
ui.status(_('hit a merge conflict\n'))
+ if confirm:
+ # abort as in-memory merge doesn't support conflict
+ rbsrt._prepareabortorcontinue(isabort=True, backup=False,
+ suppwarns=True)
+ needsabort = False
+ if not ui.promptchoice(_(b'apply changes (yn)?'
+ b'$$ &Yes $$ &No')):
+ _dorebase(ui, repo, opts, inmemory=False)
return 1
else:
- ui.status(_('dry-run rebase completed successfully; run without '
- '-n/--dry-run to perform this rebase\n'))
+ if confirm:
+ ui.status(_('rebase completed successfully\n'))
+ if not ui.promptchoice(_(b'apply changes (yn)?'
+ b'$$ &Yes $$ &No')):
+ # finish unfinished rebase
+ rbsrt._finishrebase()
+ else:
+ rbsrt._prepareabortorcontinue(isabort=True, backup=False,
+ suppwarns=True)
+ needsabort = False
+ else:
+ ui.status(_('dry-run rebase completed successfully; run without'
+ ' -n/--dry-run to perform this rebase\n'))
return 0
finally:
- # no need to store backup in case of dryrun
- rbsrt._prepareabortorcontinue(isabort=True, backup=False,
- suppwarns=True)
+ if needsabort:
+ # no need to store backup in case of dryrun
+ rbsrt._prepareabortorcontinue(isabort=True, backup=False,
+ suppwarns=True)
def _dorebase(ui, repo, opts, inmemory=False):
rbsrt = rebaseruntime(repo, ui, inmemory, opts)
--- a/mercurial/cmdutil.py Wed Jul 11 16:29:23 2018 -0700
+++ b/mercurial/cmdutil.py Sat Jun 30 12:42:49 2018 +0530
@@ -62,6 +62,11 @@
_('do not perform actions, just print output')),
]
+confirmopts = [
+ ('', 'confirm', None,
+ _('ask before applying actions')),
+]
+
remoteopts = [
('e', 'ssh', '',
_('specify ssh command to use'), _('CMD')),
--- a/tests/test-rebase-inmemory.t Wed Jul 11 16:29:23 2018 -0700
+++ b/tests/test-rebase-inmemory.t Sat Jun 30 12:42:49 2018 +0530
@@ -4,6 +4,7 @@
> amend=
> rebase=
> debugdrawdag=$TESTDIR/drawdag.py
+ > strip=
> [rebase]
> experimental.inmemory=1
> [diff]
@@ -156,8 +157,8 @@
o 0: b173517d0057 'a'
Test dry-run rebasing
- $ hg init skrepo
- $ cd skrepo
+ $ hg init repo3
+ $ cd repo3
$ echo a>a
$ hg ci -Aqma
$ echo b>b
@@ -323,3 +324,246 @@
merging e
hit a merge conflict
[1]
+
+==========================
+Test for --confirm option|
+==========================
+ $ cd ..
+ $ hg clone repo3 repo4 -q
+ $ cd repo4
+ $ hg strip 7 -q
+ $ 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 it gives error when both --dryrun and --confirm is used:
+ $ hg rebase -s 2 -d . --confirm --dry-run
+ abort: cannot specify both --confirm and --dry-run
+ [255]
+ $ hg rebase -s 2 -d . --confirm --abort
+ abort: cannot specify both --confirm and --abort
+ [255]
+ $ hg rebase -s 2 -d . --confirm --continue
+ abort: cannot specify both --confirm and --continue
+ [255]
+
+Test --confirm option when there are no conflicts:
+ $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
+ > n
+ > EOF
+ starting rebase...
+ rebasing 2:177f92b77385 "c"
+ rebasing 3:055a42cdd887 "d"
+ rebasing 4:e860deea161a "e"
+ rebase completed successfully
+ apply changes (yn)? n
+ $ 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
+
+ $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
+ > y
+ > EOF
+ starting rebase...
+ rebasing 2:177f92b77385 "c"
+ rebasing 3:055a42cdd887 "d"
+ rebasing 4:e860deea161a "e"
+ rebase completed successfully
+ apply changes (yn)? y
+ $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
+ o 9:9fd28f55f6dc test
+ | e
+ |
+ o 8:12cbf031f469 test
+ | d
+ |
+ o 7:c83b1da5b1ae test
+ | c
+ |
+ @ 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
+
+Test --confirm option when there is a conflict
+ $ hg up tip -q
+ $ echo ee>e
+ $ hg ci --amend -m "conflict with e" -q
+ $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
+ @ 9:906d72f66a59 test
+ | conflict with e
+ |
+ o 8:12cbf031f469 test
+ | d
+ |
+ o 7:c83b1da5b1ae test
+ | c
+ |
+ 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 4 -d . --keep --config ui.interactive=True --confirm << EOF
+ > n
+ > EOF
+ starting rebase...
+ rebasing 4:e860deea161a "e"
+ merging e
+ hit a merge conflict
+ apply changes (yn)? n
+ [1]
+ $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
+ @ 9:906d72f66a59 test
+ | conflict with e
+ |
+ o 8:12cbf031f469 test
+ | d
+ |
+ o 7:c83b1da5b1ae test
+ | c
+ |
+ 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 4 -d . --keep --config ui.interactive=True --confirm << EOF
+ > y
+ > EOF
+ starting rebase...
+ rebasing 4:e860deea161a "e"
+ merging e
+ hit a merge conflict
+ apply changes (yn)? y
+ rebasing 4:e860deea161a "e"
+ merging e
+ warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
+ unresolved conflicts (see hg resolve, then hg rebase --continue)
+ [1]
+
+ $ echo e>e
+ $ hg resolve --mark --all
+ (no more unresolved files)
+ continue: hg rebase --continue
+ $ hg rebase --continue
+ rebasing 4:e860deea161a "e"
+ $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
+ o 10:9fa3731dd6df test
+ | e
+ |
+ @ 9:906d72f66a59 test
+ | conflict with e
+ |
+ o 8:12cbf031f469 test
+ | d
+ |
+ o 7:c83b1da5b1ae test
+ | c
+ |
+ 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
+