Commit graph

2837 commits

Author SHA1 Message Date
Yuya Nishihara
30984dae4a cli: if enabled, parse path arguments as fileset expressions
If this doesn't work out, maybe we can try one of these:
 a. fall back to bare file name if expression doesn't contain any operator-like
    characters (e.g. "f(x" is an error, but "f x" can be parsed as bare string)
 b. introduce command-line flag to opt in (e.g. -e FILESET)
 c. introduce pattern prefix to opt in (e.g. set:FILESET)

Closes #3239, #2915, #2286
2024-04-12 11:36:40 +09:00
Ilya Grigoriev
8fa256ebac New jj debug watchman status command
This command checks not only whether Watchman works, but also whether
it's enabled in the config. Also, the output is easier to understand
than that of the other `jj debug watchman` commands.

It would be nice if `jj debug watchman` called `jj debug watchman
status`, but it's not trivial in `clap` to have a default subcommand.
2024-04-11 10:55:59 -07:00
Yuya Nishihara
33beb8d456 fileset: add recursive iterator over explicit paths
The primary use case is to warn unmatched paths. I originally thought paths in
negated expressions shouldn't be checked, but doing that seems rather
inconsistent than useful. For example, "~x" in "jj split '~x'" should match at
least one file to split to non-empty revisions.
2024-04-11 00:51:19 +09:00
Yuya Nishihara
57b423e3d7 fileset: relax identifier rule to accept more path-like strings
Since fileset is primarily used in CLI, it's better to avoid inner quoting if
possible. For example, ".." would have to be quoted in the original grammar
derived from the revset.

This patch also adds a stricter version of an identifier rule. If we add a
symbol alias, it will follow the "strict_identifier" rule.
2024-04-09 20:42:09 +09:00
Yuya Nishihara
653173abad fileset: implement name resolution stage, add all()/none() functions
#3239
2024-04-09 20:42:09 +09:00
Yuya Nishihara
9c28fe954c fileset: add grammar and implement parser (without name resolution)
The fileset grammar is basically a stripped-down version of the revset grammar,
with a few adjustments:

 * extract function call to "function" rule (like templater)
 * inline "symbol" rule (because "identifier" and "string" should be treated
   differently at the early parsing stage.)

The parser will have a separate name resolution stage. This will help to do
alias substitution properly. I'll probably rewrite the revset parser in the
same way. It will also help if we want to embed fileset expression in file()
revset.
2024-04-09 20:42:09 +09:00
Yuya Nishihara
521bcd81ab dsl_util: deduplicate collect_similar() from revset and templater
For convenience, sort and dedup are done by collect_similar().
2024-04-09 20:42:09 +09:00
Evan Mesterhazy
379849b4b8 Fix documentation for RevsetExpression::ancestors_at and descendants_at
The current documentation is wrong. This is a follow up for
https://github.com/martinvonz/jj/pull/3461#discussion_r1555011289
2024-04-08 08:29:14 -04:00
Yuya Nishihara
73508730aa revset: rewrite identifier rule in common infix-op rule pattern
I don't remember why I made it defined recursively, but it's basically the
same as "primary ~ (infix_op ~ primary)*" rule.
2024-04-08 00:37:25 +09:00
Yuya Nishihara
7f1f73b0fa revset: move whitespace rule to top
The whitespace rule is a bit special, and it seemed weird that the rule is
defined between literals and operator tokens.
2024-04-08 00:37:25 +09:00
Yuya Nishihara
c8f93c50fc revset: remove redundant Result<..> from parse_symbol_rule_as_literal() 2024-04-08 00:37:25 +09:00
Yuya Nishihara
d442cd872f revset: backport \-escapes parsing from templater 2024-04-08 00:37:25 +09:00
Yuya Nishihara
d1ae2d72c8 revset: rename Rule::literal_string to string_literal 2024-04-08 00:37:25 +09:00
Yuya Nishihara
274183fa66 dsl_util: extract helper that parses string literal with \-escapes
The top-level assertion is removed since it's now obvious that the pair
represents a Rule::string_literal.
2024-04-08 00:37:25 +09:00
Yuya Nishihara
8b32a8a916 revset: add support for file(kind:pattern) syntax
There are no more callers of parse_function_argument_to_string(), so it's
removed. This function was a thin wrapper of literal parser, and can be
easily reintroduced if needed.
2024-04-07 19:43:29 +09:00
Yuya Nishihara
850887cf09 fileset: add basic pattern parsing functions
Naming convention is described in FilePattern::from_str_kind(). It's based
on Mercurial's pattern prefixes, but hopefully fixes some inconsistencies.
https://github.com/martinvonz/jj/issues/2915#issuecomment-1956401114

