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.
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.
I'll make TreeState::snapshot() return a boolean denoting whether tree_state
is updated or not. New tree_id can be obtained from TreeState, so let's
remove it from the return value.
Otherwise directories containing files cannot be removed.
I think making files readonly is enough to tell user that the left side
cannot be edited, but I haven't tested that with Meld. If that's not enough,
we'll probably need to undo set_readonly_recursively() at exit.
Apparently, I need to pass `--merge` option to use kdiff3 as a diff editor.
We could add `diff-editor-args` or extend `diff-editor` to a list of command
arguments, but we'll eventually add stock merge tools and the configuration
would look like:
[merge-tools.<name>]
program = ...
diff-args = [...]
edit-args = [...]
merge-args = [...]
I think I copied the name `write_tree()` from Git, but I find it quite
confusing, since it's not clear if it write a tree to the working copy
or reads the working copy and writes a tree to the store (it's the
former).
Used to produce a message like this:
```
thread 'main' panicked at 'failed to run diff editor: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/diff_edit.rs:136:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
Now produces a message like this:
```
Error: Failed to edit diff: Error executing editor 'meld': No such file or directory (os error 2)
```
The library crate shouldn't look up the user's `$HOME` directory
(maybe the library is used by a server process), so let's have the
caller pass it into the library crate instead.
I'm about to make callers pass in "base" Git ignores when writing a
tree from the working copy. `edit_diff()` will then need to pass
that. It'll be easier to do that if we have a proxy on
`WorkspaceCommandHelper`.
I was surprised that we save the `TreeState` before
`LockedWorkingCopy::finish()`. That means that even if the caller
instead decides to discard the changes, some changes will already have
been written.
The diff-editing code shares the `TreeState` functionality with the
working-copy code. That means we can now let the user edit conflicts
without materializing them first. So now the user can do e.g. `jj edit
-r <some commit>` and resolve only some of the conflicts.
This change teaches `Tree::diff()` to filter by a matcher. It only
filters the result so far; it does not restrict the tree walk to what
`Matcher::visit()` says is necessary yet. It also doesn't teach the
CLI to create a matcher and pass it in.
I had initially hoped that the type-safety provided by the separate
`FileRepoPath` and `DirRepoPath` types would help prevent bugs. I'm
not sure if it has prevented any bugs so far. It has turned out that
there are more cases than I had hoped where it's unknown whether a
path is for a directory or a file. One such example is for the path of
a conflict. Since it can be conflict between a directory and a file,
it doesn't make sense to use either. Instead we end up with quite a
bit of conversion between the types. I feel like they are not worth
the extra complexity. This patch therefore starts simplifying it by
replacing uses of `FileRepoPath` by `RepoPath`. `DirRepoPath` is a
little more complicated because its string form ends with a '/'. I'll
address that in separate patches.
This is yet another step towards making it easy to propagate
`BrokenPipe` errors. The `jj diff` code (naturally) diffs two trees
and prints the diffs. If the printing fails, we shouldn't just crash
like we do today.
The new code is probably slower since it does more copying (the
callback got references to the `FileRepoPath` and `TreeValue`). I hope
that won't make a noticeable difference. At least `jj diff -r
334afbc76fbd --summary` didn't seem to get measurably slower.
I'm preparing to publish an early version before someone takes the
name(s) on crates.io. "jj" has been taken by a seemingly useless
project, but "jujube" and "jujube-lib" are still available, so let's
use those.
Changes to the "before" side of the diff will have no effect, so let's
clarify that by marking it readonly. At least Meld checks the
permissions and shows in the UI that the left side is readonly.
This adds an interactive mode for `jj restore`. It works by first
creating two temporary directories with the contents of the subset of
files that differ between the two trees, and then letting the user
edit the directory representing the right/after side. This has some
advantages compared to the interactive modes in Git and Mercurial:
* It lets the user edit the final state as opposed to the diff itself
(depending on the diff tool, of course). I think most users find it
easier to edit the file contents than to edit the patch
format.
* It delegates the hard work to a tool that is already written (this
is a big advantage for an immature tool like Jujube, but it is not
an advantage from the user's point of view).
Almost all of the work in this commit went into adding a function that
takes two trees, lets the user edit the diff, and returns a new tree
id. I plan to reuse that function for other interactive commands. One
planned command is `jj edit`, which will let the user edit the changes
in a commit. `jj edit -r abc123` will be mostly about providing a more
intuitive name for `jj restore --source abc123^ --destination abc123`,
plus it will be different for merge commits (it will edit only the
changes in the merge commit). I also plan to add `jj split` by letting
the user edit the full diff, leaving only the parts that should go
into the first commit. Perhaps there will also be commands for moving
part of a commit out of or into a parent commit.