ok/jj
1
0
Fork 0
forked from mirrors/jj
Commit graph

2841 commits

Author SHA1 Message Date
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
Yuya Nishihara
bc49b6b190 revset: make PurePredicateFn clonable
Prepares for dropping &self lifetime from to_predicate_fn(). All predicate
functions could be wrapped as Box::new(PurePredicateFn(Rc::new(f))) instead, but
I don't think the .clone() cost matters.
2024-03-13 10:47:58 +09:00
dploch
6e8f1fb390 extensions_map: create a type-safe container for arbitrary objects 2024-03-12 16:52:49 -04:00
Yuya Nishihara
283907418a revset: detach index from InternalRevset::positions()
Perhaps, union/intersection/difference combinators can be moved to the
rev_walk module, but let's think about that later.
2024-03-12 20:59:38 +09:00
Yuya Nishihara
78dbaba4dc revset: remove entry-based API from InternalRevset
Now all source/sink nodes produce/consume IndexPosition, so it doesn't make
sense to keep InternalRevset::entries().
2024-03-12 20:59:38 +09:00
Yuya Nishihara
a733b0b052 revset: detach index from predicate fn, turn it into position-based
This is the step towards removing &CompositeIndex references from the revset
evaluation tree. The filter input is changed from &IndexEntry to IndexPosition
to simplify the lifetime thingy. We might want to pass around CommitId or
Commit object once it's loaded, but that can be implemented later. I don't
see significant performance difference in revset benches.
2024-03-12 20:59:38 +09:00
Yuya Nishihara
97e69d1dcc index: add filter RevWalk adapter
FilterRevset will be built on top.
2024-03-12 20:59:38 +09:00
Yuya Nishihara
cfa067a0a9 index: add peekable RevWalk adapter
This helps to migrate union/intersection/difference iterators to RevWalk.
2024-03-12 20:59:38 +09:00
Yuya Nishihara
8f0b9a0e4a index: add RevWalk wrapper for eagerly evaluated set
This serves the same role as templater::Literal. I'm going to add basic
RevWalk adapters so that the revset evaluation tree can be constructed without
capturing the index. EagerRevWalk will help to write tests for these adapters.
2024-03-12 20:59:38 +09:00
Yuya Nishihara
7d43a5c2c0 tests: alias index.as_composite() in revset combinator/accumulator tests 2024-03-12 20:59:38 +09:00
Aleksey Kuznetsov
6fd15dc7e5 graphlog: refactor out node symbols from GraphLog
Now as default and elided node symbols come from the config, the next logical
step is to use them directly bypassing GraphLog. Note that commands like `jj op
log` and `jj obslog` do not use the elided node symbol at all.
2024-03-12 08:25:58 +05:00
Yuya Nishihara
9c1d5d155e index: remove HRTB stuff by implementing RevWalkIndex for CompositeIndex 2024-03-11 17:24:10 +09:00
Yuya Nishihara
3d0952b316 index: implement AsCompositeIndex for CompositeIndex, not for &CompositeIndex
Just a minor code cleanup. We still need Index for &CompositeIndex because the
type is unsized, and unsized type cannot be converted to another dyn reference.
2024-03-11 17:24:10 +09:00
Yuya Nishihara
243675b793 index: turn CompositeIndex into transparent reference type
This helps to eliminate higher-ranked trait bounds from RevWalkRevset and
RevWalk combinators to be added. Since &CompositeIndex is now a real reference,
it can be passed to functions as index: &T.
2024-03-11 17:24:10 +09:00
Yuya Nishihara
c8be8c3edd index: add type alias for "dyn IndexSegment" to clarify it's 'static
This helps to migrate CompositeIndex<'_> wrapper to &CompositeIndex. If
the wrapped reference had a lifetimed field, it couldn't be represented as
a trivial reference type.
2024-03-11 17:24:10 +09:00
Yuya Nishihara
64e0be2477 revset: consolidate early-return condition of PositionsAccumulator
Since consume_to() checks the bottom position yielded from the source iterator,
it makes sense to add the same check for the cached positions.
2024-03-11 17:24:01 +09:00
Martin von Zweigbergk
4d42604913 git_backend: write trees involved in conflict in git commit header
We haven't used custom Git commit headers for two main reasons:

1. I don't want commits created by jj to be different from any other
   commits. I don't want Git projects to get annoyed by such commit
   and reject them.

2. I've been concerned that tools don't know how to handle such
   headers, perhaps even resulting in crashes.

The first argument doesn't apply to commits with conflicts because
such commits would never be accepted by a project whether or not they
use custom commit headers. The second argument is less relevant for
conflicted commits because most tools will be confused by such commits
anyway.

Storing conflict information in commit headers means that we can
transfer them via the regular Git wire protocol. We already include
the tree objects nested inside the root-level tree, so they will also
be transferred.