#3239
2024-04-07 19:43:29 +09:00
Yuya Nishihara
3c1d485452 revset: extract function that handles kind:"value" pattern syntax
I also removed comment about the error span. It's unclear whether the kind
was invalid or the value had syntax error.
2024-04-07 19:43:29 +09:00
Yuya Nishihara
47150d2bb4 revset: migrate file() predicate to be based on FilesetExpression 2024-04-06 23:59:54 +09:00
Yuya Nishihara
3e029537c6 fileset: add basic AST-level object and matcher builder
FilesetExpression is similar to RevsetExpression, but there are two major
differences:
 - Union is represented as N-ary operator,
 - Expression node isn't Rc-ed.
The former is because of the nature of the runtime Matcher objects. It's easier
to construct a Matcher from flattened union expressions than from a binary tree.
The latter choice comes from UnionAll(Vec<FilesetExpression>), which doesn't
have to be Vec<Rc<FilesetExpression>>, and Rc<[FilesetExpression]> can't be
constructed from [Rc<_>, ..]. Anyway, the internal representation may change as
needed.

Another design decision I made is Vec<Pattern(RepoPathBuf)> vs
Pattern(Vec<RepoPathBuf>). I chose the former because it will be more closer
to the parsed tree of the fileset language.
2024-04-06 23:59:54 +09:00
Yuya Nishihara
7acfab695a matchers: impl custom Debug for RepoPathTree to get stable and concise output
The default Debug output entries aren't sorted by name, which was inconvenient
while writing snapshot tests.
2024-04-06 23:59:54 +09:00
Yuya Nishihara
c9b21a16be matchers: require Matcher to be Debug
This helps to write snapshot tests.
2024-04-06 23:59:54 +09:00
Yuya Nishihara
f3485c9efb repo_path: make Debug formatting of RepoPathComponent less verbose
Since RepoPath is formatted as a string, it should be okay for RepoPathComponent
to do the same.
2024-04-06 23:59:54 +09:00
Yuya Nishihara
1134dc159e repo_path: use write!() macro to implement Debug 2024-04-06 23:59:54 +09:00
Yuya Nishihara
0b833ea9c0 repo_path: qualify fmt::Error, use fmt::Result for short
"Error" is super common type name, so I think better to not pollute the
namespace with a very specific Error type.
2024-04-06 23:59:54 +09:00
Ilya Grigoriev
93cebcd0c0 protos: cargo update prost prost-builder and regenerate protobufs 2024-04-05 16:56:20 -07:00
Austin Seipp
4b45dde8c6 clippy: disable bogus lints for nightly clippy
The nightly compiler has several clippy fix-its that, if applied, break the
build. There are various bugs about this, but there isn't enough space in the
margins to detail it all.

Just ignore these on a per-function basis; about 70% of them are just multiple
instances happening inside a single function.

This makes `cargo clippy --workspace --all-targets` run clean, even with the
nightly compiler.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Ic26a025d3c62b12fbf096171308b56e38f7d1bb9
2024-04-05 11:39:29 -05:00
Yuya Nishihara
a364310b56 matchers: add binary UnionMatcher
This will be needed to concatenate patterns of different types (such as
"prefix/dir" exact:"file/path".)

The implementation is basically a copy of IntersectionMatcher, with some
logical adjustments. In Mercurial, unionmatcher supports list of matchers
as input, but I think binary version is good enough.
2024-04-05 10:26:01 +09:00
Yuya Nishihara
c4d7425de5 matchers: abstract matcher combinators over Matcher trait
In order to implement a fileset, we'll need owned variants of these matchers.
We can of course let callers move Box<dyn Matcher> into these adapters, but
we might need to somehow clone Box<dyn Matcher>. So, I simply made adapters
generic.
2024-04-05 10:26:01 +09:00
Yuya Nishihara
a7d5a9c99a commit: actually remove boxing from CommitIteratorExt::ids()
Also simplified lifetime bound a bit.
2024-04-05 00:16:42 +09:00
Evan Mesterhazy
d4a04779c0 Make check_rewritable take an iterator of &CommitId instead of &Commit
This function doesn't actually need commits, it only needs their IDs. In some
contexts we may only have commit IDs, so there's no need to require an iterator
of Commits.

