Mercurial > evolve
view tests/test-amend.t @ 4687:313565dd75e3 stable
pick: remove transaction on the whole command (issue6037)
At its core, pick is a pretty straightforward and well-behaving command, it
uses functions already in core hg, it checks that wdir is clean and that
changeset to pick is not public, it checks if there happen to be merge
conflicts and can be --continue'd later, etc.
It is very similar to graft in core (it also uses mergemod.graft function), but
it obsoletes the original changeset. However, graft does not experience this
incorrect behavior from issue 6037.
What happens in the test case for this issue when we pick a revision that
touches both "a" and "b": mergemod.graft() takes the original changeset and
tries to apply it to the wdir, which results in "b" being marked as newly added
and ready to be committed, "a" updated with the new content and being marked as
modified, but "a" also has conflicts. Pick correctly notices this and saves its
state before asking for user intervention. So far so good. However, when the
command raises InterventionRequired to print a user-facing message and exit
while being wrapped in repo.transaction() context manager, the latter partially
undoes what mergemod.graft() did: it unmarks "b" as added. And when user
continues pick, "b" is therefore not tracked and is not included in the
resulting commit.
The transaction is not useful here, because it doesn't touch wdir (it's still
dirty), it doesn't remove pickstate (and other commands will refuse to work
until pick --abort or --continue), it just makes "b" untracked.
The solution is to use repo.transaction() only to wrap code that writes data to
hg store in the final stages of the command after all checks have passed and is
not expected to fail on trivial cases like merge conflicts. For example,
committing the picked changeset. But since pick uses repo.commit() for that,
and because that function already uses a transaction, wrapping it in another
transaction doesn't make sense.
author | Anton Shestakov <av6@dwimlabs.net> |
---|---|
date | Fri, 07 Jun 2019 18:14:48 +0800 |
parents | 536c67823962 |
children | 588b3484c131 |
line wrap: on
line source
$ cat >> $HGRCPATH <<EOF > [extensions] > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH $ glog() { > hg log -G --template '{rev}@{branch}({phase}) {desc|firstline}\n' "$@" > } $ hg init repo --traceback $ cd repo $ echo a > a $ hg ci -Am adda adding a Test that amend captures branches $ hg branch foo marked working directory as branch foo (branches are permanent and global, did you want a bookmark?) $ hg amend -d '0 0' -n "this a note on the obsmarker and supported for hg>=4.4" $ hg debugobsolete 07f4944404050f47db2e5c5071e0e84e7a27bba9 6a022cbb61d5ba0f03f98ff2d36319dfea1034ae 0 (*) {'ef1': '*', 'user': 'test'} (glob) $ hg obslog @ 6a022cbb61d5 (1) adda | x 07f494440405 (0) adda rewritten(branch) as 6a022cbb61d5 using amend by test (Thu Jan 01 00:00:00 1970 +0000) note: this a note on the obsmarker and supported for hg>=4.4 $ hg branch foo $ hg branches foo 1:6a022cbb61d5 $ glog @ 1@foo(draft) adda Test no-op $ hg amend -d '0 0' nothing changed [1] $ glog @ 1@foo(draft) adda Test forcing the message to the same value, no intermediate revision. $ hg amend -d '0 0' -m 'adda' nothing changed [1] $ glog @ 1@foo(draft) adda Test collapsing into an existing revision, no intermediate revision. $ echo a >> a $ hg ci -m changea $ echo a > a $ hg status M a $ hg pstatus $ hg diff diff -r f7a50201fe3a a --- a/a Thu Jan 01 00:00:00 1970 +0000 +++ b/a * +0000 (glob) @@ -1,2 +1,1 @@ a -a $ hg pdiff $ hg ci -m reseta $ hg debugobsolete 07f4944404050f47db2e5c5071e0e84e7a27bba9 6a022cbb61d5ba0f03f98ff2d36319dfea1034ae 0 (*) {'ef1': '*', 'user': 'test'} (glob) $ hg phase 2 2: draft $ glog @ 3@foo(draft) reseta | o 2@foo(draft) changea | o 1@foo(draft) adda Specify precise commit date with -d $ hg amend -d '2001-02-03 04:05:06 +0700' $ hg parents --template '{rev} {date|date}\n' 4 Sat Feb 03 04:05:06 2001 +0700 Specify "now" as commit date with -D $ before=`date +%s` $ hg amend -D $ commit=`hg parents --template '{date|hgdate} rev{rev}\n'` $ after=`date +%s` $ (echo $before ; echo $commit; echo $after) | sort -k1 -n -s \d+ (re) \d+ 0 rev5 (re) \d+ (re) Specify current user as committer with -U $ HGUSER=newbie hg amend -U $ hg parents --template '{rev} {author}\n' 6 newbie Check that --logfile works $ echo "logfile message" > logfile.txt $ hg amend -l logfile.txt $ hg log -r . -T "{desc}\n" logfile message # Make sure we don't get reparented to -1 with no username (issue4211) $ HGUSER= $ hg amend -e --config ui.username= -m "empty user" abort: no username supplied (use 'hg config --edit' to set your username) [255] $ hg sum parent: 7:* tip (glob) logfile message branch: foo commit: 1 unknown (clean) update: (current) phases: 3 draft Check the help $ hg amend -h hg amend [OPTION]... [FILE]... aliases: refresh combine a changeset with updates and replace it with a new one Commits a new changeset incorporating both the changes to the given files and all the changes from the current parent changeset into the repository. See 'hg commit' for details about committing changes. If you don't specify -m, the parent's message will be reused. If --extract is specified, the behavior of 'hg amend' is reversed: Changes to selected files in the checked out revision appear again as uncommitted changed in the working directory. Returns 0 on success, 1 if nothing changed. options ([+] can be repeated): -A --addremove mark new/missing files as added/removed before committing -a --all match all files -e --edit invoke editor on commit messages --extract extract changes from the commit to the working copy --patch make changes to wdir parent by editing patch --close-branch mark a branch as closed, hiding it from the branch list -s --secret use the secret phase for committing -n --note TEXT store a note on amend -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns -m --message TEXT use text as commit message -l --logfile FILE read commit message from file -d --date DATE record the specified date as commit date -u --user USER record the specified user as committer -D --current-date record the current date as commit date -U --current-user record the current user as committer -i --interactive use interactive mode (some details hidden, use --verbose to show complete help)