So, let's start by writing the information redundantly to the commit
header and to the existing storage. That way we can roll it back if we
realize there's a problem with using commit headers.
2024-03-10 20:51:05 -07:00
Aleksey Kuznetsov
cd3d75ebf6 revset: introduce more performant way to check if a commit is in a revset
Initially we were thinking to have `Revset` return something like
`CachedRevset`:

```
pub trait CachedRevset {
  fn iter(&self) -> Box<dyn Iterator<Item = Commit>>;
  fn contains(&self, &CommitId) -> bool;
}
```

But we weren't sure what use case for `iter` would be, so we dropped the `iter`
method. `CachedRevset` with single `contains` method needed a better name. We
weren't able to come up with one, so we decided instead to have a method on
`Revset` that returns a closure to check if a commit is in a revset.
2024-03-11 08:27:35 +05:00
Yuya Nishihara
8a406358af index: migrate RevWalkRevset to be based off new RevWalk trait
"for<'index> RevWalk<CompositeIndex<'index>, .." works as of now, but it won't
be composed well. So I'll turn CompositeIndex<'_> into &CompositeIndex in the
next batch, and remove "for<'index>".
2024-03-11 11:25:54 +09:00
Yuya Nishihara
4107cad80e index: migrate RevWalkDescendants to new RevWalk trait
Just for consistency. Descendants are always evaluated eagerly, so this change
isn't strictly needed.
2024-03-11 11:25:54 +09:00
Yuya Nishihara
b6cbd8b90b index: add trait and adaptor types to detach index from RevWalk*
This eliminates lifetimed fields from RevWalk objects, and the RevWalk object
will be embedded directly in RevWalkRevset.

This patch adds two separate iterator adapters. They are identical at this
point, but I'm going to add detach/reattach methods only to the borrowed
version. I'm also planning to change CompositeIndex<'_> to &CompositeIndex
to get around higher-ranked trait bound restrictions.
2024-03-11 11:25:54 +09:00
Yuya Nishihara
d780910bec index: make RevWalk yield IndexPosition instead of IndexEntry
This simplifies the RevWalkIndex API. It would probably add fractional msecs of
overhead per next() call, but I don't see significant difference in revset
benches.
2024-03-11 11:25:54 +09:00
Anton Älgmyr
099f06bf71 Add configuration options for node symbols in the graphs. 2024-03-09 21:16:58 +01:00
Yuya Nishihara
f51c5d7e57 index: consistently use IntoIterator in RevWalk builder API
Since the return type is no longer "impl Iterator<..>", there isn't lifetime
issue anymore.
2024-03-10 01:45:30 +09:00
Yuya Nishihara
2615fed5be index: handle cut-off position of RevWalk by queue
I'm going to make CompositeIndex<'_> detachable from the RevWalk, and
"F: Fn(CompositeIndex) -> Box<dyn Iterator<..>>" of RevWalkRevset<F> will
be replaced with "W: RevWalk<CompositeIndex>". This will simplify the code
structure, but also means that we can no longer apply .take_while() here and
convert it back to RevWalk. Fortunately, ancestors_until_roots() is the only
function I need to reimplement.
2024-03-10 01:45:30 +09:00
Yuya Nishihara
34fbaaaad6 index: construct RevWalk queue after item type is settled
It doesn't make sense to build BinaryHeap with intermediate type, and I'm
going to reimplement take_until_roots() in a way that the queue drops
uninteresting items.
2024-03-10 01:45:30 +09:00
Yuya Nishihara
8480ee9e05 index: migrate RevWalk constructors to builder API
The current RevWalk constructors insert intermediate items to BinaryHeap
and convert them as needed. This is redundant, and I'm going to add another
parameter that should be applied to the queue first. That's why I decided
to factor out a builder type. I considered adding a few set of factory
functions that receive all parameters, but they looked messy because most of
the parameters are of [IndexPosition] type.

This patch also adds must_use to the builder and its return types, which are
all iterator-like.
2024-03-10 01:45:30 +09:00
Yuya Nishihara
008adecf23 index: rename ancestors iterators from RevWalk* to RevWalkAncestors*
I'm planning to add RevWalk trait, and this patch frees up the name. It seems
also good for consistency as we have RevWalkDescendants*.
2024-03-10 01:45:30 +09:00
Yuya Nishihara
fa60026f25 repo_path: don't panic on invalid UTF-8 path component
Although watchman client appears to fail at decoding non-UTF-8 path (somewhere
in serde), jj shouldn't panic if watchman could deal with that.

