https://github.com/cargo-bins/cargo-binstall
Note that `jj` will only become installable once the next release
is published to crates.io. For this reason, I am planning to
wait until then before documenting the fact that `jj` can be
installed this way.
At that point, `cargo binstall jj-cli` should be sufficient.
Before then, it's possible to test that this will work by doing
```
cargo binstall jj-cli --force --strategies crate-meta-data --log-level debug --dry-run --manifest-path cli/Cargo.toml
```
Without --dry-run, this should install the 0.9 release if run
on `cli/Cargo.toml` form this commit.
Among other things, this prevented `jj` from working with
`cargo binstall`.
The trick is taken from
https://github.com/rust-lang/cargo/issues/2911#issuecomment-1483256987.
We could now also remove `--bin jj` from the installation commands
in `install-and-setup.md`, but I'm not sure we should. That argument
makes it clear that the binary is `jj`, not `jj-cli`.
Fixes#216.
I don't think there's any reason to use the local backend in tests
instead of using the stricter test backend.
I think we should generally use the test backend in tests and only use
the local backend or git backend when there's a particular reason to
do so (such as in `test_bad_locking` where the on-disk directory
structure matters). But this patch only deals with the simpler cases
where we were only testing with the local backend.
This appears to be broken at db0d14569b "cli: wrap repo in a struct to
prepare for adding cached data." Testing this isn't easy since the operation
id recorded here will be overwritten immediately by snapshot_working_copy(),
and the snapshotting should work fine so long as the tree id matches.
The rest of the functions in this file are defined before they are used, so it confused me when trying to track down this function in the static call graph.
It makes the call sites clearer if we pass the `TestRepoBackend` enum
instead of the boolean `use_git` value. It's also more extensible (I
plan to add another backend for tests).
I think the feature is requested by enough users that we should
include it by default, also for people who install from source (we
include it in the `packaging` feature already).
It increases the size of the binary from 16.5 MiB to 17.8 MiB. I
suspect we'd see some of that increase in size soon anyway, as I'm
probably going to use Tokio for making async backend requests.
There should be no reason to include `criterion` without the `bench`
feature. Adding the `dep:` prefix to any dependency makes cargo not
expose the implicit `criterion` feature.
Since we have overloaded operator symbols, we need to deduplicate them
upfront. Legacy and compat operators are also removed from the suggestion.
It's a bit ugly to mutate the error struct before calling Error::renamed_rule(),
but I think it's still better than reimplementing message formatting function.
As we discussed in #1928, it seems better to print information about
abandoned commits in the context of the pre-abandon state. For
example, that means that we'll include any branches that pointed to
the now-abandoned commits.
This is a naive implementation, which cannot deal with multiple children
or parents stemming from merges.
Note: I gave each command separate a separate argument struct
for extensibility.
Fixes#878
Many failure to export refs to Git are not about conflicts between a
branch named `foo` and a branch named `foo/bar`, so don't give that
hint in most cases.
Suppose "x::y" is the operator that defaults to "root()::visible_heads()"
respectively, "::" is identical to "all()". Since we've just changed the
behavior of "..y", ".." is now "root()..visible_heads()" meaning "~root()".
In `LockedWorkingCopy::drop()`, we panic if the caller had not called
`finish()`. IIRC, the idea was both to find bugs where we forgot to
call `finish()` and to prevent continuing with a modified
`WorkingCopy` instance. I don't think the former has been a problem in
practice. It has been a problem in practice to call `discard()` to
avoid the panic, though. To address that, we can make the `Drop`
implementation discard the changes (forcing a reload of the state if
the working copy is accessed again).
I also converted the error from `InternalError` to `UserError`. So far
I've intented to use `InternalError` only to indicate bugs or corrupt
repos. I'm not sure that's a good idea, and we can revisit it later.
If the path is too long to fit on the screen, this patch makes it so
we elide the first part of it. It goes a bit further and trims it down
to ~70% of the screen, giving some room for the stat. This seems
somewhat similar to what Git does.
`insta` ignores leading indentation (as long as it's consistent within
the snapshot), but when a test case fails and you let `cargo insta`
update it, it's going to use a specific indentation. There were a few
tests that didn't match that indentation, which could lead to
surprising diffs if the tests fail at some point.
This shows that there's too much padding because we pad based on
number of bytes.
I had to reduce the path names for the file names not to get too long
for my file system.
We can still crash on terminals that are less than 4 characters wide
(maybe it doesn't matter if we do because the user can't tell the
crash report from a diffstat in such a terminal?). This patch fixes
the crash.
We would run into a panic due to "attempt to subtract with overflow"
if the path was long. This patch fixes that and adds tests showing the
current behavior when there are long paths and/or large diffs.
When we start writing tree-level conflicts in an existing repo, we
don't want commits that change the format to be non-empty if they
don't change any content. This patch updates `MergeTreeId::eq()` to
consider two resolved trees equal even if only their `MergedTreeId`
variant is different (one is path-level and one is tree-level).
I think I've gone through all places we compare tree ids and checked
that it's safe to compare them this way. One consequence is that
rebasing a commit without changing the parents (typically
auto-rebasing after `jj describe`) will not lead to the tree id
getting upgraded, due to an optimization we have for that case. I
don't think that's serious enough to handle specially; we'll have to
support the old format for existing repos for a while regardless of a
few commits not getting upgraded right away.
The number of failing tests with the config option enabled drop from
108 to 11 with this patch.
We're finally ready to start writing trees using the new format where
we represent conflicts by having multiple trees in the commit instead
of having a single tree with multiple entries at a path. This patch
adds a config option for that. It's not ready to be used yet, so I
haven't updated the release notes or other documentation.
I added only a simple CLI test for testing what happens when the
config is enabled in an existing repo. 108 tests currently fail if we
flip the default.
With the idea that less severe placeholders (like description) could
(and should) explicitly "opt out".
(Both email and name placeholders will be red with this change.)
I made it simply fail on explicit fetch/import, and ignored on implicit import.
Since the error mode is predictable and less likely to occur. I don't think it
makes sense to implement warning propagation just for this.
Closes#1690.
This switches the whole `diff_util` module to working with
`MergedTree`, `Merge<Option<TreeValue>>` etc., so it can support
tree-level conflicts.
Since we want to avoid using `ConflictId`s, I switched the hash we use
for conflicts in `--git` style diffs to use an all-'0' id instead of
using the conflict id.
This patch also extracts format_detailed_signature() function to deduplicate
the "show" template bits.
The added placeholder templates aren't labeled as "empty". If needed, I think
the whole template can be labeled as "empty" (or "empty_commit") just like
"working_copy".
Closes#2112
An alternative name for it would be `arity()`, but `num_sides()`
probably more clearly says that it's not about the number of removes
or the total number of terms.
I think this is less surprising than falling back to the default length.
i64-to-usize conversion can also overflow on 32 bit environment, but I'm not
bothered to handle overflow scenario.
To support tree-level conflicts, we're going to need to update the
working copy from one `MergedTree` to another. We're going need to
store multiple tree ids in the `tree_state` file. This patch gets us
closer to that by getting the diff from `MergedTree`s`, even though we
assume that they are legacy trees for now, so we can write to the
single-tree `tree_state` file.
This allows negative numbers, which also means functions which took numbers can now take negative numbers
Luckily, they all already handled this exactly as expected.
Many of the `TreeBuilder` users have an `Option<TreeValue>` and call
either `set()` or `remove()` or the builder depending on whether the
value is present. Let's centralize this logic in a new
`TreeBuilder::set_or_remove()`.
The way `jj git push` without arguments chooses branches pointing to
either `@` or `@-` is unusual and difficult to explain. Now that we
have `-r`, we could instead default it to `-r '@-::@'`. However, I
think it seems likely that users will want to push all local branches
leading up to `@` from the closest remote branch. That's typically
what I want. This patch changes the default to do that.
If there are branches in the revset that don't need to be pushed
because they already match the destination, we currently just print
`Nothing changed.` It seems consistent with that to also treat it as
success if there are no branches in the specified set to start
with. This patch makes the command print a warning in that case
instead.
The VS Code "Better TOML" plugin (which I think most of our VS Code developers use?) doesn't support the `x.y = z` syntax at the top level, even though it's valid TOML.
This is also useful if we ever want to add additional properties in different sub-crates (although unlikely for the near future).
`revset::parse()` already has a `RevsetWorkspaceContext` argument, so
I think it makes sense to put that and the other context arguments
into a larger `RevsetParseContext` object.
We resolve file paths into repo-relative paths while parsing the
revset expression, so I think it's consistent to also resolve which
workspace "@" refers to while parsing it. That means we won't need the
workspace context both while parsing and while resolving symbols.
In order to break things like `author("martinvonz@")` (thanks to @yuja
for catching this), I also changed the parsing of working-copy
expressions so they are not allowed to be
quoted. `author(martinvonz@)` will therefore be an error now. That
seems like a small improvement anyway, since we have recently talked
about making `root` and `[workspace]@` not parsed as other symbols.
Custom binaries will often want to provide e.g. additional command
aliases, additional revset aliases, custom colors, etc. This adds a
mechanism for them to do that.
This commit replaces the functions `UserSettings::user_name_placeholder()`` and
`UserSettings::user_email_placeholder()` with `const` `&str`s to emphasize that
the placeholder strings must not be changed to support commits without
names or email addresses made before this change.
Bright green really pops on my screen, and I don't think there is a reason
for the root commit to be attention-grabbing.
This follows up on https://github.com/martinvonz/jj/pull/2084.
The syntax is slightly different from Mercurial. In Mercurial, a pattern must
be quoted like "<kind>:<needle>". In JJ, <kind> is a separate parsing node, and
it must not appear in a quoted string. This allows us to report unknown prefix
as an error.
There's another subtle behavior difference. In Mercurial, branch(unknown) is
an error, whereas our branches(literal:unknown) is resolved to an empty set.
I think erroring out doesn't make sense for JJ since branches() by default
performs substring matching, so its behavior is more like a filter.
The parser abuses DAG range syntax for now. It can be rewritten once we remove
the deprecated x:y range syntax.
One use case for `jj split` is when creating a new commit from some of
the changes in the working copy. If there's no description on the
working-copy commit in that case, it seems better to not ask the user
to provide one when they're splitting the commit either.
I've extracted the `builtin_log_root` template for users to customize the
default templates without fully overriding them, for example I would remove
the change_id/commit_id for myself - and we discussed in Discord that leaving
those makes sense for the user to be reminded/teached that the root commit has
a change id made from z's.
Similar to other boolean flags, such as "working_copy" or "empty".
We could test something like
`"0000000000000000000000000000000000000000".contains(commit_id)`
like I did for myself, but first of all this is ugly, and secondly the root
commit id is not guaranteed to be 40 zeroes as custom backend implementations
could have some other root.
This basically means that heads in a filtered graph appear in reverse
chronological order. Before, "jj log -r 'tags()'" in linux-stable repo would
look randomly sorted once you ran "jj debug reindex" in it.
With this change, indexing is more like breadth-first search, and BFS is
known to be bad at rendering nice graph (because branches run in parallel.)
However, we have a post process to group topological branches, so we don't
have this problem. For serialization formats like Mercurial's revlog iirc,
BFS leads to bad compression ratio, but our index isn't that kind of data.
Reindexing gets slightly slower, but I think this is negligible.
(in Git repository)
% hyperfine --warmup 3 --runs 10 "jj debug reindex --ignore-working-copy"
(original)
Time (mean ± σ): 1.521 s ± 0.027 s [User: 1.307 s, System: 0.211 s]
Range (min … max): 1.486 s … 1.573 s 10 runs
(new)
Time (mean ± σ): 1.568 s ± 0.027 s [User: 1.368 s, System: 0.197 s]
Range (min … max): 1.531 s … 1.625 s 10 runs
Another idea is to sort heads chronologically and run DFS-based topological
sorting. It's ad-hoc, but worked surprisingly well for my local repositories.
For repositories with lots of long-running branches, this commit will provide
more predictable result than DFS-based one.
`jj chmod` won't operate on conflicts involving non-files on the
positive sides. However, the error message says "None of the sides of
the conflict are files", which is not correct.
That is, jj will use ui.default_description as a starting point when
user is about to describe an empty change.
I think it might be confusing to do this with -m / --stdin (violates
WYSIWYG), so I'm only doing this when jj invokes an editor.
Also, this could evolve into a proper template in the future instead of
just plain text, to allow inheriting from parent change(s), for example.
Partially addresses #1354.
We anyway trim the newlines eventually and this just does that eagerly
so we output the "correct" description back to stdout (on describe for
example, we'd now print the first non empty line).
Empty files can be confusing in diff output. For example:
```
Added regular file file1:
Added regular file file2:
1: foo
```
This commit adds an "(empty)" placeholder instead. Since it's not
colored, and doesn't have line numbers, it will hopefully not be
mistaken for a file with the contents "(empty)".
AFAIK, we can't make HEAD detached in an empty Git repository, so we need
to temporarily switch to the new default branch before checking out.
Fixes#2047
`update_from_content()` already writes file content for each term of
an unresolved merge, so it seems consistent for it to also write the
file content for resolved merges. I think this should simplify further
refactoring for tree-level conflicts and for preserving the executable
bit.
Since `update_from_contents()` only works with file contents and not
the executable or other kinds of paths, I think it makes more sense
for it to deal with `FileId`s instead of `TreeValue`s.
I think I moved way too many functions onto `Merge<Option<TreeValue>>`
in 82883e648d. This effectively reverts almost all of that
commit. The `Merge<T>` type is simple container and it seems like it
should be at fairly low level in the dependency graph. By moving
functions off of it, we can get rid of the back-depdencies from the
`merge` module to the `conflict` module that I introduced when I moved
`Merge` to the `merge` module. I'm thinking the `conflict` module can
focus on materialized conflicts.
It's messy if pager and child output are interleaved as the pager controls
the tty.
Windows code is untested. I think the underlying I/O behavior is similar, but
I don't have expertise.
Two things will be added:
a. show warning if child exited with non-zero status
b. attach pager stdin to stderr of child process
I think (a) could be propagated from generate_diff() as an error variant, but
for (b), it makes sense to pass ui down to the function.
They are shown next to the change and commit id, since they are other names the
commit can be referred by.
The description is separated from the branches by a ` | ` when there are
branches, so that one can tell the branches from the description without color.
The result looks like this: ![image](https://github.com/martinvonz/jj/assets/4123047/a38aff7b-2b47-49e6-8461-c42e8eb535a4)
Maybe we could load GitBackend without resolving .git symlink, but that would
introduce more subtle bugs. Instead, we calculate the expected Git workdir path
from the canonical ".git" path.
Fixes#2011
This makes it possible to use ed25519 and ed25519-sk keys by trying
them one at a time. However, it still fails if one of them is
password-protected; we don't try the next key in that case.
Since `Conflict<T>` can also represent a non-conflict state (a single
term), `Merge<T>` seems like better name.
Thanks to @ilyagr for the suggestion in
https://github.com/martinvonz/jj/pull/1774#discussion_r1257547709
Sorry about the churn. It would have been better if I thought of this
name before I introduced `Conflict<T>`.
Summary: There's no need to go around specifying `rust-version` or `edition` or
`version` several times, now that we have a global workspace. Instead, inherit
workspace metadata from the top-level Cargo.toml file.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Iaf905445978ed2b3377239dcdb8a6c32
Summary: This moves all dependencies across the jj-lib and jj-cli crates into
the top-level Cargo file; with that, we can change each crate instead to just
inherit the workspace version, with the toggled features enabled, by setting
a dependency such as:
dep.workspace = true
in the relevant Cargo.toml file.
This doesn't actually change any of the build semantics (from what I can tell)
nor the lockfile, and seems to respond normally. There are more cleanups that
can follow.
Two notes:
- Dependabot seems to work fine, based on what I've seen in other repos.
- `cargo add` doesn't seem to know how to add packages to a top-level
`workspace.dependencies` field; instead you can `cargo add -p jj-cli`
and move the entries, at least.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: I307827e5f15c0d8ea8e2a80ec793d3c7
Since .git/HEAD is less frequently updated, this should avoid unneeded
recompilation on test-only changes. This only applies to colocated repo.
For non-colocated repo, maybe we can watch src/ and ../lib/src files?
This also adds $NIX_JJ_GIT_HASH to reflect hash changes (and to not rerun
if no .git nor .jj directory exists.)
Since the recent move of `builds.rs` to `cli/build.rs`, incremental
builds re-calcuate the version number and thus result in some
re-compilation and lots of re-linking.
Summary: In preparation for unifying all workspace dependencies across all
crates, let's go ahead and move the jj-cli crate into its own new directory.
This will also be a nicer and more uniform layout as we add new `jj-*` crates.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Icf94e7ae5f290dc8e181215727b38ada