This commit also adds a `CommitIteratorExt` that makes it easy to convert an
iterator of `&Commit` to an iterator of `&CommitId`.
2024-04-04 09:31:17 -04:00
Yuya Nishihara
bb87fac1a4 revset: parse "all:" prefix rule by pest
I had to use negative lookahead !":" because we still support a dummy ":"
operator to provide a suggestion.
2024-04-03 08:59:42 +09:00
Yuya Nishihara
13dadadcdc revset: add ParseState constructor 2024-04-03 08:59:42 +09:00
Christoph Koehler
7bde6ddc29 revset: add working_copies() function
It includes the working copy commit of every workspace of the repo.

Implements #3384
2024-04-01 19:36:53 -06:00
Martin von Zweigbergk
bbe906b426 repo: merge rewrite state into single parent_mapping with enum
This simplifies the code and reduces the risk of inconsistencies in
the data.

Thanks to Yuya for the suggestion.
2024-03-30 09:35:45 -07:00
Yuya Nishihara
a6615bf36d cli: render string pattern suggestion as a hint
Templater doesn't have the one yet, but I think it belongs to the same
category.

For clap::Error, we could use clap's own mechanism to render suggestions as
"tip: ...", but I feel "Hint: ..." looks better because our error/hint message
is capitalized.
2024-03-30 23:53:17 +09:00
Yuya Nishihara
d759ba11f1 revset: don't stringify StringPatternParseError
This helps to add hint at the CLI layer.
2024-03-30 23:53:17 +09:00
Yuya Nishihara
c4d48c5139 revset: add constructor for InvalidFunctionArguments error
Inlined some of the make_error() closures instead. I'll make string pattern
handler preserve the source error object.
2024-03-30 23:53:17 +09:00
Yuya Nishihara
b09732f4f8 revset, templater: split parse error constructor that sets source error object
I'm going to add RevsetParseError constructor for InvalidFunctionArguments,
with/without a source error, and I don't want to duplicate code for all
combinations. The templater change is just for consistency.

I couldn't find a good naming convention for the builder-like API, so it's
called .with_source(mut self, _). Another option was .source_set(source).
Apparently, it's not uncommon to name consuming constructor as
with_<something>().
2024-03-30 23:53:17 +09:00
Yuya Nishihara
73b60903ce tree: flatten TreeMergeError into BackendError 2024-03-30 22:40:05 +09:00
Yuya Nishihara
916014dc1e tree: consolidate read error variants
There isn't much difference between BackendError::ReadObject of file type
and TreeMergeError::ReadError. They are both caused by the backend.
2024-03-30 22:40:05 +09:00
Martin von Zweigbergk
bfa43d16f9 rewrite: don't collect set of heads to add unnecessarily 2024-03-30 05:21:48 -07:00
Martin von Zweigbergk
c40949208b rewrite: all rewritten commits are no longer heads
Now that we no longer bother to keep the set of heads to add and
remove updated while we rewrite descendants, we can simplify how we
find the set of heads to remove - it's simply all commits that have
been marked rewritten, divergent, or abandoned, i.e. the keys in
`parent_mapping`.
2024-03-30 05:21:48 -07:00
Martin von Zweigbergk
bb1fef3258 rewrite: drop redundant unioning of old commits with abandoned commits
We always add abandoned commits as key in `parent_mapping`.
2024-03-30 05:21:48 -07:00
Martin von Zweigbergk
db4b905bc9 repo: when setting rewritten or divergent, remove from abandoned
I don't think we have any transactions that mark commit as abandoned
and then later mark it as rewritten or divergent. But if we ever do, I
think it should be considered just rewritten/divergent. So let's
enforce that invariant by removing the old value from the set of
abandoned commits.
2024-03-30 05:21:48 -07:00
Yuya Nishihara
f20004fffe git_backend: classify "merge with root" as user error
Perhaps, there will be more error types that hold BackendError internally, but
this change is good enough to handle a merge error.
2024-03-30 11:14:25 +09:00
Yuya Nishihara
1e83faf4f8 tree: remove useless "Backend error" message from TreeMergeError
I don't think it adds any contextual information. TreeMergeError is somewhat
similar to BackendError.
2024-03-30 11:14:25 +09:00
Evan Mesterhazy
dd1def02e4 Move parse_string_pattern in cli to StringPattern::parse in lib
This commit moves the parse_string_pattern helper function into the
str_util module in jj lib and adds tests for it.

