I noticed that some config structures do not use their "Default" implementation, and have their default specified in a TOML file. I think specifying defaults in TOML is great, and it'd be good to delete those Default implementations, so that it does not diverge from the default in the TOML file.
Cryptographic signature support in templates was added in
c99c97c6467fee3f3269d2934c10c758e041f834 (#4853), but has to be manually
configured. This adds some defaults to the built-in config.
Instead of having separate `builtin_*_with_sig` aliases, this adds to
the aliases that actually format commits. Since signature verification
is slow, this is disabled by default. To enable it, override
`ui.show-cryptographic-signatures`:
[ui]
show-cryptographic-signatures = true
[template-aliases]
'format_short_cryptographic_signature(signature)' = ...
'format_detailed_cryptographic_signature(signature)' = ...
Note that the two formatting functions take
`Option<CryptographicSignature>`, not `CryptographicSignature`. This
allows you to display a custom message if a signature is not found, but
will emit an error if you do not check for signature presence.
[template-aliases]
'format_detailed_cryptographic_signature(signature)' = '''
if(signature,
"message if present",
"message if missing",
)
'''
This goes against our rule that we shouldn't add config knob that changes the
command behavior, but I don't have any other idea to work around the problem.
Apparently, there are two parties, one who always wants to push new bookmarks,
and the other who mildly prefers to push&track new bookmarks explicitly.
Perhaps, for the former, creation of bookmarks means that the target branches
are marked to be pushed.
The added flag is a simple boolean. "non-tracking-only" behavior #5173 could be
implemented, but I don't want to complicate things. It's a failed attempt to
address the issue without introducing config knob.
Closes#5094Closes#5173
According to the discussion on Discord, streampager is still maintained.
It brings more dependencies, but seems more reliable in our use case. For
example, the streampager doesn't consume inputs indefinitely whereas minus
does. We can also use OS-level pipe to redirect child stderr to the pager.
Adds an optional `fix.tools.TOOL.enabled` config that disables use of a fix
tool (if omitted, the tool is enabled). This is useful for defining tools in
the user's configuration without enabling them for all repositories:
```toml
# ~/.jjconfig.toml
[fix.tools.rustfmt]
enabled = false
command = ["rustfmt", "--emit", "stdout"]
patterns = ["glob:'**/*.rs'"]
```
Then to enable it in a repository:
```shell
$ jj config set --repo fix.tools.rustfmt.enabled true
```
Now `jj --config ui.con<TAB><TAB>` will autocomplete
```
ui.conflict-marker-style=diff
ui.conflict-marker-style=snapshot
ui.conflict-marker-style=git
```
Booleans are completed as `false`, `true`, the remaining types are left
without completions.
the trailing `=` is especially nice to have because otherwise fish will
complete the suggestion and insert a space before the cursor.
With the `=`, `jj config --config ui.pagin<TAB>never` works.
The "git" CLI chdir()s to the work tree root, so paths in config file are
usually resolved relative to the workspace root. OTOH, jj doesn't modify the
process environment, so libgit2 resolves remote paths relative to cwd, not to
the workspace root. To mitigate the problem, this patch makes "jj git remote"
sub commands to store resolved path in .git/config. It would be nice if we can
reconfigure in-memory git2 remote object to use absolute paths (or set up
in-memory named remote without writing a config file), but there's no usable
API afaik.
This behavior is different from "git remote add"/"set-url". I don't know the
rationale, but these commands don't resolve relative paths, whereas "git clone"
writes resolved path to .git/config. I think it's more consistent to make all
"jj git" sub commands resolve relative paths.
When running `cmd.spawn()` rust will by default inherit
the stderr of the parent, so `jj log test<TAB>`, would
print `There is no jj repo in "."` into the prompt.
UserSettings will be obtained from there. If operation template supported
"self.repo() -> Repo" method, RepoLoader would be needed. It's equivalent to
Repo in CommitTemplateLanguage.
This makes the graph compact. Short change ids are usually printed as a part
of commit summary. The --no-graph output is a bit harder to parse, but we can
still discriminate entries by change ids.
The list of migration rules is managed by CliRunner. I don't know if that's
needed, but in theory, an extension may insert migration rules as well as
default config layers.
Migration could be handled by ConfigEnv::resolve_config(), but it seemed rather
complicated because Vec<ConfigMigrationRule> cannot be cloned, and the scope of
these variables are a bit different.
If many files are conflicted, it would be nice to be able to resolve all
conflicts at once without having to run `jj resolve` multiple times.
This is especially nice for merge tools which try to automatically
resolve conflicts without user input, but it is also good for regular
merge editors like VS Code.
This change makes the behavior of `jj resolve` more consistent with
other commands which accept filesets since it will use the entire
fileset instead of picking an arbitrary file from the fileset.
Since we don't support passing directories to merge tools yet, the
current implementation just calls the merge tool repeatedly in a loop
until every file is resolved, or until an error occurs. If an error
occurs after successfully resolving at least one file, the transaction
is committed with all of the successful changes before returning the
error. This means the user can just close the editor at any point to
cancel resolution on all remaining files.
There are some experiments to try and compile `jj` to WebAssembly, so that we
might be able to do things like interactive web tutorials. One step for that
is making `git` support in `jj-cli` optional, because we can stub it out for
something more appropriate and it's otherwise a lot of porting annoyance for
both gitoxide and libgit2.
(On top of that, it might be a useful build configuration for other experiments
of mine where removing the need for the large libgit2 depchain is useful.)
As part of this, we need to mark `jj-lib` as having `default-features = false`
in the workspace dependency configuration; otherwise, the default behavior
for Cargo is to compile with all its default features, i.e. with git support
enabled, ignoring the `jj-cli` features clauses.
Other than that, it is fairly straightforward junk; it largely just sprinkles
some `#[cfg]` around liberally in order to make things work. It also adjusts the
CI pipeline so this is tested there, too, so we can progressively clean it up.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Certain tools (`diff`, `delta`) exit with code 1 to indicate there was
a difference. This allows selectively suppressing the "Tool exited with
... status" warning from jj when generating a diff.
example:
```toml
[merge.tools.delta]
diff-expected-exit-codes = [0, 1]
```
This backs out commit 0de36918e4c020e0e54816f29c47cb57cc9cfbf5. Documentation,
tests, and comments are updated accordingly. I also add ConfigTableLike type
alias as we decided to abstract table-like items away.
Closes#5255
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.
There should be no difference, but it's more consistent that all workspace/repo
commands use workspace_command.settings(), etc. than command.settings().
This ensures that WorkspaceCommandHelper created for initialized/cloned repo
refers to the settings object for that repo, not the settings loaded for the
cwd repo.
I also removed WorkspaceCommandEnvironment::settings() because it doesn't own
a workspace object. It's implementation detail that the env object holds a
copy of workspace.settings(), and the caller should be accessible to the
workspace object.
This patch doesn't fix DiffEditor::edit() API, which is fundamentally broken
if matcher argument is specified. I'm not sure if the builtin behavior is
correct or not. Suppose we add "jj diffedit FILESETS..", it would probably make
sense to leave unmatched paths unmodified because it is the command to edit the
destination (or right) tree. This is the edit_diff_external() behavior.
Fixes#5252
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 bfb7613d5d192d3c4dc533afa4f2ff0d6b9016c5).
Co-authored-by: necauqua <him@necauq.ua>
Co-authored-by: julienvincent <m@julienvincent.io>