Commit graph

848 commits

Author SHA1 Message Date
Martin von Zweigbergk
5e8d7f8c6f rewrite: update references after rewriting all commits 2024-03-25 23:00:44 -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
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
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
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
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
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
f5eb172769 tests: remove last use of walk_revs() from integration tests 2024-03-08 10:07:40 +09: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
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
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
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
ebf90384f6 operation: add shorthand for .store_operation().metadata 2024-02-25 09:00:56 +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
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
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
7c11a61c23 sign: GPG backend tests 2024-02-20 00:02:08 +00: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
3c7aa75b9b index: switch to persistent change id index
The shortest change id prefix will become a few digits longer, but I think
that's acceptable. Entries included in the "revsets.short-prefixes" set are
unaffected.

The reachable set is calculated eagerly, but this is still faster as we no
longer need to sort the reachable entries by change id. The lazy version will
save another ~100ms in mid-size repos.

"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 1: target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     353.6 ms ±  11.9 ms    [User: 266.7 ms, System: 87.0 ms]
  Range (min … max):   329.0 ms … 365.6 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 ± σ):     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

Relative speed comparison
        1.99 ±  0.16  target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
        1.53 ±  0.12  target/release-with-debug/jj-1 -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 1: target/release-with-debug/jj-0 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     396.6 ms ±  10.1 ms    [User: 300.7 ms, System: 94.0 ms]
  Range (min … max):   373.6 ms … 408.0 ms    20 runs

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

Relative speed comparison
        1.85 ±  0.14  target/release-with-debug/jj-0 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
        1.48 ±  0.12  target/release-with-debug/jj-1 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