I'd like to reuse this code in a function defined by `UserSettings`, which is
part of the jj lib crate and cannot use functions from the cli crate.
2024-03-29 08:48:09 -04:00
Yuya Nishihara
916dc30828 revset: use common argument error instead of FsPathParseError
It's not special compared to the other argument errors, and we can now track
the error source separately.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
074e6e12bc revset, templater: include short parse error description in summary line
This makes the summary line more informative. Even though it just duplicates
the message printed later, I think it's easier to follow.

This patch also adjusts some RevsetParseError messages because it seemed
redundant to repeat "revset function", "argument", etc.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
d17166628f revset, templater: simplify parse error impls by using thiserror
This patch moves all "source" errors to the source field to conform to
thiserror API. It will probably help to keep ErrorKind enums comparable.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
2cd70bdf14 revset, templater: render parse error as usual error chain
Because the CLI error handler now prints error sources in multi-line format,
it doesn't make much sense to render Revset/TemplateParseError differently.

This patch also fixes the source() of the SyntaxError kind. It should be
self.pest_error.source() (= None), not self.pest_error.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
844d3d0ff0 revset, templater: allow any kind of error as parse error source
I'm going to make TemplateParseError hold RevsetParseError as Box<dyn _>, but
Box<dyn std::error::Error ..> doesn't implement Eq. I could remove Eq from
ErrorKind enums, but it's handly if these enums remain as value types.

This change will also simplify fmt::Display and error::Error impls.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
32efb4034d revset: make span of parse error mandatory, remove Option<_>
Since all callers of RevsetParseError have some reasonable span, we don't
need a special case for WorkingCopyWithoutWorkspace error.
2024-03-28 10:53:06 +09:00
Yuya Nishihara
8ad0a703d4 repo_path: accept from_relative_path("."), make "".to_fs_path("") return "."
It's common to normalize an empty directory path as ".". This change unblocks
the use of from_relative_path() in edit_sparse().

