I ran an upgraded Clippy on the codebase. All the changes seem to be
about using variables directly in format strings instead of passing
them as separate arguments.
Clap bails parsing when an "error" is encountered, e.g. a subcommand is missing,
"--help" is passed, or the "help" subcommand is invoked. This means that the
current approach of parsing args does not handle flags like `--no-pager` or
`--color` when an error is encountered.
Fix this by separating early args into their own struct and preprocessing them
using `ignore_errors` (per https://github.com/clap-rs/clap/issues/1880).
The early args are in a new `EarlyArgs` struct because of a known bug where
`ignore_errors` causes default values not to be respected
(https://github.com/clap-rs/clap/issues/4391 specifically calls out bool, but
strings may also be ignored), so when `ignore_errors` is given, the default
values will be missing and parsing will fail unless the right arg types are used
(e.g`. Option`). By parsing only early args (using the new struct) we only need
to adjust `no_pager`, instead of adjusting all args with a default value.
This fixes the bug described in the previous commit.
Because we now print the message about failed exports also while
snapshotting, we may end up reporting it twice on one command. I'm not
sure it's worth worrying about that. We can deal with that later if it
turns out to be a common complaint.
Unfortunately, config::Value is lax and '[7]' could be parsed as '["7"]'.
I don't like it, but I think that's actually better for consistency as we
use config.get_string() in various places.
When a workspace's working-copy commit is updated from another
workspace, the workspace becomes "stale". That means that the working
copy on disk doesn't represent the commit that the repo's view says it
should. In this state, we currently automatically it to the desired
commit next time the user runs any command in the workspace. That can
be undesirable e.g. if the user had a slow build or test run started
in the working copy. It can also be surprising that a checkout happens
when the user ran a seemingly readonly command like `jj status`.
This patch makes most commands instead error out if the working copy
is stale, and adds a `jj workspace update-stale` to update it. The
user can still run commands with `--no-commit-working-copy` in this
state (doing e.g. `jj --no-commit-working-copy rebase -r @ -d @--` is
another way of getting into the stale-working-copy state, by the way).
I want to be able to create a `WorkspaceCommandHelper` without
snapshotting the working copy. That will be useful when adding a
command for updating a stale working copy.
This patch makes the function checking for a stale working copy return
a specialized error instead of `CommandError`. That has several advantages:
* It makes it easier to change the behavior so we don't automatically
update a stale working copy until the user explicitly tells us.
* It allows us to move the function to the library crate, to be
shared by non-CLI UIs (and server applications).
Similar to the previous commit, the checking for stale working copy is
a big part of `commit_working_copy()` and it's logically quite
separated from the rest, so let's extract it to a function.
The code for creating a `WorkspaceCommandHelper` for a given
`Workspace` is a well-separated part of the large
`workspace_helper()`, so lets extract it to a function.
Also allows several paths to be specified. By default, `jj resolve`
will find the first conflict that matches provided paths (if any)
and try to resolve it.
This command uses an external merge tool to resolve conflicts
simple enough that they can be resolved with a 3-way merge.
This commit provides a very basic version of `jj resolve` that
is hardcoded to use vimdiff.
This also slightly changes the errors of the Diff Editor, so that
both the diff editor and `jj resolve can share an error type.
I can't see any reason the user would want to specify revisions
matching the empty string, so let's disallow it. I created a custom
type for revision arguments instead of repeating `value_parser =
NonEmptyStringValueParser::new()`.
Let's acknowledge everyone's contributions by replacing "Google LLC"
in the copyright header by "The Jujutsu Authors". If I understand
correctly, it won't have any legal effect, but maybe it still helps
reduce concerns from contributors (though I haven't heard any
concerns).
Google employees can read about Google's policy at
go/releasing/contributions#copyright.
Aliases are loaded at WorkspaceCommandHelper::new() as it's easier to warn
invalid declarations there. Not all commands use revsets, but many do, so
I think it's okay to always pay the loading cost. Parsing the declaration
part (i.e. a symbol) should be fast anyway.
The nested error message isn't super readable, but seems good enough.
Config syntax to bikeshed:
- naming: [revset-alias] vs [revset-aliases] ?
- function alias will need quotes: 'f(x)' = 'x'
The CLI will load aliases from config, insert them one by one, and warn if
declaration part is invalid. That's why RevsetAliasesMap is a public struct
and needs to be instantiated by the caller.
This adds a warning whenever export to the backing Git repo fails,
whether it's by an explicit `jj git export` or an automatic export. It
might be too spammy to print the message after every failed command in
the colocated case, but let's try it and see.
This is a simple workaround to make operation IDs predictable (so they
don't include the path to `.../target/debug/jj` or similar). The full
path can probably be useful for troubleshooting, but we can deal with
that later if we see a need for it. It might also be less confusing
for Windows users if it says "jj.exe".
We currently get the hostname and username from the `whoami` crate. We
do that in lib crate, without giving the caller a way to override
them. That seems wrong since it might be used in a server and
performing operations on behalf of some other user. This commit makes
the hostname and username configurable, so the calling crate can pass
them in. If they have not been passed in, we still default to the
values from the `whoami` crate.
I'm going to add other error variants for when we fail to read/write
to disk, and I don't think we need to have a custom message for each
in the CLI crate. It's easier to pass along the message from the lib
crate.
(`ConflictedBranch`, on the other hand, is an expected error so I
think we should continue to let let the CLI crate define the error
message for it.)
Several lines of red text can be overwhelming, and makes it harder to
tell the hint from the error. Let's separate the hint from the error
instead. This matches what hg does. Having the hints separated out
also means that we could have a single config to turn them off.
I want to add a separate field for a hint, so that can be printed in a
different color (than red). Having a factory function is useful then,
since most call sites don't want to pass a hint. Also, by using a
factory function instead of using the constructor directly means that
we can accept `&str` arguments instead of forcing the caller to
convert a string literal to `String`.
Unfortunately, TOML requires quotes around the argument. So, the
usage is `jj --config-toml ui.color=\"always\"` in bash. The plan is
to eventually have a `--config` option with simpler syntax for
simple cases.
As discussed in https://github.com/martinvonz/jj/discussions/688.
Use clap::Command::try_get_matches_from() to parse args, and handle the
resulting error as a CommandError. The exit code 2 matches the exit code that
clap would output (this is tested by test_alias).
With this new abstraction, teach the clap output to respect "ui.color"
(--color doesn't seem to be understood). We'll also make use of it when
we route output through the pager.
The "errors" returned by try_get_matches_from() can be found at
https://docs.rs/clap/latest/clap/error/enum.ErrorKind.html. I've tested:
- no args
- --help
- help subcommand
- --version
- subcommand with --help
- subcommand with bad args