If the parent tree contains conflicts, we want the index to also contain
a conflict to ensure that the use can't accidentally commit conflict
markers using `git commit`. Since we can't represent conflicts with more
than 2 sides in the Git index, we need to add a dummy conflict in this
case. We use ".jj-do-not-resolve-this-conflict" as the dummy conflict to
indicate to the user that they should not attempt to resolve this
conflict using Git.
Instead of setting the index to match the tree of HEAD, we now set the
index to the merged parent tree of the working copy commit. This means
that if you edit a merge commit, it will make the Git index look like it
would in the middle of a `git merge` operation (with all of the
successfully-merged files staged in the index).
If there are any 2-sided conflicts in the merged parent tree, then they
will be added to the index as conflicts. Since Git doesn't support
conflicts with more than 2 sides, many-sided conflicts are staged as the
first side of the conflict. The following commit will improve this.
This will give us more fine-grained control over what files we put in
the index, allowing us to create conflicted index states. We also still
need to use git2 to clean up the merge/rebase state, since gix doesn't
have any function for this currently.
These tests should still pass after we switch to gix for resetting the
index, so we need to make sure they don't rely on the cached index from
the `git2::Repository` instance.
Disclaimer: this is the work of @necauqua and @julienvincent (see
#3141). I simply materialized the changes by rebasing them on latest
`main` and making the necessary adjustments to pass CI.
---
I had to fix an issue in `TestSignatureBackend::sign()`.
The following test was failing:
```
---- test_signature_templates::test_signature_templates stdout ----
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Snapshot Summary ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Snapshot: signature_templates
Source: cli/tests/test_signature_templates.rs:28
────────────────────────────────────────────────────────────────────────────────
Expression: stdout
────────────────────────────────────────────────────────────────────────────────
-old snapshot
+new results
────────────┬───────────────────────────────────────────────────────────────────
0 0 │ @ Commit ID: 05ac066d05701071af20e77506a0f2195194cbc9
1 1 │ │ Change ID: qpvuntsmwlqtpsluzzsnyyzlmlwvmlnu
2 2 │ │ Author: Test User <test.user@example.com> (2001-02-03 08:05:07)
3 3 │ │ Committer: Test User <test.user@example.com> (2001-02-03 08:05:07)
4 │-│ Signature: Good test signature
4 │+│ Signature: Bad test signature
5 5 │ │
6 6 │ │ (no description set)
7 7 │ │
8 8 │ ◆ Commit ID: 0000000000000000000000000000000000000000
────────────┴───────────────────────────────────────────────────────────────────
```
Print debugging revealed that the signature was bad, because of a
missing trailing `\n` in `TestSignatureBackend::sign()`.
```diff
diff --git a/lib/src/test_signing_backend.rs b/lib/src/test_signing_backend.rs
index d47fef1086..0ba249e358 100644
--- a/lib/src/test_signing_backend.rs
+++ b/lib/src/test_signing_backend.rs
@@ -59,6 +59,8 @@
let key = (!key.is_empty()).then_some(std::str::from_utf8(key).unwrap().to_owned());
let sig = self.sign(data, key.as_deref())?;
+ dbg!(&std::str::from_utf8(&signature).unwrap());
+ dbg!(&std::str::from_utf8(&sig).unwrap());
if sig == signature {
Ok(Verification::new(
SigStatus::Good,
```
```
[lib/src/test_signing_backend.rs:62:9] &std::str::from_utf8(&signature).unwrap() = \"--- JJ-TEST-SIGNATURE ---\\nKEY: \\n5300977ff3ecda4555bd86d383b070afac7b7459c07f762af918943975394a8261d244629e430c8554258904f16dd9c18d737f8969f2e7d849246db0d93cc004\\n\"
[lib/src/test_signing_backend.rs:63:9] &std::str::from_utf8(&sig).unwrap() = \"--- JJ-TEST-SIGNATURE ---\\nKEY: \\n5300977ff3ecda4555bd86d383b070afac7b7459c07f762af918943975394a8261d244629e430c8554258904f16dd9c18d737f8969f2e7d849246db0d93cc004\"
```
Thankfully, @yuja pointed out that libgit2 appends a trailing newline
(see bfb7613d5d).
Co-authored-by: necauqua <him@necauq.ua>
Co-authored-by: julienvincent <m@julienvincent.io>
We need to make `TestSigningBackend` available for cli tests, as we will
add cli tests for signing related functionality (templates for
displaying commit signatures, `jj sign`) in upcoming commits.
Co-authored-by: julienvincent <m@julienvincent.io>
It's not super important that operation log has a valid user/host name. Let's
allow invalid system configuration. In jj 0.24.0, invalid hostname was panic,
and invalid username was mapped to "Unknown".
Fixes#5231
Using `gix/max-performance` requires `cmake` as a build-time dependency, which could be a significant barrier for contributors (including existing ones, like me, who already work on jj but didn't have `cmake` installed thus far).
This commit switches back to using `gix/max-performance-safe`, which doesn't have the `cmake` dependency, and adds `gix/max-performance` behind the `gix-max-performance` feature for `jj-lib`.
It also adds `gix-max-performance` to the `packaging` feature group, since I'm assuming that packagers will want maximum performance, and are more likely to have `cmake` at hand.
Tested with
```
$ cargo build --workspace
$ cargo build --workspace --features packaging
```
(and the `--features packaging` build failed until I installed `cmake`)
I'm going to remove the settings argument from start_transaction(),
new_commit(), and rewrite_commit(), and these functions will use the settings
passed in to the constructor.
The idea is that ReadonlyRepo/MutableRepo hold UserSettings to accomplish
their operations (such as transaction commit.) Later patches will remove
the "settings" argument from a couple of repo methods, which will greatly
reduce the amount of settings refs we had to pass around.
The current UserSettings is set up for the repo, so we wouldn't need a separate
RepoSettings type.
I think the issue #5144 can be fixed cleanly if UserSettings object is
loaded/resolved per repo/workspace, not per CommandHelper.
This change makes it clear that UserSettings is supposed to be shared
immutably.
This fixes the output of "jj config list --include-overridden --include-defaults
ui.pager" and ".. ui.pager.command". The default ui.pager.* should be marked as
overridden by ui.pager if set in user configuration.
It's nice that "jj config list --include-defaults" can show these default
values.
I just copied the jj-cli directory structure, but it's unlikely we'll add more
config/*.toml files.
Note that infallible version of whoami::username() would return "Unknown" on
error. I just made it error out, but it's also an option to fall back to an
empty string.
ReverseGraphIterator will be inlined. It doesn't make sense the iterator yields
Item = Result<..> whereas all possible errors are confined by constructor.
These paths may be printed, compared with user inputs, or passed to external
programs. It's probably better to avoid unusual "\\?\C:\" paths on Windows.
Fixes#5143
Storing the conflict marker length in the working copy makes conflict
parsing more consistent, and it allows us to parse valid conflict hunks
even if the user left some invalid conflict markers in the file while
resolving the conflicts.
If a file contains lines which look like conflict markers, then we need
to make the real conflict markers longer so that the materialized
conflicts can be parsed unambiguously.
When parsing the conflict, we require that the conflict markers are at
least as long as the materialized conflict markers based on the current
tree. This can lead to some unintuitive edge cases which will be solved
in the next commit.
For instance, if we have a file explaining the differences between
Jujutsu's conflict markers and Git's conflict markers, it could produce
a conflict with long markers like this:
```
<<<<<<<<<<< Conflict 1 of 1
%%%%%%%%%%% Changes from base to side #1
Jujutsu uses different conflict markers than Git, which just shows the
-sides of a conflict without a diff.
+sides of a conflict without a diff:
+
+<<<<<<<
+left
+|||||||
+base
+=======
+right
+>>>>>>>
+++++++++++ Contents of side #2
Jujutsu uses different conflict markers than Git:
<<<<<<<
%%%%%%%
-base
+left
+++++++
right
>>>>>>>
>>>>>>>>>>> Conflict 1 of 1 ends
```
We should support these options for "git" conflict marker style as well,
since Git actually does support producing longer conflict markers in
some cases through .gitattributes:
https://git-scm.com/docs/gitattributes#_conflict_marker_size
We may also want to support passing the conflict marker length to merge
tools as well in the future, since Git supports a "%L" parameter to pass
the conflict marker length to merge drivers:
https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
I don't think we need --keep-emptied flag. IIRC, "jj squash" has that flag in
order not to squash commit description to the destination commits. Since
"jj absorb" never moves commit description, the source commit is preserved in
that situation.
Closes#5141
It's convenient to test if rewriter.reparent()-ed commit is empty than
implementing the same check based on rewriter.new_parents(). CommitRewriter
is an intermediate state, and it doesn't know whether the commit will be rebased
or reparented.
This patch moves max_new_file_size() and conflict_marker_style() to CLI, but
there isn't a clear boundary whether the configuration should be managed by
UserSettings or not. I decided to move them to CLI just because we can eliminate
.optional() handling. The default parameters are defined in config/misc.toml.
I originally added the check so we would never canonicalize path relative to
random cwd, but Windows CI failed because "/" is a relative path. Suppose user
would want to share the same configuration file between native Windows and WSL,
this check would be too nitpicky.
This provides an inline version of Git's includeIf. The idea is that each config
layer has an optional key "--when" to enable the layer, and a layer may have
multiple sub-layer tables "--scope" to inline stuff. Layers can be nested, but
that wouldn't be useful in practice.
I choose "--" prefix to make these meta keys look special (and are placed
earlier in lexicographical order), but I don't have strong opinion about that.
We can use whatever names that are unlikely to conflict with the other config
sections.
resolve() isn't exported as a StackedConfig method because it doesn't make
sense to call resolve() on "resolved" StackedConfig. I'll add a newtype in
CLI layer to distinguish raw config from resolved one. Most consumers will
just see the "resolved" config.
#616
ConfigLayers will be cloned to new StackedConfig instance at resolution stage.
ConfigFile could own ConfigLayer instead of Arc<_>, but copy-on-write behavior
is probably better for the current users.