update: add a Rust fast-path when updating from null (and clean)
This case is easy to detect and we have all we need to generate a valid
working copy and dirstate entirely in Rust, which speeds things up
considerably:
On my machine updating a repo of ~300k files goes from 10.00s down to 4.2s,
all while consuming 50% less system time, with all caches hot.
Something to note is that further improvements will probably happen
with the upcoming `InnerRevlog` series that does smarter
mmap hanlding, especially for filelogs.
Here are benchmark numbers on a machine with only 4 cores (and no SMT enabled)
```
### data-env-vars.name = heptapod-public-2024-03-25-ds2-pnm
# benchmark.name = hg.command.update
# bin-env-vars.hg.py-re2-module = default
# bin-env-vars.hg.changeset.node = <this change>
# benchmark.variants.atomic-update = no
# benchmark.variants.scenario = null-to-tip
# benchmark.variants.worker = default
default: 5.328762 ~~~~~
rust: 1.308654 (-75.44%, -4.02)
### data-env-vars.name = mercurial-devel-2024-03-22-ds2-pnm
# benchmark.name = hg.command.update
# bin-env-vars.hg.py-re2-module = default
# bin-env-vars.hg.changeset.node = <this change>
# benchmark.variants.atomic-update = no
# benchmark.variants.scenario = null-to-tip
# benchmark.variants.worker = default
default: 1.693271 ~~~~~
rust: 1.151053 (-32.02%, -0.54)
### data-env-vars.name = mozilla-unified-2024-03-22-ds2-pnm
# benchmark.name = hg.command.update
# bin-env-vars.hg.py-re2-module = default
# bin-env-vars.hg.changeset.node = <this change>
# benchmark.variants.atomic-update = no
# benchmark.variants.scenario = null-to-tip
# benchmark.variants.worker = default
default: 38.901613 ~~~~~
rust: 11.637880 (-70.08%, -27.26)
### data-env-vars.name = netbsd-xsrc-public-2024-09-19-ds2-pnm
# benchmark.name = hg.command.update
# bin-env-vars.hg.py-re2-module = default
# bin-env-vars.hg.changeset.node = <this change>
# benchmark.variants.atomic-update = no
# benchmark.variants.scenario = null-to-tip
# benchmark.variants.worker = default
default: 4.793727 ~~~~~
rust: 1.505905 (-68.59%, -3.29)
```
Testing recorded "modified" files for merge commit
==================================================
#require execbit
This file shows what hg says are "modified" files for a merge commit
(hg log -T {files}), somewhat exhaustively.
This test file shows merges that involves executable bit changing, check test-merge-combination-exec-bytes.t
For merges that involve files contents changing, check test-merge-combination-file-content.t
For testing of multiple corner case, check test-merge-combination-misc.t
Case with multiple or zero merge ancestors, copies/renames, and identical file contents
with different filelog revisions are not currently covered.
$ . $TESTDIR/testlib/merge-combination-util.sh
All the merges of executable bit.
$ range () {
> max=a
> for i in $@; do
> if [ $i = - ]; then continue; fi
> if [ $i > $max ]; then max=$i; fi
> done
> if [ $max = a ]; then echo f; else echo f x; fi
> }
$ isgood () { case $line in *f*x*) true;; *) false;; esac; }
$ createfile () {
> if [ -f a ] && (([ -x a ] && [ $v = x ]) || (! [ -x a ] && [ $v != x ]))
> then touch $file
> else touch a; if [ $v = x ]; then chmod +x a; else chmod -x a; fi
> fi
> }
$ genmerges
fffx : agree on "a"
ffxf : agree on "a"
ffxx : agree on ""
ffx- : agree on "a"
ff-x : hg said "", expected "a"
fxff : hg said "", expected "a"
fxfx : hg said "a", expected ""
fxf- : agree on "a"
fxxf : agree on "a"
fxxx : agree on ""
fxx- : agree on "a"
fx-f : hg said "", expected "a"
fx-x : hg said "", expected "a"
fx-- : hg said "", expected "a"
f-fx : agree on "a"
f-xf : agree on "a"
f-xx : hg said "", expected "a"
f-x- : agree on "a"
f--x : agree on "a"
-ffx : agree on "a"
-fxf C: agree on "a"
-fxx C: hg said "", expected "a"
-fx- C: agree on "a"
-f-x : hg said "", expected "a"
--fx : agree on "a"