Most commands are non-interactive, so this reduces duplication. We can
add another function for running a command and not waiting for a
prompt when we need it.
The CLI code for cloning a Git repo didn't use the usual
`finish_transaction()` method, because we didn't have support for
doing that on a repo that was creating half-way through a
command. That led to a bug where it would leave the initial checkout
(the one on top of the root commit) after checking out the correct
head.
This fixes a bug I've run into somewhat frequently. What happens is
that if you have a conflict on top of another conflict and you resolve
the conflict in the bottom commit, we just simplify the `Conflict`
object in the second commit, but we don't try to resolve the new
conflict. That shows up as an unexpected "conflict" in `jj log`
output, and when you check out the commit, there are actually no
conflicts, so you can just `jj squash` right away.
This patch fixes that bug. It also teaches the code to work with more
than 3 parts in the merge, so if there's a 5-way conflict, for
example, we still try to resolve it if possible.
`args` seems to make it clear that these are command-line arguments
(this is not Python, so there's no `*args`). It also avoids the risk
of conflicts and confusion with other matches (e.g. file patterns or
regexes).
Git notes (at least as implemented by libgit2) quickly gets really
slow, as noted in issue #7. This patch replaces it by a custom storage
format.
I tested the performance in the git.git repo with just a few hundred
annotated commits (~450, I think) and no sharding. I listed the first
~2900 commits there using `jj log --no-graph -r ,,v1.0.0 -T 'author
"\n"' | wc -l`. That took about 882ms. After this patch, it dropped to
108ms.
I did a similar test in this repo with 12700 annotated commits and
sharding, listing all visible commits. That took 142ms before this
patch (the sharding helps a lot!) and 55ms after.
Closes#3.
Closes#7.
The new store works the same way as the `OpHeadsStore`. It keeps track
of the current head file(s) by recording their names in a
directory. When a write happens, it adds the new head and then removes
the old head. There will be generally be a single head at a time. The
only exception is when there's been concurrent operations (locally, or
remotely, in the case of a distributed file system). When there are
multiple heads files, they are automatically merged. No guarantee is
given about which value wins if the key exists in several heads; the
store is meant to be used for data that's immutable once written. As
long as different keys are written, this is a CRDT. That makes it fit
for solving both #3 and #7.
I'm trying to replace the Git backend's use of Git notes for storing
metadata (#7). This patch adds a file format that I hope can be used
for that. It's a simple generic format for storing fixed-size keys and
associated variable-size values. The keys are stored in sorted
order. Each key is followed by an offset to the value. The offset is
relative to the first value. All values are concatenated after each
other. I suppose it's a bit like Git's pack files but lacking both
delta-encoding and compression.
Each file can also have a parent pointer (just like the index files
have), so we don't have to rewrite the whole file each time. As with
the index files, the new format squashes a file into its parent if it
contains more than half the number of entries of the parent. The code
is also based on `index.rs`.
Perhaps we can alo replace the default operation storage with this
format. Maybe also the native local backend's storage. We'll need
delta-encoding and compression soon then.
I'm about to change the index format (to remove predecessor
information), which will break the format. Let's prepare for that by
having `IndexStore` reindex the repo if it fails to read the index..
I think this is just cleaner, and it gives us room to put other
store-related data in the `.jj/store/` directory. I may want to use
that place for writing the metadata we currently write in Git notes
(#7).
Diffs between certain combinations of file types were not handled by
`jj diff` (for example, a diff between a conflict and another conflict
would not show a diff). This change fixes that, and also makes added
and removed files get printed with color and line numbers, which I've
often wanted.
The user currently has to edit `.jj/git/config` (or run `git
--git-dir=.jj/git config`) to manage remotes in the underlying Git
repo. That's not very discoverable (and we may change the path some
day), so let's provide a command for it.
With this change, you can do e.g. `heads(remote_branches())`. That
should currently be the same as `public_heads()`, except that we don't
yet remove public heads when remote branches have been updated. Having
this support should be generally useful, but I may use it in the short
term specifically for depending less on the public heads, until I get
around to keeping them up to date.
I also changed the instructions to use `cargo install --git` pointing
straight to GitHub, so we don't have the naming conflict with the jj
repo created in the tutorial.
As #33 says, the default diff we have can be hard to read and it
cannot be used for use with other tools. This patch adds a `jj diff
--git` mode for showing Git's flavor of unified diffs.
We should add a config option to get these diffs by default. For
interchange with other tools, we also need a way of turnning off color
codes in output (it's currently always on, even when when not printing
to a TTY).
I noticed while working on support for unified diffs (#33) that
`Diff::for_tokenizer(..., &find_line_ranges)` would return a
`DiffHunk::Matching` for each matching line instead of a single
`DiffHunk::Matching` for all the matching lines. That's different from
what you get from `Diff::default_refinement()` and seems less
convenient to work with.