Wed, 29 Sep 2021 14:55:29 +0200 dirstate-item: use maybe_clean instead of `state` in the eol extension
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 29 Sep 2021 14:55:29 +0200] rev 48102
dirstate-item: use maybe_clean instead of `state` in the eol extension Differential Revision: https://phab.mercurial-scm.org/D11527
Thu, 30 Sep 2021 12:00:15 +0200 dirstate: move verification code within the dirstate itself
Pierre-Yves David <pierre-yves.david@octobus.net> [Thu, 30 Sep 2021 12:00:15 +0200] rev 48101
dirstate: move verification code within the dirstate itself This move implementation details further down the stack and make it the verification code easier to discover. Differential Revision: https://phab.mercurial-scm.org/D11526
Wed, 29 Sep 2021 14:52:44 +0200 dirstate-entry: use `?` for the state of entry without any tracking
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 29 Sep 2021 14:52:44 +0200] rev 48100
dirstate-entry: use `?` for the state of entry without any tracking This is what the dirstate use at a higher level. Differential Revision: https://phab.mercurial-scm.org/D11525
Wed, 29 Sep 2021 14:51:31 +0200 dirstate-item: introduce a `any_tracked` property
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 29 Sep 2021 14:51:31 +0200] rev 48099
dirstate-item: introduce a `any_tracked` property This property is True is the file is tracked anywhere, either the working copy, or any of the parent. Differential Revision: https://phab.mercurial-scm.org/D11524
Wed, 29 Sep 2021 14:41:19 +0200 dirstate-item: introduce a `maybe_clean` property
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 29 Sep 2021 14:41:19 +0200] rev 48098
dirstate-item: introduce a `maybe_clean` property It is useful for some extension that seek to invalidate some state. Differential Revision: https://phab.mercurial-scm.org/D11523
Wed, 29 Sep 2021 02:37:24 +0200 dirstate: add a `get_entry` method to the dirstate
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 29 Sep 2021 02:37:24 +0200] rev 48097
dirstate: add a `get_entry` method to the dirstate This method give access to the underlying `DirstateEntry` object (or an empty one if None was there). It should allow us to use the more semantic property of the entry instead of the state where we needs it. Differential Revision: https://phab.mercurial-scm.org/D11522
Thu, 30 Sep 2021 18:06:34 +0200 dirstate-item: Make constructor parameters optional
Simon Sapin <simon.sapin@octobus.net> [Thu, 30 Sep 2021 18:06:34 +0200] rev 48096
dirstate-item: Make constructor parameters optional … in the C implementation of DirstateItem, like they already were in the Python and Rust ones. Differential Revision: https://phab.mercurial-scm.org/D11521
Fri, 01 Oct 2021 08:44:56 -0700 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com> [Fri, 01 Oct 2021 08:44:56 -0700] rev 48095
hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor Nightly `rustc` warns about the `RevlogEntry::rev` field not being used. Rather than removing it, I added an accessor since it seems useful to be able to get the entry's revision. Differential Revision: https://phab.mercurial-scm.org/D11548
Fri, 01 Oct 2021 18:14:56 +0200 rust: remove dead code
Raphaël Gomès <rgomes@octobus.net> [Fri, 01 Oct 2021 18:14:56 +0200] rev 48094
rust: remove dead code Differential Revision: https://phab.mercurial-scm.org/D11549
Sat, 11 Sep 2021 00:09:29 +0200 rust-revset: support explicit `.` revision
Raphaël Gomès <rgomes@octobus.net> [Sat, 11 Sep 2021 00:09:29 +0200] rev 48093
rust-revset: support explicit `.` revision This is basically the same thing as not specifying a revision, except this is done in the revset resolution function. This allows calls like `rhg cat some-file -r .` to work without falling back. Differential Revision: https://phab.mercurial-scm.org/D11402
Sat, 11 Sep 2021 00:05:08 +0200 rust-revset: add separate match logic for shortcuts
Raphaël Gomès <rgomes@octobus.net> [Sat, 11 Sep 2021 00:05:08 +0200] rev 48092
rust-revset: add separate match logic for shortcuts The next change will add a shortcut for the `.` revision. One day we might start matching `tip` and others, so this is an easy refactor. Differential Revision: https://phab.mercurial-scm.org/D11401
Mon, 13 Sep 2021 15:12:35 +0200 rhg: fall back if subrepos are detected
Raphaël Gomès <rgomes@octobus.net> [Mon, 13 Sep 2021 15:12:35 +0200] rev 48091
rhg: fall back if subrepos are detected We do not handle subrepos yet, the addition of the support for `-r .` will break if we don't fall back. Differential Revision: https://phab.mercurial-scm.org/D11403
Wed, 01 Sep 2021 18:09:35 +0200 rhg: fallback if `defaults` config is set for the current command
Raphaël Gomès <rgomes@octobus.net> [Wed, 01 Sep 2021 18:09:35 +0200] rev 48090
rhg: fallback if `defaults` config is set for the current command Differential Revision: https://phab.mercurial-scm.org/D11381
Wed, 01 Sep 2021 17:41:51 +0200 rhg: fallback if the current command has any generic hook defined
Raphaël Gomès <rgomes@octobus.net> [Wed, 01 Sep 2021 17:41:51 +0200] rev 48089
rhg: fallback if the current command has any generic hook defined We do not handle hooks yet. Differential Revision: https://phab.mercurial-scm.org/D11380
Wed, 01 Sep 2021 17:41:08 +0200 rhg-cat: fallback in presence of a fileset
Raphaël Gomès <rgomes@octobus.net> [Wed, 01 Sep 2021 17:41:08 +0200] rev 48088
rhg-cat: fallback in presence of a fileset These are unsupported so far. Differential Revision: https://phab.mercurial-scm.org/D11379
Wed, 01 Sep 2021 17:40:25 +0200 rhg-cat: fallback when detecting `.` or `..` path segments
Raphaël Gomès <rgomes@octobus.net> [Wed, 01 Sep 2021 17:40:25 +0200] rev 48087
rhg-cat: fallback when detecting `.` or `..` path segments We do not normalize paths correctly yet, so exclude the shortcuts. Differential Revision: https://phab.mercurial-scm.org/D11378
Wed, 01 Sep 2021 16:13:25 +0200 rhg: add support for calling `rhg cat` without a revision
Raphaël Gomès <rgomes@octobus.net> [Wed, 01 Sep 2021 16:13:25 +0200] rev 48086
rhg: add support for calling `rhg cat` without a revision Turns out the necessary pieces were there already. Like the Python implementation, we default to the first parent of the dirstate. Differential Revision: https://phab.mercurial-scm.org/D11377
Thu, 30 Sep 2021 17:34:28 +0200 branching: merge with stable
Raphaël Gomès <rgomes@octobus.net> [Thu, 30 Sep 2021 17:34:28 +0200] rev 48085
branching: merge with stable
Mon, 27 Sep 2021 13:52:49 +0200 dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net> [Mon, 27 Sep 2021 13:52:49 +0200] rev 48084
dirstate: Remove the Rust abstraction DirstateMapMethods This Rust trait used to exist in order to allow the DirstateMap class exposed to Python to be backed by either of two implementations: one similar to the Python implementation based on a "flat" `HashMap<HgPathBuf, DirstateEntry>`, and the newer one based on a tree of nodes matching the directory structure of tracked files. A boxed trait object was used with dynamic dispatch. With the flat implementation removed and only the tree one remaining, this abstraction is not useful anymore and the concrete type can be stored directly. It remains that the trait was implemented separately for `DirstateMap<'_>` (which takes a lifetime parameter) and `OwningDirstateMap` (whose job is to wrap the former and hide the lifetime parameter), with the latter impl only forwarding calls. This changeset also removes this forwarding. Instead, the methods formerly of the `DirstateMapMethods` trait are now inherent methods implemented for `OwningDirstateMap` (where they will actually be used) but in the module that defines `DirstateMap`. This unusual setup gives access to the private fields of `DirstateMap` from those methods. Differential Revision: https://phab.mercurial-scm.org/D11517
Mon, 27 Sep 2021 12:09:15 +0200 dirstate: Remove the flat Rust DirstateMap implementation
Simon Sapin <simon.sapin@octobus.net> [Mon, 27 Sep 2021 12:09:15 +0200] rev 48083
dirstate: Remove the flat Rust DirstateMap implementation Before this changeset we had two Rust implementations of `DirstateMap`. This removes the "flat" DirstateMap so that the "tree" DirstateMap is always used when Rust enabled. This simplifies the code a lot, and will enable (in the next changeset) further removal of a trait abstraction. This is a performance regression when: * Rust is enabled, and * The repository uses the legacy dirstate-v1 file format, and * For `hg status`, unknown files are not listed (such as with `-mard`) The regression is about 100 milliseconds for `hg status -mard` on a semi-large repository (mozilla-central), from ~320ms to ~420ms. We deem this to be small enough to be worth it. The new dirstate-v2 is still experimental at this point, but we aim to stabilize it (though not yet enable it by default for new repositories) in Mercurial 6.0. Eventually, upgrating repositories to dirsate-v2 will eliminate this regression (and enable other performance improvements). # Background The flat DirstateMap was introduced with the first Rust implementation of the status algorithm. It works similarly to the previous Python + C one, with a single `HashMap` that associates file paths to a `DirstateEntry` (where Python has a dict). We later added the tree DirstateMap where the root of the tree contains nodes for files and directories that are directly at the root of the repository, and nodes for directories can contain child nodes representing the files and directly that *they* contain directly. The shape of this tree mirrors that of the working directory in the filesystem. This enables the status algorithm to traverse this tree in tandem with traversing the filesystem tree, which in turns enables a more efficient algorithm. Furthermore, the new dirstate-v2 file format is also based on a tree of the same shape. The tree DirstateMap can access a dirstate-v2 file without parsing it: binary data in a single large (possibly memory-mapped) bytes buffer is traversed on demand. This allows `DirstateMap` creation to take `O(1)` time. (Mutation works by creating new in-memory nodes with copy-on-write semantics, and serialization is append-mostly.) The tradeoff is that for "legacy" repositories that use the dirstate-v1 file format, parsing that file into a tree DirstateMap takes more time. Profiling shows that this time is dominated by `HashMap`. For a dirstate containing `F` files with an average `D` directory depth, the flat DirstateMap does parsing in `O(F)` number of HashMap operations but the tree DirstateMap in `O(F × D)` operations, since each node has its own HashMap containing its child nodes. This slower costs ~140ms on an old snapshot of mozilla-central, and ~80ms on an old snapshot of the Netbeans repository. The status algorithm is faster, but with `-mard` (when not listing unknown files) it is typically not faster *enough* to compensate the slower parsing. Both Rust implementations are always faster than the Python + C implementation # Benchmark results All benchmarks are run on changeset 98c0408324e6, with repositories that use the dirstate-v1 file format, on a server with 4 CPU cores and 4 CPU threads (no HyperThreading). `hg status` benchmarks show wall clock times of the entire command as the average and standard deviation of serveral runs, collected by https://github.com/sharkdp/hyperfine and reformated. Parsing benchmarks are wall clock time of the Rust function that converts a bytes buffer of the dirstate file into the `DirstateMap` data structure as used by the status algorithm. A single run each, collected by running `hg status` this environment variable: RUST_LOG=hg::dirstate::dirstate_map=trace,hg::dirstate_tree::dirstate_map=trace Benchmark 1: Rust flat DirstateMap → Rust tree DirstateMap hg status mozilla-clean 562.3 ms ± 2.0 ms → 462.5 ms ± 0.6 ms 1.22 ± 0.00 times faster mozilla-dirty 859.6 ms ± 2.2 ms → 719.5 ms ± 3.2 ms 1.19 ± 0.01 times faster mozilla-ignored 558.2 ms ± 3.0 ms → 457.9 ms ± 2.9 ms 1.22 ± 0.01 times faster mozilla-unknowns 859.4 ms ± 5.7 ms → 716.0 ms ± 4.7 ms 1.20 ± 0.01 times faster netbeans-clean 336.5 ms ± 0.9 ms → 339.5 ms ± 0.4 ms 0.99 ± 0.00 times faster netbeans-dirty 491.4 ms ± 1.6 ms → 475.1 ms ± 1.2 ms 1.03 ± 0.00 times faster netbeans-ignored 343.7 ms ± 1.0 ms → 347.8 ms ± 0.4 ms 0.99 ± 0.00 times faster netbeans-unknowns 484.3 ms ± 1.0 ms → 466.0 ms ± 1.2 ms 1.04 ± 0.00 times faster hg status -mard mozilla-clean 317.3 ms ± 0.6 ms → 422.5 ms ± 1.2 ms 0.75 ± 0.00 times faster mozilla-dirty 315.4 ms ± 0.6 ms → 417.7 ms ± 1.1 ms 0.76 ± 0.00 times faster mozilla-ignored 314.6 ms ± 0.6 ms → 417.4 ms ± 1.0 ms 0.75 ± 0.00 times faster mozilla-unknowns 312.9 ms ± 0.9 ms → 417.3 ms ± 1.6 ms 0.75 ± 0.00 times faster netbeans-clean 212.0 ms ± 0.6 ms → 283.6 ms ± 0.8 ms 0.75 ± 0.00 times faster netbeans-dirty 211.4 ms ± 1.0 ms → 283.4 ms ± 1.6 ms 0.75 ± 0.01 times faster netbeans-ignored 211.4 ms ± 0.9 ms → 283.9 ms ± 0.8 ms 0.74 ± 0.01 times faster netbeans-unknowns 211.1 ms ± 0.6 ms → 283.4 ms ± 1.0 ms 0.74 ± 0.00 times faster Parsing mozilla-clean 38.4ms → 177.6ms mozilla-dirty 38.8ms → 177.0ms mozilla-ignored 38.8ms → 178.0ms mozilla-unknowns 38.7ms → 176.9ms netbeans-clean 16.5ms → 97.3ms netbeans-dirty 16.5ms → 98.4ms netbeans-ignored 16.9ms → 97.4ms netbeans-unknowns 16.9ms → 96.3ms Benchmark 2: Python + C dirstatemap → Rust tree DirstateMap hg status mozilla-clean 1261.0 ms ± 3.6 ms → 461.1 ms ± 0.5 ms 2.73 ± 0.00 times faster mozilla-dirty 2293.4 ms ± 9.1 ms → 719.6 ms ± 3.6 ms 3.19 ± 0.01 times faster mozilla-ignored 1240.4 ms ± 2.3 ms → 457.7 ms ± 1.9 ms 2.71 ± 0.00 times faster mozilla-unknowns 2283.3 ms ± 9.0 ms → 719.7 ms ± 3.8 ms 3.17 ± 0.01 times faster netbeans-clean 879.7 ms ± 3.5 ms → 339.9 ms ± 0.5 ms 2.59 ± 0.00 times faster netbeans-dirty 1257.3 ms ± 4.7 ms → 474.6 ms ± 1.6 ms 2.65 ± 0.01 times faster netbeans-ignored 943.9 ms ± 1.9 ms → 347.3 ms ± 1.1 ms 2.72 ± 0.00 times faster netbeans-unknowns 1188.1 ms ± 5.0 ms → 465.2 ms ± 2.3 ms 2.55 ± 0.01 times faster hg status -mard mozilla-clean 903.2 ms ± 3.6 ms → 423.4 ms ± 2.2 ms 2.13 ± 0.01 times faster mozilla-dirty 884.6 ms ± 4.5 ms → 417.3 ms ± 1.4 ms 2.12 ± 0.01 times faster mozilla-ignored 881.9 ms ± 1.3 ms → 417.3 ms ± 0.8 ms 2.11 ± 0.00 times faster mozilla-unknowns 878.5 ms ± 1.9 ms → 416.4 ms ± 0.9 ms 2.11 ± 0.00 times faster netbeans-clean 434.9 ms ± 1.8 ms → 284.0 ms ± 0.8 ms 1.53 ± 0.01 times faster netbeans-dirty 434.1 ms ± 0.8 ms → 283.1 ms ± 0.8 ms 1.53 ± 0.00 times faster netbeans-ignored 431.7 ms ± 1.1 ms → 283.6 ms ± 1.8 ms 1.52 ± 0.01 times faster netbeans-unknowns 433.0 ms ± 1.3 ms → 283.5 ms ± 0.7 ms 1.53 ± 0.00 times faster Differential Revision: https://phab.mercurial-scm.org/D11516
Tue, 28 Sep 2021 20:00:19 +0200 dirstate: drop the from_p2_removed method
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 20:00:19 +0200] rev 48082
dirstate: drop the from_p2_removed method It it no longer in use. Differential Revision: https://phab.mercurial-scm.org/D11515
Tue, 28 Sep 2021 19:29:44 +0200 dirstate: inline the `from_p2_removed` logic
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 19:29:44 +0200] rev 48081
dirstate: inline the `from_p2_removed` logic It is used internally for compatibilty with size used in the `v1` format, but this is the only use. So we can simply inline it. Differential Revision: https://phab.mercurial-scm.org/D11514
Tue, 28 Sep 2021 19:15:46 +0200 dirstate: drop the merged_removed method
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 19:15:46 +0200] rev 48080
dirstate: drop the merged_removed method It it no longer in use. Differential Revision: https://phab.mercurial-scm.org/D11513
Tue, 28 Sep 2021 19:12:44 +0200 dirstate: inline the merged_removed logic
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 19:12:44 +0200] rev 48079
dirstate: inline the merged_removed logic It is used internally for compatibilty with size used in the `v1` format, but this is the only use. So we can simply inline it. Differential Revision: https://phab.mercurial-scm.org/D11512
Tue, 28 Sep 2021 18:57:20 +0200 dirstate: drop some safety assert in largefile
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 18:57:20 +0200] rev 48078
dirstate: drop some safety assert in largefile The code involved in `set_possibly_dirty` is now simpler and safe to use even in the cases that the assert covered. So we can drop this assert. It was the last user of `merged_removed` and `from_p2_removed`. Differential Revision: https://phab.mercurial-scm.org/D11511
Tue, 28 Sep 2021 18:29:57 +0200 dirstate: drop unused condition in `from_p2`
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 18:29:57 +0200] rev 48077
dirstate: drop unused condition in `from_p2` This conditional was added (by me) tentatively because "it seemed more correct", but it is not used anywhere yet, and it is missing from the C and the Rust implementation. So it seems more consistent to drop it for now. This effectively backout f94cc63df859c Differential Revision: https://phab.mercurial-scm.org/D11510
Tue, 28 Sep 2021 20:05:37 +0200 dirstate: drop all logic around the "non-normal" sets
Pierre-Yves David <pierre-yves.david@octobus.net> [Tue, 28 Sep 2021 20:05:37 +0200] rev 48076
dirstate: drop all logic around the "non-normal" sets The dirstate has a lot of code to compute a set of all "non-normal" and "from_other_parent" entries. This is all used in one, unique, location, when `setparent` is called and moved from a merge to a non merge. At that time, any "merge related" information has to be dropped. This is mostly useful for command like `graft` or `shelve` that move to a single-parent state -before- the commit. Otherwise the commit will already have removed all traces of the merge information in the dirstate (e.g. for a regular merges). The bookkeeping for these sets is quite invasive. And it seems simpler to just drop it and do the full computation in the single location where we actually use it (since we have to do the computation at least once anyway). This simplify the code a lot, and clarify why this kind of computation is needed. The possible drawback compared to the previous code are: - if the operation happens in a loop, we will end up doing it multiple time, - the C code to detect entry of interest have been dropped, for now. It will be re-introduced later, with a processing code directly in C for even faster operation. Differential Revision: https://phab.mercurial-scm.org/D11507
Wed, 22 Sep 2021 17:46:29 +0200 dirstate: use a new `drop_merge_data` in `setparent`
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 22 Sep 2021 17:46:29 +0200] rev 48075
dirstate: use a new `drop_merge_data` in `setparent` What is happening in this `setparent` loop is that we remove all `merge` related information when the dirstate is moved out of a `merge` situation. So instead of shuffling state to get them where we want, we simply add a method on the DirstateItem to do drop the information we want dropped. Differential Revision: https://phab.mercurial-scm.org/D11506
Wed, 22 Sep 2021 15:17:12 +0200 dirstate: move parent state handling in the dirstatemap
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 22 Sep 2021 15:17:12 +0200] rev 48074
dirstate: move parent state handling in the dirstatemap This involves dirstatemap data mostly. Moving this one level down will remove the needs for the dirstatemap to expose some of its internals. This will help us to simplify more code further. Differential Revision: https://phab.mercurial-scm.org/D11505
Wed, 22 Sep 2021 09:46:37 +0200 dirstate: stop checking for path collision when adjusting parents
Pierre-Yves David <pierre-yves.david@octobus.net> [Wed, 22 Sep 2021 09:46:37 +0200] rev 48073
dirstate: stop checking for path collision when adjusting parents This was already checked at a earlier point when adding the file. Differential Revision: https://phab.mercurial-scm.org/D11504
(0) -30000 -10000 -3000 -1000 -300 -100 -50 -30 +30 +50 +100 +300 +1000 +3000 tip