There are a couple of callers who do to_fs_path(Path::new("")), but they all
translate non-directory paths, which should never be empty.
2024-03-28 10:52:51 +09:00
Martin von Zweigbergk
9c382fd8c6 rewrite: exclude already rewritten commits from set to rebase
We currently include the commits in `parent_mapping` and `abandoned`
in the set of commits to visit when rebasing descendants. The reason
was that we used to update branches and working copies when we visited
these commits. Since we started updating refs after rebasing all
commits, there's no need to even visit these commits.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
49ff818e97 rewrite: calculate branches later, remove it from state 2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
718e54b01a rewrite: calculate heads_to_add later, remove it from state
Similar to the previous two commits.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
2ee1147145 rewrite: calculate heads_to_remove later, remove it from state
Similar to the previous commit.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
b3dd038907 rewrite: calculate new_commits later, remove it from state
We only use `new_commits` in `update_heads()`, so let's calculate it
there. It should also be more correct in case other commits were
created after we initialized `DescendantRebaser`.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
5e7a4a2028 rewrite: update heads outside update_references()
Now that we only call `update_references()` in one place, there's no
reason to have it also update `heads_to_add` and `heads_to_remove`. By
moving it out of the function, we can consolidate the logic in one
place.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
9511de486e rewrite: extract a function for updating heads 2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
0f7a86d725 rewrite: move new_parents() to MutableRepo
The function only uses state from `MutableRepo`, so it should be
implemented on that type.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
cfdb341c6b rewrite: make rebase_commit_with_options() mark abandoned commit
When `rebase_commit_with_options()` decides to abandons a commit, it
records the new parents in the `MutableRepo`, but it's currently the
caller's responsibility to remember to mark it as abandoned. Let's
move that logic into the function to reduce the risk of future bugs.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
3ddf9f4329 repo: add parents of abandoned commit to parent_mapping
By adding the abandoned commit's parents to `parent_mapping`, we can
remove a bit more of the special handling of abandoned commitsin
`DescendantRebaser`.
2024-03-26 09:50:50 -07:00
Martin von Zweigbergk
0481e67dfd rewrite: drop now-unnecessary updating of branches map
Since we update all branches at the end now, we never update them in
several steps, so there are no intermediate locations we need to
remember.
2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
5e8d7f8c6f rewrite: update references after rewriting all commits 2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
e55ebd4fe6 rewrite: drop redundant update of parent_mapping after rebasing commit
In the normal case when we don't abandon a commit because it became
empty, then `CommitBuilder::write()` will have recorded the new commit
as a rewrite of the old commit. We don't need to do that again in
`rebase_one()`.
2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
4406005dce rewrite: make DescendantRebaser use state stored in MutableRepo
A subset of the state in `DescendantRebaser` now matches exactly what
`MutableRepo` already stores, so we can avoid copying that state and
have `DescendantRebaser` use it directly instead. Having a single
source of truth for the state will enable further simplifications and
improvements.
2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
ad16bec3a6 rewrite: move an assertion a little earlier
I'm going to make `DescendantRebaser` share the state about rewritten
commits with `MutableRepo` next. That means that the call to
`rebase_commit_with_options()` will update that state, which would
make this assertion fail. So let's move it a little earlier to avoid
that.
2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
a6857a7a8f repo: rename abandoned_commits to abandoned
This is just to match `DescendantRebaser`, to make the next commit a
bit simpler. I think `MutableRepo` still has few enough fields that
just `abandoned` is clear enough. Maybe we'll move the three
rewrite-related fields into a new struct at some point.
2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
6e3ceb4d1c repo: store separate divergent field, pass into DescendantRebaser
With this patch, `MutableRepo` has the same tracking of rewritten
commits as `DescendantRebaser`, so we can simply pass that state into
`DescendantRebaser` when we create it. The next step is to remove the
state from `DescendantRebaser`.
2024-03-25 23:00:44 -07:00
Ilya Grigoriev
de0de4013d hex_utils: fix typo found by clippy 2024-03-25 21:23:09 -07:00
Martin von Zweigbergk
890a8e282f repo: update working copy to first divergent commit 2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
d2043f069e repo: delete record_rewritten_commit()
I don't think we have any callers left that call
`record_rewritten_commit()` multiple times within a transaction and
expect it to result in divergence. I think we should consider it a bug
to do that.
2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
e55168fa3e repo: make record_rewritten_commit() accept only one replacement id
All callers now pass a single new commit and I would like to keep it
that way.
2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
af7ef4d04e repo: add a method for explicitly recording divergent rewrite
I plan to remove `record_rewritten_commit()` and instead make repeated
rewrites replace the rewrite state.
2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
b54ace4954 rewrite: mark divergent commits in parent_mapping too
When rebasing descendants, we generally move branches, child commits,
the working copy to the rewritten commit(s). However, we don't move
the working copy to the new rewritten commit (s) if the old commit had
been abandoned, and we don't move child commits if the rewriten was
divergent.

This patch aims to make it clearer that there's only one mapping from
old to new parents, and that is in `parent_mapping`. It does so by
merging the current `divergent` map into it, and makes the `divergent`
just a set instead. When finding the new parents for a child, we leave
the existing parent if it's in the set.

My longer-term goal is to move `parent_mapping`, `abandoned`, and
`divergent` into `MutableRepo` (maybe in a nested struct), so we can
do some transformations on descendants as we rebase them. By having
the state in a single place (not moving it from `MutableRepo` to
`DescendantRebaser` as we currently do), I hope it will be easier to
write a `MutableRepo::transform_descendants(callback)`, where the
callback gets a `CommitBuilder` and can change parents of the commit,
for example.
2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
ba244423e8 rewrite: avoid an unnecessary clone 2024-03-25 06:53:14 -07:00
Yuya Nishihara
c311131ee2 log: encode elided node as None
Since elided graph entry has no associated commits, it makes some sense to
represent as None?
2024-03-24 10:32:15 +09:00
Benjamin Tan
3034dbba3f git-push: Display messages from remote
The implementation of sideband progress message printing is aligned with
Git's implementation. See
43072b4ca1/sideband.c (L178).

