It turns out that the use case I had for `exactly()` was slightly more
subtle, and I need range support. In particular, usage of `exactly()`
in expressions used by `revsets.log-graph-prioritize` can and will
cause `jj log` to fail if the assertion fails; in my case, a particular
expression I use should be equal to zero-or-one revisions.
This (ab)uses string literal syntax to parse out a range that is like
a subset of Rust's range syntax; in particular unbounded endpoints like
`x..` or `..=y` are not supported. Ideally the grammar would be expanded
to handle this case more smoothly.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Up until now, trying to get a config value that was an array or a table would fail with an error indicating that only values that can be converted to a string can be displayed. This change fixes that issue by converting arrays and tables into TOML format.
The migration logic is basically the same as 717d0d3d6d "git: on
deserialize/import/export, copy refs/heads/* to remote named git." Now
git::import_refs() processes bookmarks and tags in the same way.
git::export_refs() is unchanged because we don't have any commands that would
move local tags internally.
Git-tracking tags will be stored there. I don't have a concrete plan for proper
remote tags support, but I think tags fetched/pushed internally can be recorded
as remote tags.
I'm thinking of adding remote tags table to support tag mutation commands, so I
think it's time to update the storage format. RefTarget is serialized to a list
of alternate terms because we don't need to support legacy formats here.
Previously, nextest marked tests slow in CI when they run for more
than 5 seconds. This makes it so that this happens after 10 seconds.
I did *not* change the timeout for when tests are actually *terminated*
for being too slow. It remains at 100s. It might make sense to increase
it (keeping the `terminate-after` multiplier at 10).
This is just adjusting to taste, but I find the number of SLOWs in
5074734234
distracting, and most of the slow tests on Windows last more than 10s
anyway.
We could also do this only on Windows if people prefer, but
I think doing it everywhere is simpler.
This makes it so that tests that last longer than 10s are marked as
"SLOW" in nextest UI. This does not terminate them. We already have this
enabled in CI, but it seems nice to enable for everybody. On my
machine, `test_concurrent_read_write_commit` sometimes deadlocks, and
this helps see which test is troublesome.
I erred on the side of a higher timeout, following the principle that
it's more important that warnings are actionable than to miss some
warnings. If somebody is debugging slow tests, they'll know to lower the
value.
See the CI config or the next commit for what a config that also
terminates tests if they run too long looks like.
Having tests illustrates the behavior. Making this public de-duplicates
the code with ERSC. This also allows determining whether a change id
comes from the header or is synthetic.
This is just a nice-to-have for me, we will also duplicate the code
until this is merged (if that happens).
This fixes the bug described below.
I have `submodule.recurse=true` set in my .gitconfig. When trying
to fetch repos with submodules (e.g. git/git), I got errors like these:
```console
$ jj git fetch
remote: Enumerating objects: 853, done.
remote: Total 853 (delta 448), reused 439 (delta 413), pack-reused 315 (from 2)
Error: Git process failed: External git program failed:
Could not access submodule 'sha1collisiondetection'
```
This error occured when fetching only, *not* when cloning. It occured
even when there wasn't anything to fetch.
I only tested repositories that never had submodules initialized or
fetched (which would have to be done with Git).
Our own tutorial and the one by Steve Klabnik both require experience
with Git. Adding a link to "Jujutsu for everyone" will give newcomers
without that experience an appropriate starting point for learning
Jujutsu.
If a subprocess exits with a nonzero status, we don't need to print out
the fact that it exited with a nonzero status.
I think it is fairly obvious that we should try to match the return code
of the inner process.
In a bit more contention is whether we should print out the error
message at all. I would argue that a command that fails almost always
prints to stderr anyway, and the whole point of `jj util exec` is that
it should go into your aliases and thus the fact that it's an "external"
command should be hidden from the user (see my example above).
```
$ jj upload # "upload" is an alias using jj util exec
<presubmit failures>
Error: presubmits failed
external command exited with 5
<exits with exit status 1>
```
I think this helps readability a bit. I updated `TreeDiffEntry` and a
few related places. I think there are many other places where we could
use the new type.
I'm about to add a generic `Diff<T>` that's more similar to
`Merge<T>`, so I want to free up the name. It seems better to have
`Diff<T>` and `ContentDiff` than e.g. `GenericDiff<T>` and `Diff` or
having to use qualified imports.
After updating nightly rust, this code generates a false positive
(below). AFAICT, the new code is only a little more consistent, but it
avoids the warning.
The warning is:
```
warning: unneeded cloning of iterator items
--> cli/src/commands/bookmark/list.rs:251:19
|
251 | commits = bookmark_list_items
| ___________________^
252 | | .iter()
253 | | .filter_map(|item| item.primary.target().added_ids().next())
254 | | .cloned()
... |
258 | | .map(|commit| (commit_id, commit.store_commit().clone()))
259 | | })
| |______________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_iter_cloned
= note: `#[warn(clippy::redundant_iter_cloned)]` on by default
help: try
|
253 ~ .filter_map(|item| item.primary.target().added_ids().next())
254 + .map(|commit_id| {
255 + store
256 + .get_commit(&commit_id)
257 + .map(|commit| (commit_id, commit.store_commit().clone()))
258 + })
|
```
Rust version (nightly) that generates this clippy warning:
```console
$ rustc -Vv
rustc 1.92.0-nightly (0be8e1608 2025-09-19)
binary: rustc
commit-hash: 0be8e16088894483a7012c5026c3247c14a0c3c2
commit-date: 2025-09-19
host: aarch64-apple-darwin
release: 1.92.0-nightly
LLVM version: 21.1.1
```
Simply removing the `.cloned()` as suggested by Clippy results in this
error:
```
error[E0277]: a value of type `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>` cannot be built from an iterator over elements of type `(&jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>)`
--> cli/src/commands/bookmark/list.rs:259:14
|
259 | .try_collect()?;
| ^^^^^^^^^^^ value of type `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>` cannot be built from `std::iter::Iterator<Item=(&jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>)>`
|
= help: the trait `FromIterator<(&jj_lib::backend::CommitId, std::sync::Arc<_>)>` is not implemented for `std::collections::HashMap<jj_lib::backend::CommitId, std::sync::Arc<jj_lib::backend::Commit>>`
but trait `FromIterator<(jj_lib::backend::CommitId, std::sync::Arc<_>)>` is implemented for it
= help: for that trait implementation, expected `jj_lib::backend::CommitId`, found `&jj_lib::backend::CommitId`
= note: required for `Result<HashMap<CommitId, Arc<Commit>>, BackendError>` to implement `FromIterator<Result<(&CommitId, Arc<Commit>), BackendError>>`
note: required by a bound in `itertools::Itertools::try_collect`
--> /Users/ilyagr/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.14.0/src/lib.rs:2381:23
|
2378 | fn try_collect<T, U, E>(self) -> Result<U, E>
| ----------- required by a bound in this associated function
...
2381 | Result<U, E>: FromIterator<Result<T, E>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Itertools::try_collect`
= note: the full name for the type has been written to '/Users/ilyagr/dev/jj/target/debug/deps/jj_cli-442101cf9493e967.long-type-2991360816845051416.txt'
= note: consider using `--verbose` to print the full type name to the console
```
Provide a bit more detail about the JJ to Gerrit change mapping, advice
on handling splits and squashes, as well as the existing FAQ
configuration for adding Change-Id directly to change descriptions.
1.90 was just released, so this seems reasonable, and it finally lets us
use let-chains. This includes all the clippy fixups too, and some small
changes suggested by Ilya.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
With `all:` having gone away, some users (including me) had been using it
to enforce an invariant: by omitting it, an expression was guaranteed to
yield exactly one result. For example, this is important when using tools
like `jj rebase -B/-A`
Instead, let's fix that case by building that functionality into the
revset language itself. The previous behavior can now be enforced via
the term `exactly(x, 1)`
In the future, `n` could also be a range.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
When completion functions are called in bash and zsh, quoted arguments
are passed exactly as they are typed, including shell quotes, and
clap_complete currently does not attempt to normalize this behavior.
For example, if the user types:
jj diff -f 'trunk()' <TAB>
std::env::args() will be equivalent to:
["jj", "diff", "-f", "'trunk()'", ""]
To accurately capture the revset, the quotes need to be stripped.
This workaround handles the most common cases that work consistently
across shells, rather than going for maximum accuracy.
Currently there are instructions on how to setup jj to work with GitHub,
but not Gerrit, which seems to be very popular with the jj community.
Add a gerrit.md file to help users discover the jj gerrit subcommand.
Gerrit's web UI (like jj) recognizes unique ID prefixes, so a reference
like `I1234cdef` in a commit message or a review comment becomes a
hyperlink to the referenced change. Currently, every jj-produced change
begins with `I6a6a6964`, which makes that less useful. This moves the
fixed `6a6a6964` component to the end, so the prefix is unique.
Closes#7500.
This is mostly a revert of dd73b5ab7d. It closes#5374, as feedback on
the issue has shown that many longtime and new users dislike it. Martin
himself also mentioned that he wants to walk back this deprecation.
Co-authored-by: Remo Senekowitsch <remo@buenzli.dev>
This code was added by 4af678848d "op_store: minimal change to load/store
tracking state of remote branches" (2023-10-16). It's unlikely that the head
operation was written by jj older than that. Remote refs in old views are now
mapped to State::New unconditionally, which should be okay for read-only
operations.
This implements the most basic workflow for submitting changes to Gerrit,
through a verb called 'upload'. This verb is chosen to match the gerrit
documentation (https://gerrit-documentation.storage.googleapis.com/Documentation/3.12.1/user-upload.html).
Given a list of revsets (specified by multiple `-r` options), this will parse
the footers of every commit, collect them, insert a `Change-Id` based off the jj change-id (if one doesn't already exist), and then push them into the given remote.
It will then abandon the transaction, thus ensuring that gerrit change-IDs do not appear in jj.
Because the argument is a revset, you may submit entire trees of changes at
once, including multiple trees of independent changes, e.g.
jj gerrit upload -r foo:: -r baz::
Signed-off-by: Austin Seipp <aseipp@pobox.com>