windows: implement `util.cachestat` to fix numerous dirstate problems
I got here by bisecting the issue1790 related failure on Windows to keep an
entry from being marked "unset" in `test-dirstate.t` back to eedbf8256263.
There were a handful of other tests failing with an unexpected dirstate entry
state like this, as well as numerous "skip updating dirstate: identity mismatch"
messages added to various tests, as well as an issue with dirstate wrapping with
the largefiles extension[1], all of which appear to be fixed by this. In total,
~25 tests are fully fixed on Windows with this change on default.
This is basically a copy/paste of the posix implementation, but we drop the
`st_mode` comparison- I think the only reason we care about the mode on posix is
to detect +/-x mode changes, but the executable bits on Windows are synthesized
based on the name of the file[2]. None of the other parts of the codebase are
equipped to handle executable bits in the filesystem on Windows anyway, so it
doesn't make sense to worry about them here.
Note that `st_uid` and `st_gid` seem to always be 0 on Windows (and I can't find
them being initialized), so they can probably be dropped from the comparison.
But I doubt they matter any more on posix, since we don't track ownership. The
`st_ino`, `st_dev`, and `st_nlink` attributes all seem to have reasonable values
for comparing like on posix[3].
Also note that `st_ctime` is apparently deprecated in 3.12+ (for reasons I
haven't explored)[4].
[1] https://foss.heptapod.net/mercurial/mercurial-devel/-/merge_requests/884
[2] https://github.com/python/cpython/blob/aab3210271136ad8e8fecd927b806602c463e1f2/Modules/posixmodule.c#L1948
[3] https://github.com/python/cpython/blob/aab3210271136ad8e8fecd927b806602c463e1f2/Python/fileutils.c#L1158
[4] https://github.com/python/cpython/blob/aab3210271136ad8e8fecd927b806602c463e1f2/Modules/posixmodule.c#L2200
#require execbit
$ umask 027
$ hg init test1
$ cd test1
$ touch a b
$ hg add a b
$ hg ci -m "added a b"
$ cd ..
$ hg clone test1 test3
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg init test2
$ cd test2
$ hg pull ../test1
pulling from ../test1
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 2 changes to 2 files
new changesets 22a449e20da5
(run 'hg update' to get a working copy)
$ hg co
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ chmod +x a
$ hg ci -m "chmod +x a"
the changelog should mention file a:
$ hg tip --template '{files}\n'
a
$ cd ../test1
$ echo 123 >>a
$ hg ci -m "a updated"
$ hg pull ../test2
pulling from ../test2
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (+1 heads)
new changesets 7f4313b42a34
1 local changesets published
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg heads
changeset: 2:7f4313b42a34
tag: tip
parent: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: chmod +x a
changeset: 1:c6ecefc45368
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: a updated
$ hg history
changeset: 2:7f4313b42a34
tag: tip
parent: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: chmod +x a
changeset: 1:c6ecefc45368
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: a updated
changeset: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: added a b
$ hg -v merge
resolving manifests
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ cat a
123
$ [ -x a ]
$ cd ../test3
$ echo 123 >>b
$ hg ci -m "b updated"
$ hg pull ../test2
pulling from ../test2
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (+1 heads)
new changesets 7f4313b42a34
(run 'hg heads' to see heads, 'hg merge' to merge)
$ hg heads
changeset: 2:7f4313b42a34
tag: tip
parent: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: chmod +x a
changeset: 1:dc57ead75f79
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: b updated
$ hg history
changeset: 2:7f4313b42a34
tag: tip
parent: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: chmod +x a
changeset: 1:dc57ead75f79
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: b updated
changeset: 0:22a449e20da5
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: added a b
$ hg -v merge
resolving manifests
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ ls -l ../test[123]/a > foo
$ cut -b 1-10 < foo
-rwxr-x---
-rwxr-x---
-rwxr-x---
$ hg debugindex a
rev linkrev nodeid p1-nodeid p2-nodeid
0 0 b80de5d13875 000000000000 000000000000
$ hg debugindex -R ../test2 a
rev linkrev nodeid p1-nodeid p2-nodeid
0 0 b80de5d13875 000000000000 000000000000
$ hg debugindex -R ../test1 a
rev linkrev nodeid p1-nodeid p2-nodeid
0 0 b80de5d13875 000000000000 000000000000
1 1 7fe919cc0336 b80de5d13875 000000000000
$ cd ..