Details
Details
- Reviewers
dlax durin42 - Group Reviewers
hg-reviewers - Commits
- rHG98f97eb20597: rewriteutil: use precheck() in uncommit and amend commands
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
( )
dlax | |
durin42 |
hg-reviewers |
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/uncommit.py (13 lines) | |||
M | mercurial/commands.py (9 lines) | |||
M | tests/test-amend.t (1 line) | |||
M | tests/test-commit-amend.t (1 line) | |||
M | tests/test-uncommit.t (1 line) |
from mercurial import ( | from mercurial import ( | ||||
cmdutil, | cmdutil, | ||||
commands, | commands, | ||||
context, | context, | ||||
copies, | copies, | ||||
error, | error, | ||||
node, | node, | ||||
obsolete, | |||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
rewriteutil, | |||||
scmutil, | scmutil, | ||||
) | ) | ||||
cmdtable = {} | cmdtable = {} | ||||
command = registrar.command(cmdtable) | command = registrar.command(cmdtable) | ||||
configtable = {} | configtable = {} | ||||
configitem = registrar.configitem(configtable) | configitem = registrar.configitem(configtable) | ||||
This command undoes the effect of a local commit, returning the affected | This command undoes the effect of a local commit, returning the affected | ||||
files to their uncommitted state. This means that files modified or | files to their uncommitted state. This means that files modified or | ||||
deleted in the changeset will be left unchanged, and so will remain | deleted in the changeset will be left unchanged, and so will remain | ||||
modified in the working directory. | modified in the working directory. | ||||
""" | """ | ||||
opts = pycompat.byteskwargs(opts) | opts = pycompat.byteskwargs(opts) | ||||
with repo.wlock(), repo.lock(): | with repo.wlock(), repo.lock(): | ||||
wctx = repo[None] | |||||
if not pats and not repo.ui.configbool('experimental', | if not pats and not repo.ui.configbool('experimental', | ||||
'uncommitondirtywdir'): | 'uncommitondirtywdir'): | ||||
cmdutil.bailifchanged(repo) | cmdutil.bailifchanged(repo) | ||||
if wctx.parents()[0].node() == node.nullid: | |||||
raise error.Abort(_("cannot uncommit null changeset")) | |||||
if len(wctx.parents()) > 1: | |||||
raise error.Abort(_("cannot uncommit while merging")) | |||||
old = repo['.'] | old = repo['.'] | ||||
if not old.mutable(): | rewriteutil.precheck(repo, [old.rev()], 'uncommit') | ||||
raise error.Abort(_('cannot uncommit public changesets')) | |||||
if len(old.parents()) > 1: | if len(old.parents()) > 1: | ||||
raise error.Abort(_("cannot uncommit merge changeset")) | raise error.Abort(_("cannot uncommit merge changeset")) | ||||
allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt) | |||||
if not allowunstable and old.children(): | |||||
raise error.Abort(_('cannot uncommit changeset with children')) | |||||
with repo.transaction('uncommit'): | with repo.transaction('uncommit'): | ||||
match = scmutil.match(old, pats, opts) | match = scmutil.match(old, pats, opts) | ||||
newid = _commitfiltered(repo, old, match, opts.get('keep')) | newid = _commitfiltered(repo, old, match, opts.get('keep')) | ||||
if newid is None: | if newid is None: | ||||
ui.status(_("nothing to uncommit\n")) | ui.status(_("nothing to uncommit\n")) | ||||
return 1 | return 1 | ||||
merge as mergemod, | merge as mergemod, | ||||
obsolete, | obsolete, | ||||
patch, | patch, | ||||
phases, | phases, | ||||
pycompat, | pycompat, | ||||
rcutil, | rcutil, | ||||
registrar, | registrar, | ||||
revsetlang, | revsetlang, | ||||
rewriteutil, | |||||
scmutil, | scmutil, | ||||
server, | server, | ||||
sshserver, | sshserver, | ||||
streamclone, | streamclone, | ||||
tags as tagsmod, | tags as tagsmod, | ||||
templatekw, | templatekw, | ||||
ui as uimod, | ui as uimod, | ||||
util, | util, | ||||
repo[None].parents()[0].p2().branch() != branch: | repo[None].parents()[0].p2().branch() != branch: | ||||
raise error.Abort(_('can only close branch heads')) | raise error.Abort(_('can only close branch heads')) | ||||
if opts.get('amend'): | if opts.get('amend'): | ||||
if ui.configbool('ui', 'commitsubrepos'): | if ui.configbool('ui', 'commitsubrepos'): | ||||
raise error.Abort(_('cannot amend with ui.commitsubrepos enabled')) | raise error.Abort(_('cannot amend with ui.commitsubrepos enabled')) | ||||
old = repo['.'] | old = repo['.'] | ||||
if not old.mutable(): | rewriteutil.precheck(repo, [old.rev()], 'amend') | ||||
raise error.Abort(_('cannot amend public changesets')) | |||||
if len(repo[None].parents()) > 1: | |||||
raise error.Abort(_('cannot amend while merging')) | |||||
allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt) | |||||
if not allowunstable and old.children(): | |||||
raise error.Abort(_('cannot amend changeset with children')) | |||||
# Currently histedit gets confused if an amend happens while histedit | # Currently histedit gets confused if an amend happens while histedit | ||||
# is in progress. Since we have a checkunfinished command, we are | # is in progress. Since we have a checkunfinished command, we are | ||||
# temporarily honoring it. | # temporarily honoring it. | ||||
# | # | ||||
# Note: eventually this guard will be removed. Please do not expect | # Note: eventually this guard will be removed. Please do not expect | ||||
# this behavior to remain. | # this behavior to remain. | ||||
if not obsolete.isenabled(repo, obsolete.createmarkersopt): | if not obsolete.isenabled(repo, obsolete.createmarkersopt): |
#endif | #endif | ||||
Cannot amend public changeset | Cannot amend public changeset | ||||
$ hg phase -r A --public | $ hg phase -r A --public | ||||
$ hg update -C -q A | $ hg update -C -q A | ||||
$ hg amend -m AMEND | $ hg amend -m AMEND | ||||
abort: cannot amend public changesets | abort: cannot amend public changesets | ||||
(see 'hg help phases' for details) | |||||
[255] | [255] | ||||
Amend a merge changeset | Amend a merge changeset | ||||
$ hg init $TESTTMP/repo3 | $ hg init $TESTTMP/repo3 | ||||
$ cd $TESTTMP/repo3 | $ cd $TESTTMP/repo3 | ||||
$ hg debugdrawdag <<'EOS' | $ hg debugdrawdag <<'EOS' | ||||
> C | > C |
$ hg ci -Am 'base' | $ hg ci -Am 'base' | ||||
adding a | adding a | ||||
Refuse to amend public csets: | Refuse to amend public csets: | ||||
$ hg phase -r . -p | $ hg phase -r . -p | ||||
$ hg ci --amend | $ hg ci --amend | ||||
abort: cannot amend public changesets | abort: cannot amend public changesets | ||||
(see 'hg help phases' for details) | |||||
[255] | [255] | ||||
$ hg phase -r . -f -d | $ hg phase -r . -f -d | ||||
$ echo a >> a | $ echo a >> a | ||||
$ hg ci -Am 'base1' | $ hg ci -Am 'base1' | ||||
Nothing to amend: | Nothing to amend: | ||||
-X --exclude PATTERN [+] exclude names matching the given patterns | -X --exclude PATTERN [+] exclude names matching the given patterns | ||||
(some details hidden, use --verbose to show complete help) | (some details hidden, use --verbose to show complete help) | ||||
Uncommit with no commits should fail | Uncommit with no commits should fail | ||||
$ hg uncommit | $ hg uncommit | ||||
abort: cannot uncommit null changeset | abort: cannot uncommit null changeset | ||||
(no changeset checked out) | |||||
[255] | [255] | ||||
Create some commits | Create some commits | ||||
$ touch files | $ touch files | ||||
$ hg add files | $ hg add files | ||||
$ for i in a ab abc abcd abcde; do echo $i > files; echo $i > file-$i; hg add file-$i; hg commit -m "added file-$i"; done | $ for i in a ab abc abcd abcde; do echo $i > files; echo $i > file-$i; hg add file-$i; hg commit -m "added file-$i"; done | ||||
$ ls | $ ls |