The current docs for conflict markers start out by introducing Git
"diff3" conflict markers, and then discussing how Jujutsu's conflict
markers are different from Git's. I don't think this is the best way to
explain it, because it requires the reader to first understand Git's
conflict markers before they go on to learn Jujutsu's conflict markers.
Instead, I think it's better to explain the conflict markers from
scratch with a more detailed example so that we don't assume any
particular knowledge of Git.
This structure also works better with the new config option, since we
can talk about the default option first, and then go on to explain
alternatives later.
Adds a new "git" conflict marker style option. This option matches Git's
"diff3" conflict style, allowing these conflicts to be parsed by some
external tools that don't support JJ-style conflicts. If a conflict has
more than 2 sides, then it falls back to the similar "snapshot" conflict
marker style.
The conflict parsing code now supports parsing Git-style conflict
markers in addition to the normal JJ-style conflict markers, regardless
of the conflict marker style setting. This has the benefit of allowing
the user to switch the conflict marker style while they already have
conflicts checked out, and their old conflicts will still be parsed
correctly.
Example of "git" conflict markers:
```
<<<<<<< Side #1 (Conflict 1 of 1)
fn example(word: String) {
println!("word is {word}");
||||||| Base
fn example(w: String) {
println!("word is {w}");
=======
fn example(w: &str) {
println!("word is {w}");
>>>>>>> Side #2 (Conflict 1 of 1 ends)
}
```
Adds a new "snapshot" conflict marker style which returns a series of
snapshots, similar to Git's "diff3" conflict style. The "snapshot"
option uses a subset of the conflict hunk headers as the "diff" option
(it just doesn't use "%%%%%%%"), meaning that the two options are
trivially compatible with each other (i.e. a file materialized with
"snapshot" can be parsed with "diff" and vice versa).
Example of "snapshot" conflict markers:
```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn example(word: String) {
println!("word is {word}");
------- Contents of base
fn example(w: String) {
println!("word is {w}");
+++++++ Contents of side #2
fn example(w: &str) {
println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
Adds a new "ui.conflict-marker-style" config option. The "diff" option
is the default jj-style conflict markers with a snapshot and a series of
diffs to apply to the snapshot. New conflict marker style options will
be added in later commits.
The majority of the changes in this commit are from passing the config
option down to the code that materializes the conflicts.
Example of "diff" conflict markers:
```
<<<<<<< Conflict 1 of 1
+++++++ Contents of side #1
fn example(word: String) {
println!("word is {word}");
%%%%%%% Changes from base to side #2
-fn example(w: String) {
+fn example(w: &str) {
println!("word is {w}");
>>>>>>> Conflict 1 of 1 ends
}
```
Since commit e716fe7, the function no longer returns a tree id. That
commit updated the function documentation to match the new behavior,
but then the old documentation was restored in commit ef83f2b, perhaps
by a bad merge conflict resolution.
There's a subtle difference in error message, but the conversion function to be
called is the same. The error message now includes "for key <key>", which is
nice.
.get_table() isn't implemented because it isn't cheap to build a HashMap,
and a table of an abstract Value type wouldn't be useful. Maybe we'll
instead provide an iterator of table keys.
.config() is renamed to .raw_config() to break existing callers.
Ui::with_config() is unchanged because I'm not sure if UserSettings should be
constructed earlier. I assume UserSettings will hold an immutable copy of
LayerdConfigs object, whereas Ui has to be initialized before all config layers
get loaded.
I'm planning to rewrite config store layer by leveraging toml_edit instead of
the config crate. It will allow us to merge config overlays in a way that
deprecated keys are resolved within a layer prior to merging, for example.
This patch moves ConfigNamePathBuf to jj-lib where new config API will be
hosted. We'll probably extract LayeredConfigs to this module, but we'll first
need to split environment dependencies from it.
Some editors strip trailing whitespace on save, which breaks any diffs
which have context lines, since the parsing function expects them to
start with a space. There's no visual difference between " \n" and "\n",
so it seems reasonable to accept both.
Currently, conflict markers ending in CRLF line endings aren't allowed.
I don't see any reason why we should reject them, since some
editors/tools might produce CRLF automatically on Windows when saving
files, which would break the conflicts otherwise.
Use `jj new && jj undo` instead of `jj new @-` at the end of converting to a
co-located repository, because the latter "stashes" newly added working copy
changes into a sibling commit.
See also: https://github.com/martinvonz/jj/discussions/4945
Signed-off-by: Tim Janik <timj@gnu.org>
The previous iteration of `jj simplify-parents` would only reparent the
commits in the target set in the `MutableRepo::transform_descendants`
callback. The subsequent `MutableRepo::rebase_descendants` call invoked
when the transaction is committed would then rebase all descendants of
the target set, which includes the commits in the target set again.
This commit updates the `MutableRepo::transform_descendants` callback to
perform rebasing of all descendants within the callback. All descendants
of the target set will only be rebased at most once.
Because the output of diff.hunks() is a list of [&BStr]s, a Merge object
reconstructed from a diff hunk will be Merge<&BStr>. I'm not pretty sure if
we'll implement conflict diffs in that way, but this change should be harmless
anyway.
I believe this was an oversight. "jj duplicate" should duplicate commits (=
patches), not trees.
This patch adds a separate test file because test_rewrite.rs is pretty big, and
we'll probably want to migrate CLI tests to jj-lib.
Our docs are built with MkDocs, which requires Python and several deps.
Previously those deps were managed with Poetry, which is also written in Python.
This commit replaces Poetry with `uv`, a Rust-based Python
project/package manager, and thus removes several steps from the docs
build process.
Before:
<install Python>
<install pipx>
pipx install poetry
poetry install
poetry run -- mkdocs serve
After:
<install uv>
uv run mkdocs serve
The working-copy revision is usually the latest commit, but it's not always
true. This patch ensures that the wc branch is emitted first so the graph node
order is less dependent on rewrites.
This isn't always fast because it increases the chance of cache miss, but in
practice, it makes "jj file annotate" faster. It's still slower than
"git blame", though.
Maybe we should also change the hash function.
```
group new old
----- --- ---
bench_diff_git_git_read_tree_c 1.00 45.2±0.38µs 1.29 58.4±0.32µs
bench_diff_lines/modified/10k 1.00 32.7±0.24ms 1.05 34.4±0.17ms
bench_diff_lines/modified/1k 1.00 2.9±0.00ms 1.06 3.1±0.01ms
bench_diff_lines/reversed/10k 1.00 22.7±0.18ms 1.02 23.2±0.29ms
bench_diff_lines/reversed/1k 1.00 439.0±9.46µs 1.19 523.9±6.05µs
bench_diff_lines/unchanged/10k 1.00 2.9±0.06ms 1.20 3.5±0.02ms
bench_diff_lines/unchanged/1k 1.00 240.8±1.03µs 1.30 312.1±1.05µs
```
```
% hyperfine --sort command --warmup 3 --runs 10 -L bin jj-0,jj-1 \
'target/release-with-debug/{bin} --ignore-working-copy file annotate lib/src/revset.rs'
Benchmark 1: target/release-with-debug/jj-0 ..
Time (mean ± σ): 1.604 s ± 0.259 s [User: 1.543 s, System: 0.057 s]
Range (min … max): 1.348 s … 1.917 s 10 runs
Benchmark 2: target/release-with-debug/jj-1 ..
Time (mean ± σ): 1.183 s ± 0.026 s [User: 1.118 s, System: 0.062 s]
Range (min … max): 1.155 s … 1.237 s 10 runs
```