Closes #3236.
2024-03-23 20:17:04 +08:00
Ilya Grigoriev
02a04d0d37 test_conflicts and test_resolve_command: use indoc! to indent conflict markers in tests
Apart from (IMO) looking nicer, this will also sidestep the potential problem
that if the file contains actual jj conflict markers (`>>>>>>>` in the beginning
of a line, for example), jj would currently have trouble materializing and
subsequently parsing conflicts in the file if it actually became conflicted.

I'll demo this bug in either this or a subsequent PR. It's the kind of bug that
sounds serious in theory but might never cause a problem in practice.

After this PR, only `docs/tutorial.md` has a conflict marker that's not indented.
There's only one there, so hopefully it won't be too much of a pain to deal with.

I also indented other strings in `test_conflicts.rs`. IMO, this looks nice and
more consistent with the `insta::assert_snapshot` output. I didn't spend the
time to do the same for `test_resolve_command`.
2024-03-22 23:27:25 -07:00
Anton Älgmyr
e2eb5bddf9 Make node symbols templatable in the graphs.
Adds config options
* templates.log_graph_node
* templates.log_graph_node_elided
* templates.op_log_graph_node
2024-03-21 17:41:31 +01:00
dploch
9380f9d529 rewrite: move handling of simplified ancestry into rebase_commit_with_options
It seems incorrect that `simplify_ancestor_merge` is ignored when it's part of the helper's input.
2024-03-20 11:57:54 -04:00
Ilya Grigoriev
4fbe6aecc9 clippy: remove some unused code beta clippy/rustc compain about
There are still some warnings from (seemingly) clippy bugs. Quoting
myself from Discord:

> PSA: the latest beta cargo clippy (from Rust 1.78) has some problems
> that affect jj: https://github.com/rust-lang/rust-clippy/issues/12467
> and https://github.com/rust-lang/rust-clippy/issues/12377.  You could
> disable clippy::assigning_clones and clippy::empty_docs as a workaround.
> VS Code can disable them in rust-analyzer, you can also use
> https://github.com/ericseppanen/cargo-cranky (you can put Cranky.toml in
> the per-user gitignore).
2024-03-19 18:33:29 -07:00
Martin von Zweigbergk
f865c1bc5d index: print a milder "Reindexing..." message on version mismatch
Closes #3323.
2024-03-18 13:50:14 -07:00
Yuya Nishihara
50363419fb revset: substitute '~(::x)' to 'x..'
Suppose we have an alias 'immutable()' = '::immutable_heads()', user can
express (visible) mutable set as '~immutable()'. 'immutable_heads()..' can
terminate early, but a generic difference 'all() & ~immutable()' can't.
2024-03-17 14:50:48 +09:00
Yuya Nishihara
9207314173 revset: add substitution rule for "::x & ~(::y-)"
Suppose the generation value is usually small, it should be faster to do
bounded range look up first 'y-', then walk ancestors with the unwanted set
'y-..x'.
2024-03-17 14:50:48 +09:00
Yuya Nishihara
39a460a077 revset: extract helper function that substitutes "::x & ~(::y)"
I'm going to add a similar substitution rule for "~(::y)".
2024-03-17 14:50:48 +09:00
Yuya Nishihara
3f9ac78215 revset: update legacy range syntax in comment 2024-03-17 14:50:48 +09:00
Yuya Nishihara
a777cfe98e index: remove topo_order() which is no longer used
The same thing can be achieved by evaluating the input as a revset.
2024-03-17 11:44:41 +09:00
Martin von Zweigbergk
c55e08023e workspace: don't lose sparsed-away paths when recovering workspace
When an operation is missing and we recover the workspace, we create a
new working-copy commit on top of the desired working-copy commit (per
the available head operation). We then reset the working copy to an
empty tree because it shouldn't really matter much which commit we
reset to. However, when the workspace is sparse, it does matter, as
the test case from the previous patch shows. This patch fixes it by
replacing the `reset_to_empty()` method by a new `recover(&Commit)`,
which effectively resets to the empty tree and then resets to the
commit. That way, any subsequent snapshotting will result keep the
paths from that tree for paths outside the sparse patterns.
2024-03-16 07:30:36 -07:00
Alexis (Poliorcetics) Bourget
93c707a469 lib: improve error message for invalid string pattern, suggesting to use one of the known one 2024-03-16 14:22:16 +01:00
Evan Mesterhazy
f30857190e Add more test cases for Index::common_ancestors 2024-03-14 12:54:13 -04:00
Evan Mesterhazy
adaedd5556 Add documentation to lib/src/index.rs and lib/src/default_index/ 2024-03-14 12:54:13 -04:00
Yuya Nishihara
5806dbfd32 revset_graph: detach CompositeIndex, reimplement as RevWalk
For API consistency. It wouldn't practically matter unless we want to reuse
.iter_graph() in lazy event-driven GUI context.

