cmdstate: introduce a "saver" contextmanager and use it in place of save()
Previously, the state was only saved in some paths out of these functions. This
can be problematic, if the user ctrl-c's (or `kill -9`'s) the process, or we
exit out of `relocate` for anything besides the "expected" reason, we won't
record that we were in the middle of an evolve.
One of our users has discovered that this leaves hg in a weird state; the user
did something like this:
```
$ hg evolve
<something goes wrong with the merge tool, hits ctrl-c>
<deals with the merge conflicts>
$ hg evolve --continue
abort: no interrupted evolve to continue
$ hg evolve
abort: uncommitted changes
# Note: commands.status.verbose=True is set.
$ hg status
M foo
# The repository is in an unfinished *update* state.
# No unresolved merge conflicts
# To continue: hg update
```
The user did an `hg update`, but it didn't actually do anything besides take it
out of the unfinished update state (the files were still dirty in the working
directory).
Testing the `--no-update` flag to `hg evolve` command
=====================================================
There is an `--update` flag to `hg evolve` command which defaults to False. The
`--update` flag updates to the head of the evolved revisions. If you don't want
to change your working directory or update your working directory to its
successor after hg evolve, `hg evolve --no-update` is the thing for you.
This patch tests that flag.
Setup
-----
$ cat >> $HGRCPATH <<EOF
> [alias]
> glog = log -GT "{rev}:{node|short} {desc}\n ({bookmarks}) {phase}"
> [extensions]
> EOF
$ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
$ hg init stoprepo
$ cd stoprepo
$ echo ".*\.orig" > .hgignore
$ hg add .hgignore
$ hg ci -m "added hgignore"
$ for ch in a b c d; do echo foo > $ch; hg add $ch; hg ci -qm "added "$ch; done;
$ hg glog
@ 4:c41c793e0ef1 added d
| () draft
o 3:ca1b80f7960a added c
| () draft
o 2:b1661037fa25 added b
| () draft
o 1:c7586e2a9264 added a
| () draft
o 0:8fa14d15e168 added hgignore
() draft
Making sure we stay where we were if current wdir parent was not obsoleted
--------------------------------------------------------------------------
$ hg up .^^
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ echo bar > b
$ hg amend
2 new orphan changesets
$ hg glog
@ 5:7ed0642d644b added b
| () draft
| * 4:c41c793e0ef1 added d
| | () draft
| * 3:ca1b80f7960a added c
| | () draft
| x 2:b1661037fa25 added b
|/ () draft
o 1:c7586e2a9264 added a
| () draft
o 0:8fa14d15e168 added hgignore
() draft
There is no 'working directory is now at' message because we didn't update
$ hg evolve --all --no-update
move:[3] added c
atop:[5] added b
move:[4] added d
$ hg glog
o 7:b6b20b8eefdc added d
| () draft
o 6:7c46f743e62f added c
| () draft
@ 5:7ed0642d644b added b
| () draft
o 1:c7586e2a9264 added a
| () draft
o 0:8fa14d15e168 added hgignore
() draft
Updating to successor when working directory parent is obsoleted by evolution
-----------------------------------------------------------------------------
$ hg prev
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
[1] added a
$ echo bar > a
$ hg amend
3 new orphan changesets
$ hg up 7ed0642d644b
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg glog
o 8:3d41537b44ca added a
| () draft
| * 7:b6b20b8eefdc added d
| | () draft
| * 6:7c46f743e62f added c
| | () draft
| @ 5:7ed0642d644b added b
| | () draft
| x 1:c7586e2a9264 added a
|/ () draft
o 0:8fa14d15e168 added hgignore
() draft
$ hg evolve --all --any --no-update
move:[5] added b
atop:[8] added a
move:[6] added c
move:[7] added d
working directory is now at 12c720cb3782
$ hg glog
o 11:a74d9f22ba3f added d
| () draft
o 10:958f5155e8cd added c
| () draft
@ 9:12c720cb3782 added b
| () draft
o 8:3d41537b44ca added a
| () draft
o 0:8fa14d15e168 added hgignore
() draft