The outer error message "path not in the repo" would sounds odd, but I think
that's okay because 1. it's unlikely that a user input is not UTF-8, and 2.
it's technically correct that a non-UTF-8 path is not contained in the repo.
2024-03-09 11:01:43 +09:00
Yuya Nishihara
a224d0f172 repo_path: show more detailed error if filesystem path failed to parse
This should address both use cases:
 1. If from_relative_path() is directly called, the error says ".." shouldn't
    be included in the (normalized) relative path.
 2. If parse_fs_path() is used, the error message contains paths relative to
    cwd. #3216
2024-03-09 11:01:43 +09:00
Yuya Nishihara
a76f716cd1 index: remove RevWalk newtypes that were necessary to hide impl types/traits
Some of the RevWalk methods could be generalized, but I decided to not try that
for now. I'll probably need to do more cleanup to (hopefully) remove 'index
lifetime from these types.
2024-03-08 10:07:40 +09:00
Yuya Nishihara
8451453f3a index: hide walk_revs() and related types
They are now implementation details of the default index backend.
2024-03-08 10:07:40 +09:00
Yuya Nishihara
f5eb172769 tests: remove last use of walk_revs() from integration tests 2024-03-08 10:07:40 +09:00
Martin von Zweigbergk
5ce5022ee9 cargo: mark the jj-lib-proc-macros crate for publish
I don't think we can publish a new version of the other crates without
publishing `jj-lib-proc-macros`.
2024-03-06 20:35:38 -08:00
Thomas Castiglione
d661f59f9d working_copy: implement symlinks on windows with a helper function
enables symlink tests on windows, ignoring failures due to disabled developer mode,
and updates windows.md
2024-03-05 15:16:38 +08:00
Austin Seipp
bd551099f0 cargo: update whoami dependency to 1.5.0
This requires a code tweak to avoid clippy failures, as `whoami` 1.5.0 has
deprecated the default `hostname()` function.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2024-03-04 18:35:21 -06:00
Yuya Nishihara
c8023dbd8b signing: insert tracing events to command invocation paths
This might help debug command failure.
2024-03-05 09:23:15 +09:00
Yuya Nishihara
fa7864edeb signing: ensure child processes are wait()ed on I/O error
This will also provide a better error indication. If write() failed, the child
process would presumably have exited with non-zero status and error message to
stderr.
2024-03-05 09:23:15 +09:00
Evan Mesterhazy
a09ee4b9a3 Make URLs in docs hyperlinks
`cargo doc` complains that two URLs aren't actually links:

```
warning: this URL is not a hyperlink
  --> lib/src/fsmonitor.rs:66:6
   |
66 | /// (https://facebook.github.io/watchman/). Requires `watchman` to already be
   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://facebook.github.io/watchman/>`
   |
   = note: bare URLs are not automatically turned into clickable links
   = note: `#[warn(rustdoc::bare_urls)]` on by default

warning: `jj-lib` (lib doc) generated 1 warning (run `cargo fix --lib -p jj-lib` to apply 1 suggestion)
 Documenting jj-cli v0.14.0 (/Users/emesterhazy/oss/github.com/martinvonz/jj/cli)
 Documenting testutils v0.14.0 (/Users/emesterhazy/oss/github.com/martinvonz/jj/lib/testutils)
warning: this URL is not a hyperlink
    --> cli/src/cli_util.rs:2077:41
     |
2077 | /// To get started, see the tutorial at https://github.com/martinvonz/jj/blob/main/docs/tutorial.md.
     |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://github.com/martinvonz/jj/blob/main/docs/tutorial.md.>`
     |
     = note: bare URLs are not automatically turned into clickable links
     = note: `#[warn(rustdoc::bare_urls)]` on by default

