Skip to content
Snippets Groups Projects
  1. Apr 07, 2025
    • Mitchell Kember's avatar
      rust-annotate: change FileId let-else to match · aedbc690
      Mitchell Kember authored
      This changes all the let-else statements on FileId to instead use an exhaustive
      match to make it more clear that the "else" case is Wdir.
      aedbc690
    • Mitchell Kember's avatar
      rust-annotate: do ancestor checks for all revs · 04bc2087
      Mitchell Kember authored
      This makes rhg annotate do ancestor checks for all filelog revs. Previously it
      only did so for revs that would actually appear in the output. While this often
      improves performance, sometimes it hurts it (in a few rare cases making it
      slower overall than Python).
      
      The reason is that linkrev adjustment goes in reverse topological order such
      that each changelog scan picks up where its child (or other descendant) left
      off. By skipping revs that don't appear in the output, we do fewer scans, but
      the scans are longer. If we do "unnecessary" ancestor checks (which are
      comparatively cheap), we get better descendants to start those changelog scans
      from. That's what this change does.
      
      Here are some poulpe benchmarks on the jane repo. The "file-with-long-history"
      examples were chosen by the setup script. The "was-faster-in-python" files I
      manually selected. The "50-random-files" is from `hg files | shuf -n50`.
      
      ### data-env-vars.name               = jane
      ### benchmark.name                   = hg.command.annotate
      ### bin-env-vars.hg.flavor           = rhg
      ### benchmark.variants.files-as-text = no
      ### benchmark.variants.follow-copies = yes
      ### benchmark.variants.listed        = default
      
       ## benchmark.variants.files         = 50-random-files.list
      ce5d61140f14: 167.293994  ~~~~~
      49568c6ba019: 98.502573 (-41.12%, -68.79)
       ## benchmark.variants.files         = file-with-long-history.a
      ce5d61140f14: 49.005604  ~~~~~
      49568c6ba019: 24.821525 (-49.35%, -24.18)
       ## benchmark.variants.files         = file-with-long-history.b
      ce5d61140f14: 48.959987  ~~~~~
      49568c6ba019: 25.059625 (-48.82%, -23.90)
       ## benchmark.variants.files         = file-with-long-history.c
      ce5d61140f14: 22.892105  ~~~~~
      49568c6ba019: 21.788369   (-4.82%, -1.10)
       ## benchmark.variants.files         = was-faster-in-python.a
      ce5d61140f14: 35.160262  ~~~~~
      49568c6ba019: 0.749528 (-97.87%, -34.41)
       ## benchmark.variants.files         = was-faster-in-python.b
      ce5d61140f14: 34.236378  ~~~~~
      49568c6ba019: 0.559009 (-98.37%, -33.68)
       ## benchmark.variants.files         = was-faster-in-python.c
      ce5d61140f14: 22.803029  ~~~~~
      49568c6ba019: 1.257608 (-94.48%, -21.55)
       ## benchmark.variants.files         = was-faster-in-python.d
      ce5d61140f14: 18.779003  ~~~~~
      49568c6ba019: 0.960363 (-94.89%, -17.82)
       ## benchmark.variants.files         = was-faster-in-python.e
      ce5d61140f14: 18.147231  ~~~~~
      49568c6ba019: 0.698075 (-96.15%, -17.45)
      04bc2087
  2. Mar 03, 2025
    • Mitchell Kember's avatar
      rust-annotate: support -Tjson · b242980e
      Mitchell Kember authored
      This adds support for the json template in rhg annotate. All other -T/--template
      values continue to fallback to Python.
      
      I matched the format of the Python output so all existing tests pass. This was
      not that hard to do printing JSON manually. The only thing I use serde_json for
      is to escape strings.
      b242980e
  3. Mar 06, 2025
  4. Mar 18, 2025
  5. Mar 04, 2025
  6. Apr 14, 2025
    • Arseniy Alekseyev's avatar
      rhg: extract function expand_aliases · fddb8e12
      Arseniy Alekseyev authored
      In the interest of keeping the code of `main_with_result` clean,
      move all alias-related stuff into a separate function.
      
      Also, add a comment explaining why we think `trailing_args` behavior
      is good enough.
      fddb8e12
  7. Apr 01, 2025
    • Mitchell Kember's avatar
      rhg: support basic aliases · df58357b
      Mitchell Kember authored
      This adds rhg support for resolving aliases. It does not yet support shell
      aliases (starting with "!") or interpolation ("$1", "$@", etc.). It splits words
      in alias definitions using the shlex crate.
      df58357b
  8. Apr 02, 2025
  9. Apr 01, 2025
    • Mitchell Kember's avatar
      rust-config: preserve insertion order · bbab51e5
      Mitchell Kember authored
      This changes ConfigItem to be an indexmap::IndexMap instead of a HashMap, so
      that it preserves insertion order. It also changes Config::iter_section to
      return keys in that order (lowest to highest precedence). For all existing uses
      of iter_section, the order doesn't appear to matter.
      
      This is motivated by a follow-up change that will implement support for aliases
      in rhg, where the order of alias definitions matters.
      bbab51e5
  10. Apr 16, 2025
  11. Mar 19, 2025
  12. Mar 20, 2025
  13. Apr 11, 2025
    • Arseniy Alekseyev's avatar
      dirstate: fix panic when validating dirstate on write · 2b7631bb
      Arseniy Alekseyev authored
      We saw this crash with a message like this:
      
      thread '<unnamed>' panicked at hg-core/src/dirstate/on_disk.rs:812:59:
      range end index 18446744073709551615 out of range for slice of length 12
      
      I believe this indicates that there's another bug or dirstate corruption that
      this validation caught, since I think it wouldn't crash on valid inputs
      (all "children" in this context are at level two or above, so they must
      have a slash in their full paths, so "-1" for a slash should not overflow).
      2b7631bb
  14. Apr 10, 2025
    • Arseniy Alekseyev's avatar
      rust-matchers: make Matcher extend Sync · 2ae3cd11
      Arseniy Alekseyev authored
      It removes the code repetition of having to mention Sync
      in returned matchers all the time.
      
      This makes matchers a tiny bit less general because you can't have a
      non-Sync matcher anymore, but we don't have any examples of those,
      and if we ever need one we can revert this change.
      2ae3cd11
  15. Mar 20, 2025
    • Arseniy Alekseyev's avatar
      rust-matchers: generalize consumers of the Matcher api somewhat · 4a4c5e65
      Arseniy Alekseyev authored
      In the interest of making it easier to use the matchers API,
      be more generous when producing matchers,
      and be more permissive when consuming them.
      
      - Add the `Send` trait everywhere where we're returning a Boxed matcher,
      so the caller can be free to wrap it into an `Arc` to share between threads.
      
      - For all matcher consumers, accept an &impl instead of a dyn box so
      the caller is free to pass anything they want.
      4a4c5e65
    • Arseniy Alekseyev's avatar
      rust-matchers: stop requiring that matchers are built of trait objects · 3659c13a
      Arseniy Alekseyev authored
      You can still use trait objects (and all existing code still does),
      but the choice of the trait object is not forced upon you by the matchers.
      
      In particular:
      - it's now possible to make a Send matcher and stick that into an Arc
        (the alternative would be to add a Send bound everywhere)
      - it's now possible to use borrowed matchers
        (the alternative would be add a lifetime bound everywhere: `Box<Matcher + 'a>`)
      - maybe performance is a tiny bit better (but I doubt that's measurable)
      3659c13a
  16. Mar 14, 2025
    • Mitchell Kember's avatar
      rust-annotate: allow --follow · 40bf6deb
      Mitchell Kember authored
      This makes rhg annotate support --follow as an alias for --file. It has been
      marked deprecated since 2010 (f142fa3c0a8c).
      However, Emacs vc-annotate still passes it, and we don't want it to fall back.
      40bf6deb
  17. Mar 20, 2025
    • Mitchell Kember's avatar
      rust-annotate: support --rev wdir() · f7d3c6cb
      Mitchell Kember authored
      This adds support for annotating a file in wdir(). Lines that are changed in the
      working directory get annotated with dirstate.p1 followed by "+", as in Python.
      
      I had to change some test-annotate.t output for an edge case. If file "foo" does
      not exist, `hg annotate -r wdir() foo` prints a slightly different error message
      depending on whether "foo" was ever previously tracked. I don't think this is
      useful or done purposefully, so it doesn't seem worth complicating rhg annotate
      to behave in the same way.
      f7d3c6cb
  18. Feb 18, 2025
  19. Mar 20, 2025
  20. Feb 18, 2025
  21. Feb 19, 2025
    • Mitchell Kember's avatar
      rust-revset: support resolving wdir() · f7693a8a
      Mitchell Kember authored
      This makes revset::resolve_single return RevisionOrWdir. Previously, it returned
      RevlogError::WDirUnsupported (leading to abort, not fallback) for 2147483647 and
      ffffffffffffffffffffffffffffffffffffffff. It did not recognize 'wdir()' itself,
      so that would lead to Python fallback. Now, it treats all 3 cases the same: it
      returns RevisionOrWdir::wdir() and lets the caller decide what to do.
      
      I changed rhg cat, files, and annotate to return HgError::unsupported in this
      case, since wdir is valid. I made `rhg status --change wdir()` behave the same
      as `rhg status`, conforming to the test in test-status.t.
      f7693a8a
    • Mitchell Kember's avatar
      rust-revlog: add RevisionOrWdir · 2fb3ad7c
      Mitchell Kember authored
      This type represents either a checked Revision or the wdir() pseudo-revision
      (revision 0x7fffffff, node ffffffffffffffffffffffffffffffffffffffff).
      
      You construct it with revision.into() or Revision::wdir(), and destructure it
      with rev.exclude_wdir() which returns Option<Revision>.
      
      I considered something like `enum RevisionOrWdir { Wdir, Revision(Revision) }`,
      but decided on `struct RevisionOrWdir(BaseRevision)` for a few reasons:
      
      - It's more ergonomic for the ways it actually gets used, in my opinion.
      - It also avoids the possibility of an invalid value Revision(0x7fffffff).
      - It remains 4 bytes rather than 8.
      - It maintains the ordering: wdir is greater than all other revisions.
      
      I'm planning to use this for 'rhg annotate -r wdir()'.
      2fb3ad7c
  22. Feb 14, 2025
    • Mitchell Kember's avatar
      rust-config: add username parsing · 663fe423
      Mitchell Kember authored
      This adds Config::username which returns HGUSER, ui.username, or EMAIL in that
      order, similar to ui.username() in Python.
      
      I considered following the pattern of EDITOR, VISUAL, PAGER, etc. and using
      add_for_environment_variable, but it's not possible to get the same precendence
      as in Python that way (in particular HGUSER coming after the repo .hg/hgrc), at
      least not without significant changes.
      
      This will be used for 'rhg annotate -r wdir() -u' to annotate the username on
      lines that were changed in the working directory.
      663fe423
  23. Mar 03, 2025
    • Mitchell Kember's avatar
      rust-utils: reimplement clean_whitespace without regex · 33aeb857
      Mitchell Kember authored
      This is similar to fixws in mercurial/cext/bdiff.c, except in addition to
      --ignore-all-space (-w) and --ignore-space-change (-b), it also handles
      --ignore-ws-at-eol (-Z). Unlike the regex, it operates in-place.
      
      For files with large histories such as mercurial/commands.py, it brings the
      penalty of -w and -b from 25% down to around 10%. For -Z, and for files with
      small histories, it makes little difference.
      
      Here are some poulpe benchmarks on the mercurial repo for the stack of four
      changes in this merge request (!1299):
      
      ### benchmark.name                = hg.command.annotate
        # data-env-vars.name            = mercurial-devel
        # bin-env-vars.hg.flavor        = rhg
      
       ## benchmark.variants.files      = 100-random-files
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 0.647526  ~~~~~
      cc30bead2d61: 0.633503   (-2.17%, -0.01)
       ## benchmark.variants.files      = 100-random-files
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 0.649229  ~~~~~
      cc30bead2d61: 0.642296   (-1.07%, -0.01)
       ## benchmark.variants.files      = 100-random-files
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 0.675751  ~~~~~
      cc30bead2d61: 0.645437   (-4.49%, -0.03)
       ## benchmark.variants.files      = 100-random-files
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 0.678141  ~~~~~
      cc30bead2d61: 0.645375   (-4.83%, -0.03)
       ## benchmark.variants.files      = file-with-long-history.a
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 1.700064  ~~~~~
      cc30bead2d61: 1.695099
       ## benchmark.variants.files      = file-with-long-history.a
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 1.682014  ~~~~~
      cc30bead2d61: 1.697669
       ## benchmark.variants.files      = file-with-long-history.a
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 2.140711  ~~~~~
      cc30bead2d61: 1.857253  (-13.24%, -0.28)
       ## benchmark.variants.files      = file-with-long-history.a
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 2.127745  ~~~~~
      cc30bead2d61: 1.814402  (-14.73%, -0.31)
       ## benchmark.variants.files      = file-with-long-history.b
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 0.263050  ~~~~~
      cc30bead2d61: 0.263603
       ## benchmark.variants.files      = file-with-long-history.b
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 0.261817  ~~~~~
      cc30bead2d61: 0.263896
       ## benchmark.variants.files      = file-with-long-history.b
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 0.286191  ~~~~~
      cc30bead2d61: 0.276698   (-3.32%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.b
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 0.282997  ~~~~~
      cc30bead2d61: 0.275538   (-2.64%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.c
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 0.318708  ~~~~~
      cc30bead2d61: 0.318006
       ## benchmark.variants.files      = file-with-long-history.c
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 0.323910  ~~~~~
      cc30bead2d61: 0.318743   (-1.60%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.c
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 0.390691  ~~~~~
      cc30bead2d61: 0.372053   (-4.77%, -0.02)
       ## benchmark.variants.files      = file-with-long-history.c
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 0.407243  ~~~~~
      cc30bead2d61: 0.403874
       ## benchmark.variants.files      = file-with-long-history.d
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 0.295730  ~~~~~
      cc30bead2d61: 0.269190   (-8.97%, -0.03)
       ## benchmark.variants.files      = file-with-long-history.d
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 0.276715  ~~~~~
      cc30bead2d61: 0.271512   (-1.88%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.d
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 0.283624  ~~~~~
      cc30bead2d61: 0.278003   (-1.98%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.d
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 0.286407  ~~~~~
      cc30bead2d61: 0.276957   (-3.30%, -0.01)
       ## benchmark.variants.files      = file-with-long-history.e
       ## benchmark.variants.flags      = default
      0471bf04ddf1: 0.349047  ~~~~~
      cc30bead2d61: 0.331948   (-4.90%, -0.02)
       ## benchmark.variants.files      = file-with-long-history.e
       ## benchmark.variants.flags      = -Z
      0471bf04ddf1: 0.359457  ~~~~~
      cc30bead2d61: 0.334011   (-7.08%, -0.03)
       ## benchmark.variants.files      = file-with-long-history.e
       ## benchmark.variants.flags      = -b
      0471bf04ddf1: 0.373671  ~~~~~
      cc30bead2d61: 0.347020   (-7.13%, -0.03)
       ## benchmark.variants.files      = file-with-long-history.e
       ## benchmark.variants.flags      = -w
      0471bf04ddf1: 0.374186  ~~~~~
      cc30bead2d61: 0.347367   (-7.17%, -0.03)
      33aeb857
    • Mitchell Kember's avatar
      rust-utils: add tests for clean_whitespace · 97f9cf5f
      Mitchell Kember authored
      This is in preparation for a follow-up change that reimplements the function.
      97f9cf5f
  24. Feb 25, 2025
    • Mitchell Kember's avatar
      rust-utils: make clean_whitespace mutate input · ee1a114b
      Mitchell Kember authored
      This makes clean_whitespace take a &mut Vec<u8> instead of returning Cow<[u8]>.
      Where before it returned Cow::Borrowed, now it is a no-op.
      
      This is in preparation for a follow-up change that reimplements clean_whitespace
      without regexes.
      ee1a114b
    • Mitchell Kember's avatar
      rust-utils: remove CleanWhitespace::None · 283f77c5
      Mitchell Kember authored
      Instead we use Option<CleanWhitespace>. This is in preparation for a follow-up
      change that reimplements clean_whitespace, where the None case felt awkward.
      283f77c5
  25. Feb 10, 2025
  26. Mar 05, 2025
    • Raphaël Gomès's avatar
      tracing: add a way of calling the Rust tracing framework from Python · 5c0cb780
      Raphaël Gomès authored
      This allows us to collect traces that include Python spans to get a better
      idea of where time is spent.
      
      The focus here is purely to trace span times and no other features are
      included, because the runtime performance impact to Python can be a lot more
      than one would hope.
      
      There are three cases:
        1) No Rust is available, the calls to `tracing.tracer.span` are a no-op
          context manager and should be negligible if not run in a tight loop
      	(otherwise you would get gc cycles etc.)
        2) Rust is present, but without the `full-tracing` feature: calls to
          `tracing.tracer.span` do the same thing as in case 1
        3) Rust is present and built with the `full-tracing` feature: calls to
          `tracing.tracer.span` go through to the Rust tracing system and appear in
      	the resulting chrome tracing.
      5c0cb780
  27. Mar 04, 2025
Loading