My recent fix to print context lines when there are less than 3 lines
of context wasn't enough; we should also print context lines when
there are exactly 3 lines of context :) I can't understand what the
`!context_before` condition was for, so I've just removed it. I guess
I'll notice soon if things look worse in some case.
With lots of callbacks replaced by iterators, we are now ready to
propagate most cases of `BrokenPipe` errors to the top-level
`dispatch()` function where it gets ignored and we exit with an error
code.
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.
The new `jj unsquash` command moves changes from a commit's parent
into the commit itself. It comes with a `--interactive` flag. The
command is probably most useful for moving changes from the working
copy's parent into the working copy but it can of course be used for
moving changes into any commit (from that commit's parent).
This updates `jj log` to walk the index for doing the topological
walk, which is much faster than walking the object graph. This speeds
up `jj log | head -1` in the git.git repo from ~1.9s to ~0.27s (most
of the remaining time is spent calculating the evolve state).
A consequence of walking the index instead is that the order of
commits in the output is by by generation number. That's nice in some
ways, but it also means that the newest commit isn't always at the
top.
When I recently changed the revision argument from being passed to
`-r` to being a positional argument, I accidentally made it
required. Let's restore the default of "@".
I keep forgetting to pass the `-r`. The command takes only a revision
as argument and it doesn't seem likely that we'll want to positional
arguments for filenames in the future either.
`Transaction` has a bunch of functions that are now simple
delegates. It probably makes sense to directly use a `&mut
MutableRepo` instead of `&mut Transaction` in most places. This patch
starts that migration.
This patch continues the work from the previous pathc. From this
patch, we no longer calculate the evolution state just because a
transaction starts. We still unnecessarily calculate it when adding a
commit within the transaction, however. I'll fix that next.
"{:?}" escapes `\` to `\\` for Windows paths. That breaks tests checking
paths without using "{:?}". Use PathBuf::display() in both commands and
tests to get consistent output.
This fixes test_init_local, test_init_git_internal, and
test_init_git_external on Windows.
It's sometimes useful to create a `RepoLoader` given an existing
`ReadonlyRepo`. We already do that in `ReadonlyRepo::reload()`. This
patch repurposes `ReadonlyRepo::reload()` for that.
This is yet another step towards making the `View` types
simpler. Perhaps we eventually won't need to wrap the types returned
from the `OpStore` at all.
I'd like to make `ReadonlyView` and `MutableView` focused on just the
state of the view (i.e. the set of heads, git refs, etc.). The
responsibility for managing the `.jj/view/op_heads/` directory should
be moved out of it. This prepares for that.
The only way to load the repo at a current operation (as with
`--at-op`) is currently to first load it at the head operation and
then call `reload()` on the repo. This patch makes it so we can load
the repo directly at the requested operation.
The index is now always kept up to date and it has functionality for
finding common ancestors, so let's use it! This should make merging
commits a little faster if their common ancestor is far away (which is
rare). It's probably much more important that the index-based
algorithm is more correct. Also, it returns multiple common ancestors
in the criss-cross case, which lets us do a recursive merge like git
does. I'm leaving the recursive merge for later, though.
We currently need to read the commit objects for finding common
ancestors. That can be very slow when the common ancestor is far back
in history. This patch adds a function for finding common ancestors
using the index instead.
Unlike the current algorithm, which only returns one common ancestor,
the new index-based one correctly handles criss-cross merges.
Here are some timings for finding the common ancestors in the git.git
repo:
| Without index | With Index |
| First run | Subsequent | First run | Subsequent |
v2.30.0-rc0 v2.30.0-rc1 | 5.68 ms | 5.94 us | 40.3 us | 4.77 us |
v2.25.4 v2.26.1 | 1.75 ms | 1.42 us | 13.8 ms | 4.29 ms |
v1.0.0 v2.0.0 | 492 ms | 2.79 ms | 23.4 ms | 6.41 ms |
Finding ancestors of v2.25.4 and v2.26.1 got much slower because the
new algorithm finds all common ancestors. Therefore, it also finds
v2.24.2, v2.23.2, v2.22.3, v2.21.2, v2.20.3, v2.19.4, v2.18.3, and
v2.17.4, which it then filters out because they're all ancestors of
v2.25.3.
Also note that the result was incorrect before, because the old
algorithm would return as soon as it had found a common ancestor, even
if it's not the latest common ancestor. For example, for the common
ancestor between v1.0.0 and v2.0.0, it returned an ancestor of v1.0.0
because it happened to get there by following some side branch that
led there more quickly.
The only place we currently need to find the common ancestor is when
merging trees, which we only do when the user runs `jj merge`, as well
as when operating on existing merge commits (e.g. to diff or rebase
them). That means that this change won't be very noticeable. However,
it's something we clearly want to do sooner or later, so we might as
well get it done.
The `StoreWrapper` currently caches all objects it returns. That lead
to e.g. `common_ancestors()` being very fast once all commits have
been read in. For example, in the git.git repo `jj bench
commonancestors` with v1.0.0 and v2.0.0 reports 2.8ms, but the first
iteration takes 480ms. This commit highlights such differences by
adding a printout of the time it took to run the timed routine the
first time.