warning: `jj-cli` (lib doc) generated 1 warning (run `cargo fix --lib -p jj-cli` to apply 1 suggestion)
```

This commit fixes the warnings by making the watchman URL a hyperlink and by
disabling the lint for the jj-cli error. Disabling the link is the right thing
to do because the comment is captured by clap and printed when `jj --help`
runs and any markdown formatting like `<>` is passed through.
2024-03-04 16:05:42 -05:00
Yuya Nishihara
24868e5192 gpg_signing: handle early termination of gpg command in verify path
Also fixes missing wait() on I/O error. We have the same problem in several
places. I'll fix them in another batch.
2024-03-03 18:35:10 +09:00
Yuya Nishihara
a0c31134ba gpg_signing: split run_command() into sign/verify variants 2024-03-03 18:35:10 +09:00
Yuya Nishihara
093f61607e gpg_signing: leverage Command builder API to eliminate type casting noises 2024-03-03 18:35:10 +09:00
Yuya Nishihara
dbe99c8fe0 gpg_signing: extract bottom half of run() to helper function
I'll split it further to fix EPIPE handling.
2024-03-03 18:35:10 +09:00
Evan Mesterhazy
ff4a5aa491 Store OpHeadsStore in UnpublishedOperation instead of RepoLoader
The only thing we need from the `RepoLoader` is the `OpHeadsStore`, so we can
extract it in UnpublishedOperation::new instead of keeping the entire
`RepoLoader` around.
2024-03-02 23:08:57 -05:00
Evan Mesterhazy
1439c902be Replace NewRepoData with ReadonlyRepo in the UnpublishedOperation struct
`NewRepoData` is just a container that holds data used to construct a
`ReadonlyRepo`. The `ReaonlyRepo` is always constructed before the
`UnpublishedOperation` is dropped, so we can simply construct the
`ReadonlyRepo` upfront and delete the `NewRepoData` type.
2024-03-02 23:08:57 -05:00
Evan Mesterhazy
c4cbf25545 Remove the std::Option around UnpublishedOperation::data
The Option is unnecessary now since `UnpublishedOperation` doesn't implement
the Drop trait (the `MustClose` member implements it instead).
2024-03-02 23:08:57 -05:00
Evan Mesterhazy
962b188b76 Replace custom Drop impl for UnpublishedOperation with #[must_use]
The custom Drop impl prevents us from moving members of UnpublishedOperation,
and is the reason why `NewRepoData` is wrapped in an `Option`. We don't use
custom Drop functions like this for debugging elsewhere in the codebase, and in
some ways #[must_use] provides better protection since it will typically cause
a compiler error if the UnpublishedOperation isn't used.
2024-03-02 23:08:57 -05:00
Evan Mesterhazy
6ee19589e9 Adjust visibility of codependent MutableRepo and CommitBuilder functions
MutableRepo and CommitBuilder both define public (now crate-public) functions
which should only be called by each other. This commit adds documentation and
restricts visibility of these functions to the jj_lib crate. It might be even
better to move CommitBuilder to the same module as MutableRepo so that these
codependent functions can be private to the module to avoid misuse.
2024-03-02 22:41:47 -05:00
Ilya Grigoriev
96bf190234 Nightly clippy fixes
There are a few additional warnings because of
https://github.com/rust-lang/rust-clippy/issues/12377, which is a
nightly-only bug that will hopefully be fixed.
2024-03-02 18:19:14 -08:00
Evan Mesterhazy
2f7b15b7b1 Add documentation comments for operation, transaction, and view types 2024-03-02 15:35:41 -05:00
Evan Mesterhazy
a335321c45 Add documentation comments for several types
These comments are intended to make it easier for new developers to get up to
speed with the project. This is just a starting point... there are other types
and functions that could benefit from documentation.
2024-03-02 15:01:55 -05:00
Evan Mesterhazy
b8aa9a1a2b Make a minor simplification to CommitBuilder::write
There's no need to have a block of code at the beginning of the function to
cache the rewrite source id. We can simply check the necessary condition before
calling record_rewritten_commit.

This tweak makes the function a little easier to read since we don't check the
condition until we're ready to do the work.
2024-03-02 13:40:18 -05:00
Evan Mesterhazy
276276ea01 Reorder functions in impl Repo for MutableRepo to match trait
This is just a clean-up to silence a lint that complains that the functions are
defined in a different order than they are in the trait.
2024-03-02 13:40:04 -05:00
Yuya Nishihara
5df7a42915 merge_tools: move "ui.diff-instructions" to CLI and config/misc.toml
There are no users of this option in jj-lib. Let's simplify it.
2024-03-02 23:33:45 +09:00
Evan Mesterhazy
5c252bd8e4 Add test cases where HexPrefix::new fails due to invalid inputs 2024-03-01 10:00:22 -05:00
Yuya Nishihara
4c16c05be1 cli: move --git-repo path normalization back from workspace
This reverts dc074363d1 "no-op: Move external git repo canonicalization into
Workspace::init_git_external." As I said in the PR comment, appending ".git"
is normalization of the user input, which is IMHO more appropriate to be done
in the CLI layer.
2024-02-28 09:03:16 +09:00
Evan Mesterhazy
a28beb5b8f Allow id_type! to capture doc comments
This allows us to define documentation comments for types implemented using the
id_type! macro. Comments defined above the type inside the macro will be
captured and visible in generated docs.

Example:

```
id_type!(
    /// Stable identifier for a [`Commit`]. Unlike the `CommitId`, the `ChangeId`
    /// follows the commit and is not updated when the commit is rewritten.
    pub ChangeId
);
```

This commit also adds documentation for the `CommitId` and `ChangeId` types
defined using the `id_type!` macro.
2024-02-27 10:37:05 -05:00
Yuya Nishihara
ef9d22887c tests: disable gpg unknown_key() test on Windows as well
Follows up 7552f939c6 "tests: disable most gpg integration tests on Windows."
I couldn't find this test failing in a few samples before, but it does now.
2024-02-27 00:55:06 +09:00
Martin von Zweigbergk
1cbf2b4acf rewrite: allow working-copy to be abandoned
This removes the special handling of the working-copy commit. By
recording when an empty/emptied commit was abanoned, we rebase
descendants correctly and create a new empty working-copy commit on
top.
2024-02-25 16:39:05 -08:00
Martin von Zweigbergk
3bc3a63411 rewrite: move decision about abandoned commit into update_references() 2024-02-25 16:39:05 -08:00
Yuya Nishihara
7552f939c6 tests: disable most gpg integration tests on Windows
These tests often stuck on Windows CI for unknown reasons. Let's mark them
ignored for the moment. The unknown_key test is allowed because it somehow
appears to pass.

https://github.com/martinvonz/jj/actions/runs/8009950119/job/21879789008?pr=3123#step:7:1487

#3140
2024-02-25 17:07:05 +09:00
Yuya Nishihara
e588a9babc backend: allow cheap copy of MillisSinceEpoch(i64)
It's unlikely this type will become uncopyable.
2024-02-25 09:00:56 +09:00
Yuya Nishihara
ebf90384f6 operation: add shorthand for .store_operation().metadata 2024-02-25 09:00:56 +09:00
Yuya Nishihara
a67aa08995 gitignore: make objects chain be more Arc friendly
This partially reverts changes in a9f489ccdf "Switch to ignore crate for
gitignore handling." Since child ignore object no longer needs to access the
root to resolve the prefix path, it's simpler to store a matcher per node.
2024-02-24 15:55:10 +09:00
Yuya Nishihara
febae9f9e8 gitignore: fix prefix handling when chaining .gitignore in sub directory
The prefix is relative to the root, not to the parent .gitignore file.

Fixes #3126
2024-02-24 15:55:10 +09:00
Yuya Nishihara
2f25848883 gitignore: update file ordering test to not use relative path in patterns
With the current implementation, the file3 pattern is set to the prefix
"foo/foo/bar". I don't know if (unrooted) "baz" prefixed with "foo/foo/bar"
should match "foo/bar/baz", but apparently it is. Anyway, that wouldn't be
the case in practice because adjacent .gitignore files shouldn't be loaded.
2024-02-24 15:55:10 +09:00
Yuya Nishihara
073310547c operation: make Operation object cheaply clonable
We do clone Operation object in several places, and I'm going to add one more
.clone() in the templater. Since the underlying metadata has many fields, I
think it's better to wrap it with Arc just like a Commit object.
2024-02-23 10:13:25 +09:00
Yuya Nishihara
62f0cb8c3f cli: change default log revset to not include all tagged heads
The default immutable_heads() includes tags(), which makes sense, but computing
heads(tags()) can be expensive because the tags() set is usually sparse. For
example, "jj bench revset 'heads(tags())'" took 157ms in my linux stable
mirror. We can of course optimize the heads evaluation by using bit set or
segmented index, but the query includes many historical heads if the repository
has per-release branches, which are uninteresting anyway. So, this patch
replaces heads(immutable_heads()) with trunk().

The reason we include heads(immutable_heads()) is to mitigate the following
problem. Suppose trunk() is the branch to be based off, I think using trunk()
here is pretty good.

```
A   B
*---*----* trunk() ⊆ immutable_heads()
     \
      * C
