test-dirstate.t
483 lines
| 12.1 KiB
| text/troff
|
Tads3Lexer
/ tests / test-dirstate.t
Simon Sapin
|
r48882 | #testcases dirstate-v1 dirstate-v2 | ||
Simon Sapin
|
r47900 | |||
Simon Sapin
|
r48056 | #if dirstate-v2 | ||
r49049 | $ cat >> $HGRCPATH << EOF | |||
> [format] | ||||
r49523 | > use-dirstate-v2=1 | |||
r49049 | > [storage] | |||
> dirstate-v2.slow-path=allow | ||||
> EOF | ||||
Simon Sapin
|
r48056 | #endif | ||
Adrian Buehlmann
|
r11888 | ------ Test dirstate._dirs refcounting | ||
Adrian Buehlmann
|
r11887 | |||
$ hg init t | ||||
$ cd t | ||||
$ mkdir -p a/b/c/d | ||||
$ touch a/b/c/d/x | ||||
$ touch a/b/c/d/y | ||||
$ touch a/b/c/d/z | ||||
$ hg ci -Am m | ||||
adding a/b/c/d/x | ||||
adding a/b/c/d/y | ||||
adding a/b/c/d/z | ||||
$ hg mv a z | ||||
Matt Harbison
|
r35394 | moving a/b/c/d/x to z/b/c/d/x | ||
moving a/b/c/d/y to z/b/c/d/y | ||||
moving a/b/c/d/z to z/b/c/d/z | ||||
Joshua Redstone
|
r17095 | |||
Test name collisions | ||||
$ rm z/b/c/d/x | ||||
$ mkdir z/b/c/d/x | ||||
$ touch z/b/c/d/x/y | ||||
$ hg add z/b/c/d/x/y | ||||
abort: file 'z/b/c/d/x' in dirstate clashes with 'z/b/c/d/x/y' | ||||
[255] | ||||
$ rm -rf z/b/c/d | ||||
$ touch z/b/c/d | ||||
$ hg add z/b/c/d | ||||
abort: directory 'z/b/c/d' already in dirstate | ||||
[255] | ||||
Adrian Buehlmann
|
r11888 | $ cd .. | ||
Adrian Buehlmann
|
r11887 | |||
Martin Geisler
|
r12399 | Issue1790: dirstate entry locked into unset if file mtime is set into | ||
the future | ||||
Adrian Buehlmann
|
r11888 | |||
Prepare test repo: | ||||
$ hg init u | ||||
$ cd u | ||||
$ echo a > a | ||||
$ hg add | ||||
adding a | ||||
$ hg ci -m1 | ||||
Set mtime of a into the future: | ||||
r48926 | $ touch -t 203101011200 a | |||
Adrian Buehlmann
|
r11888 | |||
Status must not set a's entry to unset (issue1790): | ||||
$ hg status | ||||
$ hg debugstate | ||||
r48926 | n 644 2 2031-01-01 12:00:00 a | |||
Matt Mackall
|
r17733 | |||
Arseniy Alekseyev
|
r53242 | Check that .hg/dirstate permissions are correct | ||
(there was a bug where rust atomic replace would set permissions 0600, | ||||
which is not what we want) | ||||
paugier
|
r53350 | #if unix-permissions | ||
Arseniy Alekseyev
|
r53242 | $ f --mode .hg/dirstate | ||
.hg/dirstate: mode=644 | ||||
paugier
|
r53350 | #endif | ||
Arseniy Alekseyev
|
r53242 | |||
Matt Mackall
|
r17733 | Test modulo storage/comparison of absurd dates: | ||
Adrian Buehlmann
|
r11888 | |||
Jim Hague
|
r19092 | #if no-aix | ||
Matt Mackall
|
r17733 | $ touch -t 195001011200 a | ||
$ hg st | ||||
$ hg debugstate | ||||
n 644 2 2018-01-19 15:14:08 a | ||||
Jim Hague
|
r19092 | #endif | ||
Durham Goode
|
r22406 | |||
Verify that exceptions during a dirstate change leave the dirstate | ||||
coherent (issue4353) | ||||
$ cat > ../dirstateexception.py <<EOF | ||||
Augie Fackler
|
r33956 | > from mercurial import ( | ||
> error, | ||||
> extensions, | ||||
Augie Fackler
|
r45383 | > mergestate as mergestatemod, | ||
Augie Fackler
|
r33956 | > ) | ||
Durham Goode
|
r22406 | > | ||
Valentin Gatien-Baron
|
r42656 | > def wraprecordupdates(*args): | ||
Martin von Zweigbergk
|
r46273 | > raise error.Abort(b"simulated error while recording dirstateupdates") | ||
Durham Goode
|
r22406 | > | ||
> def reposetup(ui, repo): | ||||
Augie Fackler
|
r45383 | > extensions.wrapfunction(mergestatemod, 'recordupdates', | ||
> wraprecordupdates) | ||||
Durham Goode
|
r22406 | > EOF | ||
$ hg rm a | ||||
$ hg commit -m 'rm a' | ||||
$ echo "[extensions]" >> .hg/hgrc | ||||
$ echo "dirstateex=../dirstateexception.py" >> .hg/hgrc | ||||
$ hg up 0 | ||||
abort: simulated error while recording dirstateupdates | ||||
[255] | ||||
$ hg log -r . -T '{rev}\n' | ||||
1 | ||||
$ hg status | ||||
? a | ||||
Raphaël Gomès
|
r49614 | |||
#if dirstate-v2 | ||||
Check that folders that are prefixes of others do not throw the packer into an | ||||
infinite loop. | ||||
$ cd .. | ||||
$ hg init infinite-loop | ||||
$ cd infinite-loop | ||||
$ mkdir hgext3rd hgext | ||||
$ touch hgext3rd/__init__.py hgext/zeroconf.py | ||||
$ hg commit -Aqm0 | ||||
$ hg st -c | ||||
C hgext/zeroconf.py | ||||
C hgext3rd/__init__.py | ||||
$ cd .. | ||||
Raphaël Gomès
|
r50044 | |||
Check that the old dirstate data file is removed correctly and the new one is | ||||
valid. | ||||
$ dirstate_data_files () { | ||||
> find .hg -maxdepth 1 -name "dirstate.*" | ||||
> } | ||||
$ find_dirstate_uuid () { | ||||
Raphaël Gomès
|
r50048 | > hg debugstate --docket | grep uuid | sed 's/.*uuid: \(.*\)/\1/' | ||
Raphaël Gomès
|
r50044 | > } | ||
Arseniy Alekseyev
|
r50096 | $ find_dirstate_data_size () { | ||
> hg debugstate --docket | grep 'size of dirstate data' | sed 's/.*size of dirstate data: \(.*\)/\1/' | ||||
> } | ||||
Raphaël Gomès
|
r50044 | $ dirstate_uuid_has_not_changed () { | ||
Raphaël Gomès
|
r50051 | > # Non-Rust always rewrites the whole dirstate | ||
> if [ $# -eq 1 ] || ([ -n "$HGMODULEPOLICY" ] && [ -z "${HGMODULEPOLICY##*rust*}" ]) || [ -n "$RHG_INSTALLED_AS_HG" ]; then | ||||
Raphaël Gomès
|
r50044 | > test $current_uid = $(find_dirstate_uuid) | ||
Raphaël Gomès
|
r50052 | > else | ||
> echo "not testing because using Python implementation" | ||||
Raphaël Gomès
|
r50044 | > fi | ||
> } | ||||
$ cd .. | ||||
$ hg init append-mostly | ||||
$ cd append-mostly | ||||
$ mkdir dir dir2 | ||||
Raphaël Gomès
|
r51072 | $ touch -t 200001010000 dir/a dir/b dir/c dir/d dir/e dir2/f dir dir2 | ||
Raphaël Gomès
|
r50044 | $ hg commit -Aqm initial | ||
$ hg st | ||||
$ dirstate_data_files | wc -l | ||||
*1 (re) | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Nothing changes here | ||||
$ hg st | ||||
$ dirstate_data_files | wc -l | ||||
*1 (re) | ||||
$ dirstate_uuid_has_not_changed | ||||
Raphaël Gomès
|
r50052 | not testing because using Python implementation (no-rust no-rhg !) | ||
Raphaël Gomès
|
r50044 | |||
Raphaël Gomès
|
r51072 | Trigger an append with a small change to directory mtime | ||
Raphaël Gomès
|
r50044 | |||
Arseniy Alekseyev
|
r50096 | $ current_data_size=$(find_dirstate_data_size) | ||
Raphaël Gomès
|
r51072 | $ touch -t 201001010000 dir2 | ||
Raphaël Gomès
|
r50044 | $ hg st | ||
$ dirstate_data_files | wc -l | ||||
*1 (re) | ||||
$ dirstate_uuid_has_not_changed | ||||
Raphaël Gomès
|
r50052 | not testing because using Python implementation (no-rust no-rhg !) | ||
Arseniy Alekseyev
|
r50096 | $ new_data_size=$(find_dirstate_data_size) | ||
$ [ "$current_data_size" -eq "$new_data_size" ]; echo $? | ||||
0 (no-rust no-rhg !) | ||||
1 (rust !) | ||||
1 (no-rust rhg !) | ||||
Raphaël Gomès
|
r50044 | |||
Raphaël Gomès
|
r50049 | Unused bytes counter is non-0 when appending | ||
$ touch file | ||||
$ hg add file | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Trigger a rust/rhg run which updates the unused bytes value | ||||
$ hg st | ||||
A file | ||||
$ dirstate_data_files | wc -l | ||||
*1 (re) | ||||
$ dirstate_uuid_has_not_changed | ||||
Raphaël Gomès
|
r50052 | not testing because using Python implementation (no-rust no-rhg !) | ||
Raphaël Gomès
|
r50049 | |||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 (no-rust no-rhg !) | ||||
number of unused bytes: [1-9]\d* (re) (rhg no-rust !) | ||||
number of unused bytes: [1-9]\d* (re) (rust no-rhg !) | ||||
number of unused bytes: [1-9]\d* (re) (rust rhg !) | ||||
Raphaël Gomès
|
r50044 | Delete most of the dirstate to trigger a non-append | ||
$ hg rm dir/a dir/b dir/c dir/d | ||||
$ dirstate_data_files | wc -l | ||||
*1 (re) | ||||
$ dirstate_uuid_has_not_changed also-if-python | ||||
[1] | ||||
Raphaël Gomès
|
r50049 | Check that unused bytes counter is reset when creating a new docket | ||
$ hg debugstate --docket | grep unused | ||||
Raphaël Gomès
|
r50050 | number of unused bytes: 0 | ||
Raphaël Gomès
|
r50049 | |||
#endif | ||||
Raphaël Gomès
|
r51117 | (non-Rust always rewrites) | ||
Test the devel option to control write behavior | ||||
============================================== | ||||
Sometimes, debugging or testing the dirstate requires making sure that we have | ||||
done a complete rewrite of the data file and have no unreachable data around, | ||||
sometimes it requires we ensure we don't. | ||||
We test the option to force this rewrite by creating the situation where an | ||||
append would happen and check that it doesn't happen. | ||||
$ cd .. | ||||
$ hg init force-base | ||||
$ cd force-base | ||||
$ mkdir -p dir/nested dir2 | ||||
$ touch -t 200001010000 f dir/nested/a dir/b dir/c dir/d dir2/e dir/nested dir dir2 | ||||
$ hg commit -Aqm "recreate a bunch of files to facilitate append" | ||||
$ hg st --config devel.dirstate.v2.data_update_mode=force-new | ||||
$ cd .. | ||||
#if dirstate-v2 | ||||
$ hg -R force-base debugstate --docket | grep unused | ||||
number of unused bytes: 0 | ||||
Check with the option in "auto" mode | ||||
------------------------------------ | ||||
$ cp -a force-base append-mostly-no-force-rewrite | ||||
$ cd append-mostly-no-force-rewrite | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of dir on disk which will be recorded, causing a small enough change | ||||
to warrant only an append | ||||
$ touch -t 202212010000 dir2 | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=auto | ||||
UUID hasn't changed and a non-zero number of unused bytes means we've appended | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation (no-rust no-rhg !) | ||||
#if no-rust no-rhg | ||||
The pure python implementation never appends at the time this is written. | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 (known-bad-output !) | ||||
#else | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: [1-9]\d* (re) | ||||
#endif | ||||
$ cd .. | ||||
Check the same scenario with the option set to "force-new" | ||||
--------------------------------------------------------- | ||||
$ cp -a force-base append-mostly-force-rewrite | ||||
$ cd append-mostly-force-rewrite | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of dir on disk which will be recorded, causing a small enough change | ||||
to warrant only an append, but we force the rewrite | ||||
$ touch -t 202212010000 dir2 | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=force-new | ||||
UUID has changed and zero unused bytes means a full-rewrite happened | ||||
#if no-rust no-rhg | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation | ||||
#else | ||||
$ dirstate_uuid_has_not_changed | ||||
[1] | ||||
#endif | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 | ||||
$ cd .. | ||||
Check the same scenario with the option set to "force-append" | ||||
------------------------------------------------------------- | ||||
(should behave the same as "auto" here) | ||||
$ cp -a force-base append-mostly-force-append | ||||
$ cd append-mostly-force-append | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of dir on disk which will be recorded, causing a small enough change | ||||
to warrant only an append, which we are forcing here anyway. | ||||
$ touch -t 202212010000 dir2 | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=force-append | ||||
UUID has not changed and some unused bytes exist in the data file | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation (no-rust no-rhg !) | ||||
#if no-rust no-rhg | ||||
The pure python implementation never appends at the time this is written. | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 (known-bad-output !) | ||||
#else | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: [1-9]\d* (re) | ||||
#endif | ||||
$ cd .. | ||||
Check with the option in "auto" mode | ||||
------------------------------------ | ||||
$ cp -a force-base append-mostly-no-force-rewrite | ||||
$ cd append-mostly-no-force-rewrite | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of everything on disk causing a full rewrite | ||||
$ touch -t 202212010005 `hg files` | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=auto | ||||
UUID has changed and zero unused bytes means we've rewritten. | ||||
#if no-rust no-rhg | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation | ||||
#else | ||||
$ dirstate_uuid_has_not_changed | ||||
[1] | ||||
#endif | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 (known-bad-output !) | ||||
$ cd .. | ||||
Check the same scenario with the option set to "force-new" | ||||
--------------------------------------------------------- | ||||
(should be the same as auto) | ||||
$ cp -a force-base append-mostly-force-rewrite | ||||
$ cd append-mostly-force-rewrite | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of everything on disk causing a full rewrite | ||||
$ touch -t 202212010005 `hg files` | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=force-new | ||||
UUID has changed and a zero number unused bytes means we've rewritten. | ||||
#if no-rust no-rhg | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation | ||||
#else | ||||
$ dirstate_uuid_has_not_changed | ||||
[1] | ||||
#endif | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 | ||||
$ cd .. | ||||
Check the same scenario with the option set to "force-append" | ||||
------------------------------------------------------------- | ||||
Should append even if "auto" did not | ||||
$ cp -a force-base append-mostly-force-append | ||||
$ cd append-mostly-force-append | ||||
$ current_uid=$(find_dirstate_uuid) | ||||
Change mtime of everything on disk causing a full rewrite | ||||
$ touch -t 202212010005 `hg files` | ||||
$ hg st \ | ||||
> --config rhg.on-unsupported=abort \ | ||||
> --config devel.dirstate.v2.data_update_mode=force-append | ||||
UUID has not changed and some unused bytes exist in the data file | ||||
$ dirstate_uuid_has_not_changed | ||||
not testing because using Python implementation (no-rust no-rhg !) | ||||
#if no-rust no-rhg | ||||
The pure python implementation is never appending at the time this is written. | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: 0 (known-bad-output !) | ||||
#else | ||||
$ hg debugstate --docket | grep unused | ||||
number of unused bytes: [1-9]\d* (re) | ||||
#endif | ||||
$ cd .. | ||||
Get back into a state suitable for the test of the file. | ||||
$ cd ./append-mostly | ||||
#else | ||||
$ cd ./u | ||||
#endif | ||||
r50361 | Transaction compatibility | |||
Raphaël Gomès
|
r51117 | ========================= | ||
r50361 | ||||
The transaction preserves the dirstate. | ||||
We should make sure all of it (docket + data) is preserved | ||||
#if dirstate-v2 | ||||
$ hg commit -m 'bli' | ||||
#endif | ||||
$ hg update --quiet | ||||
$ hg revert --all --quiet | ||||
$ rm -f a | ||||
$ echo foo > foo | ||||
$ hg add foo | ||||
$ hg commit -m foo | ||||
#if dirstate-v2 | ||||
$ uid=$(find_dirstate_uuid) | ||||
$ touch bar | ||||
$ while [ uid = $(find_dirstate_uuid) ]; do | ||||
> hg add bar; | ||||
> hg remove bar; | ||||
> done; | ||||
$ rm bar | ||||
#endif | ||||
$ hg rollback | ||||
repository tip rolled back to revision 1 (undo commit) | ||||
working directory now based on revision 1 | ||||
$ hg status | ||||
A foo | ||||
Raphaël Gomès
|
r50443 | $ cd .. | ||
Check dirstate ordering | ||||
(e.g. `src/dirstate/` and `src/dirstate.rs` shouldn't cause issues) | ||||
$ hg init repro | ||||
$ cd repro | ||||
$ mkdir src | ||||
$ mkdir src/dirstate | ||||
$ touch src/dirstate/file1 src/dirstate/file2 src/dirstate.rs | ||||
$ touch file1 file2 | ||||
$ hg commit -Aqm1 | ||||
$ hg st | ||||
$ cd .. | ||||