```
2024-02-18 09:44:57 +09:00
Yuya Nishihara
8cdf6d752c index: move change ids to sstable, build change-id-to-pos lookup table
This basically means that the change ids are interned. We'll implement binary
search over the sorted change ids table. The table could be sorted differently
for better cache locality, but it is in lexicographical order for simplicity.
With my testing, the cost of the id lookup isn't dominant.

Unlike the parent entries, the size of the per-id overflow items isn't saved.
That's s because the number of the same-change-id commits is either 1 or many.
It doesn't make sense to allocate 8 bytes for each change id. Instead, we'll
pay extra indirection cost to determine the size.
2024-02-18 09:44:57 +09:00
Thomas Castiglione
aaa5d6bc4f working_copy: add Send supertrait
If WorkingCopy: Send, then Workspace is Send, which is useful for long-running
servers. All existing impls are Send already, so this is just a marker.
2024-02-17 15:13:25 +08:00
Yuya Nishihara
5eea88d26a tests: fix concurrent git read/write test to retry on ref lock contention
Apparently, gix has 100ms timeout. Since this test tries to create contended
situation, it's possible that the ref lock can't be acquired. I've added
upper bound to the retry loop at b37293fa68 "tests: add upper bound to
test_concurrent_read_write_commit() loop", so ignoring arbitrary errors
should be okay.

The problem can be reproduced on my Linux machine by inserting 10ms sleep() to
gix and increasing the concurrency.

Fixes #3069
2024-02-17 15:09:27 +09:00
Evan Mesterhazy
e1fd402d39 Fix the ContentHash implementations for std::Option, MergedTreeId, and RemoteRefState
The `ContentHash` documentation specifies that implementations for enums should
hash the ordinal number of the variant contained in the enum as a 32-bit
little-endian number and then hash the contents of the variant, if any.

The current implementations for `std::Option`, `MergedTreeId`, and
`RemoteRefState` are non-conformant since they hash the ordinal number as a u8
with platform specific endianness.


Fixes #3051
2024-02-16 09:27:32 -05:00
Yuya Nishihara
e2c8a8fabd index: fix change id resolution test to not depend on deterministic order
Since IdIndex sorts the entries by using .sort_unstable_by_key(), the order of
the same-key elements is undefined. Perhaps, it's stable for short arrays, and
the test passes because of that.
2024-02-14 23:22:23 +09:00
Yuya Nishihara
2905a70b18 doc, tests: drop use of deprecated revset dag range operator 2024-02-14 10:04:56 +09:00
Yuya Nishihara
b0e8e2a1af index: move segment files to sub directory, add version number
I'm going to introduce breaking changes in index format. Some of them will
affect the file size, so version number or signature won't be needed. However,
I think it's safer to detect the format change as early as possible.

I have no idea if embedded version number is the best way. Because segment
files are looked up through the operation links, the version number could be
stored there and/or the "segments" directory could be versioned. If we want to
support multiple format versions and clients, it might be better to split the
tables into data chunks (e.g. graph entries, commit id table, change id table),
and add per-chunk version/type tag. I choose the per-file version just because
it's simple and would be non-controversial.

As I'm going to introduce format change pretty soon, this patch doesn't
implement data migration. The existing index files will be deleted and new
files will be created from scratch.

Planned index format changes include:
 1. remove unused "flags" field
 2. inline commit parents up to two
 3. add sorted change ids table
2024-02-12 19:38:36 +09:00
Ilya Grigoriev
a9c3af8153 test_local_working_copy: use std::fs:write instead of OpenOptions 2024-02-10 16:06:28 -08:00
Ilya Grigoriev
b2e37d448b clippy: add truncate option as suggested by clippy
In the next commit, I replace the whole thing with
std::fs::write, but I'll leave this here in case
the next commit is somhow incorrect
2024-02-10 16:06:28 -08:00
Ilya Grigoriev
a88c06068e clippy: new nightly fixes
For some reason, clippy also suggested surrounding
`self.value` with parentheses. Not sure whether
that's a clippy bug.

Cc: https://github.com/rust-lang/rust-clippy/issues/12268
2024-02-10 16:06:28 -08:00
dependabot[bot]
6d1faf9b03 Update strsim (changes tests), clap, clap_complete
This is #3002 with tests rerun to account for changes
to `strsim`, as @thoughtpolice noticed in
https://github.com/martinvonz/jj/pull/3002#issuecomment-1936763101

The string similarity changes include an example that
seems better and one that seems worse. Decreasing
the threshold definitely makes things worse.
2024-02-10 00:01:47 -08:00
Austin Seipp
5b517b542e rust: bump MSRV to 1.76.0
Signed-off-by: Austin Seipp <aseipp@pobox.com>
2024-02-09 15:48:01 -06:00
Martin von Zweigbergk
6c1aeff7a9 working copy: materialize symlinks on Windows as regular files
I was a bit surprised to learn (or be reminded?) that checking out
symlinks on Windows leads to a panic. This patch fixes the crash by
materializing symlinks from the repo as regular files. It also updates
the snapshotting code so we preserve the symlink-ness of a path. The
user can update the symlink in the repo by updating the regular file
in the working copy. This seems to match Git's behavior on Windows
when symlinks are disabled.
2024-02-09 09:20:24 -08:00
jyn
d66fcf2ca0 compile integration tests as a single binary
this greatly speeds up the time to run all tests, at the cost of slightly larger recompile times for individual tests.

this unfortunately adds the requirement that all tests are listed in `runner.rs` for the crate.
to avoid forgetting, i've added a new test that ensures the directory is in sync with the file.

 ## benchmarks

before this change, recompiling all tests took 32-50 seconds and running a single test took 3.5 seconds:

```
; hyperfine 'touch lib/src/lib.rs && cargo t --test test_working_copy'
  Time (mean ± σ):      3.543 s ±  0.168 s    [User: 2.597 s, System: 1.262 s]
  Range (min … max):    3.400 s …  3.847 s    10 runs
```

after this change, recompiling all tests take 4 seconds:
```
;  hyperfine 'touch lib/src/lib.rs ; cargo t --test runner --no-run'
  Time (mean ± σ):      4.055 s ±  0.123 s    [User: 3.591 s, System: 1.593 s]
  Range (min … max):    3.804 s …  4.159 s    10 runs
```
and running a single test takes about the same:
```
; hyperfine 'touch lib/src/lib.rs && cargo t --test runner -- test_working_copy'
  Time (mean ± σ):      4.129 s ±  0.120 s    [User: 3.636 s, System: 1.593 s]
  Range (min … max):    3.933 s …  4.346 s    10 runs
```

about 1.4 seconds of that is the time for the runner, of which .4 is the time for the linker. so
there may be room for further improving the times.
2024-02-06 18:19:41 -08:00
Martin von Zweigbergk
b343289238 working_copy: make reset() take a commit instead of a tree
Our virtual file system at Google (CitC) would like to know the commit
so it can scan backwards and find the closest mainline tree based on
it. Since we always record an operation id (which resolves to a
working-copy commit) when we write the working-copy state, it doesn't
seem like a restriction to require a commit.
2024-02-06 12:41:09 -08:00
Ilya Grigoriev
d439de073d rewrite.rs: revert commits cfcc7c5e and becbc889
This mostly reverts https://github.com/martinvonz/jj/pull/2901 as well as its
fixup https://github.com/martinvonz/jj/pull/2903. The related bug is reopened,
see https://github.com/martinvonz/jj/issues/2869#issuecomment-1920367932.

The problem is that while the fix did fix #2869 in most cases, it did
reintroduce the more severe bug https://github.com/martinvonz/jj/issues/2760
in one case, if the working copy is the commit being rebased.

For example, suppose you have the tree

```
root -> A -> B -> @ (empty) -> C
```

### Before this commit

#### Case 1

`jj rebase -s B -d root --skip-empty` would work perfectly before this
commit, resulting in

```
root -> A
  \-------B -> C
           \- @ (new, empty)