```
https://github.com/martinvonz/jj/pull/2247#discussion_r1335078879
2024-02-23 00:25:58 +09:00
Yuya Nishihara
f21c078249 revset: ad-hoc optimization for range queries containing unwanted wanted heads
In my linux stable mirror, this makes the default log revset evaluation super
fast. immutable_heads(), if configured properly, includes many historical
branch heads which are also the visible heads.

revsets/immutable_heads()..
---------------------------
0     12.27     117.1±0.77m
3      1.00       9.5±0.08m
2024-02-22 23:26:29 +09:00
Yuya Nishihara
f71f065b17 revset: rename InternalRevset::iter() to ::entries() 2024-02-22 23:26:29 +09:00
Yuya Nishihara
1572c251ef revset: add positions() iterator to InternalRevset
I just wanted to clean up the callers, but this might also be marginally
faster.
2024-02-22 23:26:29 +09:00
Yuya Nishihara
33c7e18ac8 revset: flip ordering of generic combination iterators
As a general-purpose iterator combinator, ascending order makes more sense.
2024-02-22 23:26:29 +09:00
Yuya Nishihara
22933563e8 revset: extract generic combination iterators
I'm going to add pre-filtering to the 'roots..heads' evaluation path, and
difference_by() will be used there to calculate 'heads ~ roots'.

Union and intersection iterators are slightly changed so that all iterators
prioritize iter1's item.
2024-02-22 23:26:29 +09:00
Julien Vincent
f97e929cbf sign: Skip gpg tests if gpg is not installed
This adds a guard to the gpg signing tests which will skip the test if
`gpg` is not installed on the system.

This is done in order to avoid requiring all collaborators to have setup
all the tools on their local machines that are required to test commit
signing.
2024-02-21 13:22:53 +00:00
Yuya Nishihara
9f05aa8c46 tests: fix fun typo "singing" -> "signing" 2024-02-21 22:04:41 +09:00
Yuya Nishihara
e3d2ff2b75 signing: change default gpg program, add --keyid-format option accordingly
This is the default of Git, and Debian sid doesn't install the gpg2 symlink
by default.

https://github.com/git/git/blob/v2.43.2/gpg-interface.c#L92
https://github.com/martinvonz/jj/pull/3007#discussion_r1496877808
https://packages.debian.org/bookworm/gnupg2
2024-02-21 22:04:41 +09:00
Austin Seipp
6c31bab0d3 fsmonitor: allow core.fsmonitor = "none" to disable
When doing things like testing snapshot performance differences,
this allows you to turn off the monitor, no matter what the enabled
user or repository configuration has, e.g.

    jj st --config-toml='core.fsmonitor="none"'

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2024-02-20 20:19:47 -06:00
Evan Mesterhazy
79518eafce Output better error messages when deriving ContentHash for an enum fails
Consider this code:
```
struct NoContentHash {}