I don't see significant performance difference:
- jj-0: original impl with look-ahead IndexEntry<'_> buffer
- jj-1: this patch

With dense graph
```
% hyperfine --sort command --warmup 3 --runs 10 -L bin jj-0,jj-1 \
  "target/release-with-debug/{bin} -R ~/mirrors/git --ignore-working-copy log -r.. -T ''"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r.. -T ''
  Time (mean ± σ):      1.367 s ±  0.008 s    [User: 1.261 s, System: 0.105 s]
  Range (min … max):    1.357 s …  1.380 s    10 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r.. -T ''
  Time (mean ± σ):      1.344 s ±  0.017 s    [User: 1.245 s, System: 0.099 s]
  Range (min … max):    1.313 s …  1.369 s    10 runs

Relative speed comparison
        1.02 ±  0.01  target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r.. -T ''
        1.00          target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r.. -T ''
```

With sparse graph
```
% hyperfine --sort command --warmup 3 --runs 10 -L bin jj-0,jj-1 \
  "target/release-with-debug/{bin} -R ~/mirrors/git --ignore-working-copy log -r'tags()' -T ''"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r'tags()' -T ''
  Time (mean ± σ):      1.347 s ±  0.017 s    [User: 1.216 s, System: 0.130 s]
  Range (min … max):    1.321 s …  1.379 s    10 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r'tags()' -T ''
  Time (mean ± σ):      1.379 s ±  0.023 s    [User: 1.238 s, System: 0.140 s]
  Range (min … max):    1.328 s …  1.403 s    10 runs

Relative speed comparison
        1.00          target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r'tags()' -T ''
        1.02 ±  0.02  target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r'tags()' -T ''
```
2024-03-14 10:07:19 +09:00
Yuya Nishihara
3c8f22456b revset_graph: remove lifetimed IndexEntry<'_> from look_ahead buffer
Prepares for removing &CompositeIndex from the RevsetGraphIterator struct.
The input iterator will also be changed to position-based.

I've turned self.look_ahead.get().unwrap() into assertion, but it's not super
important here. It's just for sanity that we've mapped missing edges properly.
FWIW, we could say RevsetGraphIterator is an example of iterating *and* testing
membership of the input revset (though the yielded entries are discarded.)
2024-03-14 10:07:19 +09:00
Yuya Nishihara
699707905c index: reorganize revset_graph_iterator as private module of default_index
The RevsetGraphIterator type is hidden so that the Iterator trait can be
implemented differently.
2024-03-14 10:07:19 +09:00
Yuya Nishihara
17e46e0932 revset: extend lifetime of CommitId/ChangeId iterators
For the same reason as the previous commit. Since self.inner.positions()
basically clones the underlying evaluation tree, there is no reason to stick
to &self lifetime. Perhaps, some of the CLI utility can be changed to not
collect() the iterator.

Migrating iter_graph() requires non-trivial changes, so it will be done
separately.
2024-03-13 10:47:58 +09:00
Yuya Nishihara
3bf41d0c52 revset: extend lifetime of containing_fn()
This allows callers to cache the returned function at 'index lifetime. It's
important in templater. It also means the returned function could be 'static
if the index were Arc<_> and we had a trait interface to achieve that.

Option<Box<dyn ..>> is removed since RevWalk is fused.
2024-03-13 10:47:58 +09:00
Yuya Nishihara
027bd8f03a revset: extend lifetime of internal evaluation nodes
This makes the whole evaluation tree 'static, and we can freely move it without
keeping the root RevsetImpl object alive.

Perhaps, "Self: 'a" can be replaced with 'static, but let's leave it for now.
It's not technically wrong to store lifetimed object in InternalRevset.
2024-03-13 10:47:58 +09:00