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 | ||||