#[derive(ContentHash)]
enum Hashable {
    NoCanHash(NoContentHash),
    Empty,
}
```

Before this commit, it generates an error like this:
```
error[E0277]: the trait bound `NoContentHash: ContentHash` is not satisfied
   --> lib/src/content_hash.rs:150:10
    |
150 | #[derive(ContentHash)]
    |          ^^^^^^^^^^^ the trait `ContentHash` is not implemented for `NoContentHash`
151 | enum Hashable {
152 |     NoCanHash(NoContentHash),
    |     --------- required by a bound introduced by this call
    |
    = help: the following other types implement trait `ContentHash`:
              bool
              i32
              i64
              u8
              u32
              u64
              std::collections::HashMap<K, V>
              BTreeMap<K, V>
            and 35 others

For more information about this error, try `rustc --explain E0277`.
```

After this commit, it generates a better error message:
```
error[E0277]: the trait bound `NoContentHash: ContentHash` is not satisfied
   --> lib/src/content_hash.rs:152:15
    |
152 |     NoCanHash(NoContentHash),
    |               ^^^^^^^^^^^^^ the trait `ContentHash` is not implemented for `NoContentHash`
    |
    = help: the following other types implement trait `ContentHash`:
              bool
              i32
              i64
              u8
              u32
              u64
              std::collections::HashMap<K, V>
              BTreeMap<K, V>
            and 35 others

For more information about this error, try `rustc --explain E0277`.
error: could not compile `jj-lib` (lib) due to 1 previous error
```

It also works for enum variants with named fields:
```
error[E0277]: the trait bound `NoContentHash: ContentHash` is not satisfied
   --> lib/src/content_hash.rs:152:23
    |
152 |     NoCanHash { named: NoContentHash },
    |                       ^^^^^^^^^^^^^ the trait `ContentHash` is not implemented for `NoContentHash`
    |
    = help: the following other types implement trait `ContentHash`:
              bool
              i32
              i64
              u8
              u32
              u64
              std::collections::HashMap<K, V>
              BTreeMap<K, V>
            and 35 others

For more information about this error, try `rustc --explain E0277`.
```
2024-02-20 16:29:25 -05:00
Evan Mesterhazy
e8f324ffde Replace uses of content_hash! with #[derive(ContentHash)]
This is a pure refactor with no behavior changes.

#3054
2024-02-20 14:18:13 -05:00
Evan Mesterhazy
966a5505e2 Add support for deriving ContentHash for Enums
Here's an example of what the derived output looks like for an enum:

```rust
pub enum TreeValue {
    File { id: FileId, executable: bool },
    Symlink(SymlinkId),
    Tree(TreeId),
    GitSubmodule(CommitId),
    Conflict(ConflictId),
}
#[automatically_derived]
impl ::jj_lib::content_hash::ContentHash for TreeValue {
    fn hash(&self, state: &mut impl digest::Update) {
        match self {
            Self::File { id, executable } => {
                state.update(&0u32.to_le_bytes());
                ::jj_lib::content_hash::ContentHash::hash(id, state);
                ::jj_lib::content_hash::ContentHash::hash(executable, state);
            }
            Self::Symlink(field_0) => {
                state.update(&1u32.to_le_bytes());
                ::jj_lib::content_hash::ContentHash::hash(field_0, state);
            }
            Self::Tree(field_0) => {
                state.update(&2u32.to_le_bytes());
                ::jj_lib::content_hash::ContentHash::hash(field_0, state);
            }
            Self::GitSubmodule(field_0) => {
                state.update(&3u32.to_le_bytes());
                ::jj_lib::content_hash::ContentHash::hash(field_0, state);
            }
            Self::Conflict(field_0) => {
                state.update(&4u32.to_le_bytes());
                ::jj_lib::content_hash::ContentHash::hash(field_0, state);
            }
        }
    }
}
```


#3054
2024-02-20 12:59:35 -05:00
Evan Mesterhazy
8e1a6c708f Add support for generics to #[derive(ContentHash)]
#3054
2024-02-20 12:48:25 -05:00
Daehyeok Mun
a9f489ccdf Switch to ignore crate for gitignore handling.
Co-authored-by: Waleed Khan <me@waleedkhan.name>
2024-02-20 09:12:46 -08:00
Evan Mesterhazy
965d6ce4e4 Implement a procedural macro to derive the ContentHash trait for structs
This is a no-op in terms of function, but provides a nicer way to derive the
ContentHash trait for structs using the `#[derive(ContentHash)]` syntax used
for other traits such as `Debug`.

This commit only adds the macro. A subsequent commit will replace uses of
`content_hash!{}` with `#[derive(ContentHash)]`.

The new macro generates nice error messages, just like the old macro:

```
error[E0277]: the trait bound `NotImplemented: content_hash::ContentHash` is not satisfied
   --> lib/src/content_hash.rs:265:16
    |
265 |             z: NotImplemented,
    |                ^^^^^^^^^^^^^^ the trait `content_hash::ContentHash` is not implemented for `NotImplemented`
    |
    = help: the following other types implement trait `content_hash::ContentHash`:
              bool
              i32
              i64
              u8
              u32
              u64
              std::collections::HashMap<K, V>
              BTreeMap<K, V>
            and 38 others
```

This commit does two things to make proc macros re-exported by jj_lib useable
by deps:

1. jj_lib needs to be able refer to itself as `jj_lib` which it does
   by adding an `extern crate self as jj_lib` declaration.

2. jj_lib::content_hash needs to re-export the `digest::Update` type so that
   users of jj_lib can use the `#[derive(ContentHash)]` proc macro without
   directly depending on the digest crate. This is done by re-exporting it
   as `DigestUpdate`.


#3054
2024-02-20 11:29:05 -05:00
Ilya Grigoriev
106483ad6a clippy: run nightly cargo clippy --fix 2024-02-19 23:38:33 -08:00
Martin von Zweigbergk
11c67cf979 op_store: add metadata flag for ops representing working-copy snapshot
It should be useful at least in the presentation layer to know which
operations correspond to working-copy snapshots. They might be
rendered differently in the graph, for example. Or maybe an undo
command wants to warn if you just undid a snapshot operation. This
patch just introduces a field in the metadata to store the
information.
2024-02-19 22:44:38 -08:00
Julien Vincent
23e5fba737 sign: Add SSH backend tests 2024-02-20 00:02:08 +00:00
Julien Vincent
5e24677301 sign: Implement SSH signing backend 2024-02-20 00:02:08 +00:00
Julien Vincent
7c11a61c23 sign: GPG backend tests 2024-02-20 00:02:08 +00:00
Anton Bulakh
0efaef2da9 sign: Implement GPG signing backend
Now it is actually possible to set GPG as the main backend and have jj
"preserving" signatures on rewrites. Just no way to make signatures yet
2024-02-20 00:02:08 +00:00
Martin von Zweigbergk
3f1d75f518 rewrite: default to not simplifying ancestor merges
This means auto-rebase will no longer simplify ancestor merges.
2024-02-19 14:20:18 -08:00
Martin von Zweigbergk
a9d0300b11 rewrite: make simplification of ancestor merges optional
I think the conclusion from #2600 is that at least auto-rebasing
should not simplify merge commits that merge a commit with its
ancestor. Let's start by adding an option for that in the library.
2024-02-19 14:20:18 -08:00
Yuya Nishihara
0c0eb37f2e index: don't store commit ids in sorted lookup table to save disk space
This reduces the index file size. In my linux mirror repo containing 1591524
commits, the initial index file shrank from 122MB to 92MB. In theory, this
makes commit id lookup slow because of additional indirection and cache miss,
but I don't see significant difference. In mid-size repo, this is actually a
bit faster thanks to smaller index reads.

Alternatively, the commit id field could be removed from the CommitGraphEntry,
but doing that would introduce indirect lookup there, and the index disk size
isn't as small as this change.

- jj-0 baseline                         122MB
- jj-1 shrink CommitLookupEntry (this)   92MB
- jj-3 shrink CommitGraphEntry           98MB

Mid-size repo, "log" with default template
```
% hyperfine --sort command --warmup 3 --runs 20 -L bin jj-0,jj-1,jj-2,jj-3 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/linux debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     177.7 ms ±  12.9 ms    [User: 96.3 ms, System: 81.5 ms]
  Range (min … max):   156.8 ms … 191.2 ms    20 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     169.8 ms ±  13.8 ms    [User: 93.3 ms, System: 76.6 ms]
  Range (min … max):   151.1 ms … 191.5 ms    20 runs

Benchmark 4: target/release-with-debug/jj-3 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     170.3 ms ±  13.4 ms    [User: 90.1 ms, System: 79.7 ms]
  Range (min … max):   154.8 ms … 186.2 ms    20 runs

Relative speed comparison
        1.05 ±  0.11  target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
        1.00          target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
        1.00 ±  0.11  target/release-with-debug/jj-3 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
```

Small repo, "log" thousands of commits with -T"commit_id.shortest()"
```
% hyperfine --sort command --warmup 3 --runs 100 -L bin jj-0,jj-1,jj-2,jj-3 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/git debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     179.3 ms ±  12.8 ms    [User: 149.7 ms, System: 29.6 ms]
  Range (min … max):   155.2 ms … 191.0 ms    100 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     179.1 ms ±  13.7 ms    [User: 148.5 ms, System: 30.5 ms]
  Range (min … max):   157.2 ms … 196.7 ms    100 runs

Benchmark 4: target/release-with-debug/jj-3 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     178.2 ms ±  13.6 ms    [User: 148.7 ms, System: 29.6 ms]
  Range (min … max):   156.5 ms … 191.7 ms    100 runs

Relative speed comparison
        1.01 ±  0.11  target/release-with-debug/jj-0 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
        1.01 ±  0.11  target/release-with-debug/jj-1 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
        1.01 ±  0.11  target/release-with-debug/jj-3 -R ~/mirrors/git --ignore-working-copy log -r.. -l5000 -T'commit_id.shortest()' --config-toml='revsets.short-prefixes=""'
```
2024-02-19 11:36:45 +09:00
Vladimir Petrzhikovskii
06d67f02d8 cli: list new remote branches during git fetch 2024-02-18 17:36:01 +01:00
Yuya Nishihara
a1b16c5583 index: build reachable change ids set lazily
Instead of abstracting RevWalk over borrowed/Arc-ed index types, I decided to
implement bitset-based ancestor traversal. It's simpler and probably faster so
long as the set isn't sparse.

"jj log" without working copy snapshot:
```
% hyperfine --sort command --warmup 3 --runs 20 -L bin jj-0,jj-1,jj-2 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/linux debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/linux \
   --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     271.3 ms ±   9.9 ms    [User: 183.8 ms, System: 87.7 ms]
  Range (min … max):   250.5 ms … 282.7 ms    20 runs

Benchmark 3: target/release-with-debug/jj-2 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     177.5 ms ±  12.6 ms    [User: 94.6 ms, System: 82.9 ms]
  Range (min … max):   154.4 ms … 188.7 ms    20 runs

Relative speed comparison
        1.53 ±  0.12  target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
        1.00          target/release-with-debug/jj-2 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
```

"jj status" with working copy snapshot (watchman enabled):
```
% hyperfine --sort command --warmup 3 --runs 20 -L bin jj-0,jj-1,jj-2 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/linux debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/linux \
   status --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     318.6 ms ±  12.6 ms    [User: 219.1 ms, System: 94.1 ms]
  Range (min … max):   294.2 ms … 333.0 ms    20 runs

Benchmark 3: target/release-with-debug/jj-2 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     214.7 ms ±  15.0 ms    [User: 117.4 ms, System: 96.1 ms]
  Range (min … max):   198.4 ms … 243.3 ms    20 runs

Relative speed comparison
        1.48 ±  0.12  target/release-with-debug/jj-1 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
        1.00          target/release-with-debug/jj-2 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
```
2024-02-19 00:54:43 +09:00
Yuya Nishihara
adcb01ef95 index: move RevWalk tests to inner module
The main tests module is getting bigger, and these tests are very specific
to the RevWalk* implementations.
2024-02-19 00:54:43 +09:00
Yuya Nishihara
924a5fc842 index: inline entry size calculation
There aren't many callers now, and using self.commit_id_length might help
compiler remove redundant bounds checking in CommitLookupEntry.
2024-02-19 00:47:46 +09:00
Yuya Nishihara
d5c75da4f5 index: precompute base data offsets
These offsets are getting messier, so let's calculate them in one place. This
will probably help compiler optimization.
2024-02-19 00:47:46 +09:00