```

#### Case 2

Unfortunately, if you run `jj rebase -s @ -d A --skip-empty`, you'd have the
following result (before this commit), which shows the reintroduction of #2760:

```
root -> A @ -> C
         \-- B
```

with the working copy at `A`. The reason for this is explained in
https://github.com/martinvonz/jj/pull/2901#issuecomment-1920043560.

### After this commit

After this commit, both case 1 and case 2 will be wrong in the sense of #2869,
but it will no longer exhibit the worse bug #2760 in the second case.

Case 1 would result in:

```
root -> A
  \-------B -> @ (empty) -> C
```

Case 2 would result in:

```
root -> A -> @ -> C
         \-- B
```

with the working copy remaining a descendant of A
2024-02-03 15:56:44 -08:00
Ilya Grigoriev
cfcc7c5e34 test_rewrite: Fixup test comment after becbc88 2024-01-30 23:43:05 -08:00
Ilya Grigoriev
becbc88915 rewrite.rs: fix working copy position after jj rebase --abandon-empty
Fixes #2869
2024-01-30 22:53:55 -08:00
Yuya Nishihara
3d0b3d57d8 git_backend: on gc(), remove unreachable no-gc refs and compact them
With my jj repo, the number of jj/keep refs went down from 87887 to 27733.
The .git directory size is halved, but we'll need to clean up extra and index
files to save disk space. "git gc --prune=now && jj debug reindex" passed, so
the repo wouldn't be corrupted.

#12
2024-01-27 10:18:11 +09:00
Yuya Nishihara
fc114ef217 git: extract Git HEAD handling bits from import_some_refs()
I'm going to make WorkspaceCommandHelper::maybe_snapshot() snapshot the working
copy before importing refs. git::import_some_refs() can rebase the working copy
branch and therefore @ can be moved. git::import_head() doesn't, and it should
be invoked before snapshotting.

git::import_head() is inserted to some of the git:import_refs() callers where
HEAD seems to matter. I feel it's a bit odd that the HEAD ref is imported to
non-colocated repo, but "jj init --git-repo" relies on that, and I think the
existence of HEAD@git is harmless. It's merely a ref to the revision checked
out somewhere else.
2024-01-27 00:01:59 +09:00
Daniel Ploch
cb889f0b45 workspace: combine working copy functions into a trait 2024-01-25 11:46:07 -08:00
Yuya Nishihara
5a7d8ac596 working_copy: don't follow symlinks when visiting files in gitignored directory
Fixes #2878
2024-01-24 16:38:48 +09:00
Yuya Nishihara
d0d4496258 tests: add executable files and symlinks to gitignored directory test 2024-01-24 16:38:48 +09:00
Martin von Zweigbergk
502150b2f4 conflicts: test materialization with with negative snapshots
We didn't have any tests with negative snapshots (after a `-------`
line). I initially thought we couldn't produce such conflict markers
anymore. I'm not sure we want to render conflicts like the one in the
test like this. I don't think I intended for `add_index` in the code
to be able to be two steps ahead of the remove. Maybe we should
rewrite the algorithm to not do that and thus never produce negative
snapshots.
2024-01-23 07:18:54 -08:00
Ilya Grigoriev
d168fd2b09 test_rebase_abandoning_empty: add children of an empty @ to the test case
This demonstrates the minor bug discussed in
https://github.com/martinvonz/jj/pull/2766#discussion_r1442365389
AKA https://github.com/martinvonz/jj/issues/2869.

It's also interesting whether changing the definition of "discardable" commit
would affect this test, see
https://github.com/martinvonz/jj/issues/2859#issuecomment-1903275884

(I think it won't, but still)
2024-01-22 18:36:49 -08:00
Yuya Nishihara
fb3e006a45 op_store: add special case for root id resolution 2024-01-16 21:46:54 +09:00
Yuya Nishihara
660806ffed tests: set up unparented operations for id prefix tests
Otherwise we can't easily pick i to create operation id starting with "0".
2024-01-16 21:46:54 +09:00