##// END OF EJS Templates
localrepo: make journal.dirstate contain in-memory changes before transaction...
localrepo: make journal.dirstate contain in-memory changes before transaction Before this patch, in-memory dirstate changes aren't written out at opening transaction, even though 'journal.dirstate' is created directly from '.hg/dirstate'. Therefore, subsequent 'hg rollback' uses incomplete 'undo.dirstate' to restore dirstate, if dirstate is changed and isn't written out before opening transaction. In cases below, the condition "dirstate is changed and isn't written out before opening transaction" isn't satisfied and this problem doesn't appear: - "wlock scope" and "transaction scope" are almost equivalent e.g. 'commit --amend', 'import' and so on - dirstate changes are written out before opening transaction e.g. 'rebase' (via 'dirstateguard') and 'commit -A' (by separated wlock scopes) On the other hand, 'backout' may satisfy the condition above. To make 'journal.dirstate' contain in-memory changes before opening transaction, this patch explicitly invokes 'dirstate.write()' in 'localrepository.transaction()'. 'dirstate.write()' is placed before not "writing journal files out" but "invoking pretxnopen hooks" for visibility of dirstate changes to external hook processes. BTW, in the test script, 'touch -t 200001010000' and 'hg status' are invoked to make file 'c' surely clean in dirstate, because "clean but unsure" files indirectly cause 'dirstate.write()' at 'repo.status()' in 'repo.commit()' (see fe03f522dda9 for detail) and prevents from certainly reproducing the issue.

File last commit:

r25382:60849263 default
r25878:800e090e stable
Show More
test-rebase-abort.t
324 lines | 6.6 KiB | text/troff | Tads3Lexer
$ cat >> $HGRCPATH <<EOF
> [extensions]
> rebase=
>
> [phases]
> publish=False
>
> [alias]
> tglog = log -G --template "{rev}:{phase} '{desc}' {branches}\n"
> EOF
$ hg init a
$ cd a
$ touch .hg/rebasestate
$ hg sum
parent: -1:000000000000 tip (empty repository)
branch: default
commit: (clean)
update: (current)
abort: .hg/rebasestate is incomplete
[255]
$ rm .hg/rebasestate
$ echo c1 > common
$ hg add common
$ hg ci -m C1
$ echo c2 >> common
$ hg ci -m C2
$ echo c3 >> common
$ hg ci -m C3
$ hg up -q -C 1
$ echo l1 >> extra
$ hg add extra
$ hg ci -m L1
created new head
$ sed -e 's/c2/l2/' common > common.new
$ mv common.new common
$ hg ci -m L2
$ hg phase --force --secret 2
$ hg tglog
@ 4:draft 'L2'
|
o 3:draft 'L1'
|
| o 2:secret 'C3'
|/
o 1:draft 'C2'
|
o 0:draft 'C1'
Conflicting rebase:
$ hg rebase -s 3 -d 2
rebasing 3:3163e20567cc "L1"
rebasing 4:46f0b057b5c0 "L2" (tip)
merging common
warning: conflicts during merge.
merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
Abort:
$ hg rebase --abort
saved backup bundle to $TESTTMP/a/.hg/strip-backup/3e046f2ecedb-6beef7d5-backup.hg (glob)
rebase aborted
$ hg tglog
@ 4:draft 'L2'
|
o 3:draft 'L1'
|
| o 2:secret 'C3'
|/
o 1:draft 'C2'
|
o 0:draft 'C1'
Test safety for inconsistent rebase state, which may be created (and
forgotten) by Mercurial earlier than 2.7. This emulates Mercurial
earlier than 2.7 by renaming ".hg/rebasestate" temporarily.
$ hg rebase -s 3 -d 2
rebasing 3:3163e20567cc "L1"
rebasing 4:46f0b057b5c0 "L2" (tip)
merging common
warning: conflicts during merge.
merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
$ mv .hg/rebasestate .hg/rebasestate.back
$ hg update --quiet --clean 2
$ hg --config extensions.mq= strip --quiet "destination()"
$ mv .hg/rebasestate.back .hg/rebasestate
$ hg rebase --continue
abort: cannot continue inconsistent rebase
(use "hg rebase --abort" to clear broken state)
[255]
$ hg summary | grep '^rebase: '
rebase: (use "hg rebase --abort" to clear broken state)
$ hg rebase --abort
rebase aborted (no revision is removed, only broken state is cleared)
$ cd ..
Construct new repo:
$ hg init b
$ cd b
$ echo a > a
$ hg ci -Am A
adding a
$ echo b > b
$ hg ci -Am B
adding b
$ echo c > c
$ hg ci -Am C
adding c
$ hg up -q 0
$ echo b > b
$ hg ci -Am 'B bis'
adding b
created new head
$ echo c1 > c
$ hg ci -Am C1
adding c
$ hg phase --force --secret 1
$ hg phase --public 1
Rebase and abort without generating new changesets:
$ hg tglog
@ 4:draft 'C1'
|
o 3:draft 'B bis'
|
| o 2:secret 'C'
| |
| o 1:public 'B'
|/
o 0:public 'A'
$ hg rebase -b 4 -d 2
rebasing 3:a6484957d6b9 "B bis"
note: rebase of 3:a6484957d6b9 created no changes to commit
rebasing 4:145842775fec "C1" (tip)
merging c
warning: conflicts during merge.
merging c incomplete! (edit conflicts, then use 'hg resolve --mark')
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
$ hg tglog
@ 4:draft 'C1'
|
o 3:draft 'B bis'
|
| @ 2:secret 'C'
| |
| o 1:public 'B'
|/
o 0:public 'A'
$ hg rebase -a
rebase aborted
$ hg tglog
@ 4:draft 'C1'
|
o 3:draft 'B bis'
|
| o 2:secret 'C'
| |
| o 1:public 'B'
|/
o 0:public 'A'
$ cd ..
rebase abort should not leave working copy in a merge state if tip-1 is public
(issue4082)
$ hg init abortpublic
$ cd abortpublic
$ echo a > a && hg ci -Aqm a
$ hg book master
$ hg book foo
$ echo b > b && hg ci -Aqm b
$ hg up -q master
$ echo c > c && hg ci -Aqm c
$ hg phase -p -r .
$ hg up -q foo
$ echo C > c && hg ci -Aqm C
$ hg log -G --template "{rev} {desc} {bookmarks}"
@ 3 C foo
|
| o 2 c master
| |
o | 1 b
|/
o 0 a
$ hg rebase -d master -r foo
rebasing 3:6c0f977a22d8 "C" (tip foo)
merging c
warning: conflicts during merge.
merging c incomplete! (edit conflicts, then use 'hg resolve --mark')
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
$ hg rebase --abort
rebase aborted
$ hg log -G --template "{rev} {desc} {bookmarks}"
@ 3 C foo
|
| o 2 c master
| |
o | 1 b
|/
o 0 a
$ cd ..
Make sure we don't clobber changes in the working directory when the
user has somehow managed to update to a different revision (issue4009)
$ hg init noupdate
$ cd noupdate
$ hg book @
$ echo original > a
$ hg add a
$ hg commit -m a
$ echo x > b
$ hg add b
$ hg commit -m b1
$ hg up 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
(leaving bookmark @)
$ hg book foo
$ echo y > b
$ hg add b
$ hg commit -m b2
created new head
$ hg rebase -d @ -b foo --tool=internal:fail
rebasing 2:070cf4580bb5 "b2" (tip foo)
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
$ mv .hg/rebasestate ./ # so we're allowed to hg up like in mercurial <2.6.3
$ hg up -C 0 # user does other stuff in the repo
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ mv rebasestate .hg/ # user upgrades to 2.7
$ echo new > a
$ hg up 1 # user gets an error saying to run hg rebase --abort
abort: rebase in progress
(use 'hg rebase --continue' or 'hg rebase --abort')
[255]
$ cat a
new
$ hg rebase --abort
rebase aborted
$ cat a
new
$ cd ..
On the other hand, make sure we *do* clobber changes whenever we
haven't somehow managed to update the repo to a different revision
during a rebase (issue4661)
$ hg ini yesupdate
$ cd yesupdate
$ echo "initial data" > foo.txt
$ hg add
adding foo.txt
$ hg ci -m "initial checkin"
$ echo "change 1" > foo.txt
$ hg ci -m "change 1"
$ hg up 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo "conflicting change 1" > foo.txt
$ hg ci -m "conflicting 1"
created new head
$ echo "conflicting change 2" > foo.txt
$ hg ci -m "conflicting 2"
$ hg rebase -d 1 --tool 'internal:fail'
rebasing 2:e4ea5cdc9789 "conflicting 1"
unresolved conflicts (see hg resolve, then hg rebase --continue)
[1]
$ hg rebase --abort
rebase aborted
$ hg summary
parent: 3:b16646383533 tip
conflicting 2
branch: default
commit: (clean)
update: 1 new changesets, 2 branch heads (merge)
phases: 4 draft