Commit graph

347 commits

Author SHA1 Message Date
Martin von Zweigbergk
aeab6660d9 revsets: add branches() and tags() functions
The `branches()` function resolves to all "adds" on both local and
remote branches.
2021-08-04 12:03:13 -07:00
Martin von Zweigbergk
7fad705062 revsets: add support for resolving symbols as tags and branches
This adds support for resolving tags and branches in revsets. Branches
and tags can be resolved by specifying their name (e.g. "main"). To
specify a branch's target on a remote, use e.g. "main@origin". In case
of conflicts, they get resolved to their "adds".
2021-08-04 11:42:03 -07:00
Martin von Zweigbergk
8738421990 git: update own branch and tag records based on git refs
Now that we have our own representation of branches and tags, let's
update them when we import git refs. The View object's git refs are
now just a record of what the refs are in the underlying git ref last
time we imported them (we don't -- and won't -- provide a way for the
user to update our record of the git refs). We can therefore do a nice
3-way ref-merge using the `refs` module we added recently. That means
that we'll detect conflicts caused by changes made concurrently in the
underlying git repo and in jj's view.
2021-08-04 11:39:07 -07:00
Martin von Zweigbergk
044f23bc33 view: add support for ref-based branches and tags to model
I've finally decided to copy Git's branching model (issue #21), except
that I'm letting the name identify the branch across
remotes. Actually, now that I think about, that makes them more like
Mercurial's "bookmarks". Each branch will record the commit it points
to locally, as well as the commits it points to on each remote (as far
as the repo knows, of course). Those records are effectively the same
thing as Git's "remote-tracking branches"; the difference is that we
consider them the same branch. Consequently, when you pull a new
branch from a remote, we'll create that branch locally.

For example, if you pull branch "main" from a remote called "origin",
that will result in a local branch called "main", and also a record of
the position on the remote, which we'll show as "main@origin" in the
CLI (not part of this commit). If you then update the branch locally
and also pull a new target for it from "origin", the local "main"
branch will be divergent. I plan to make it so that pushing "main"
will update the remote's "main" iff it was currently at "main@origin"
(i.e. like using Git's `git push --force-with-lease`).

This commit adds a place to store information about branches in the
view model. The existing git_refs field will be used as input for the
branch information. For example, we can use it to tell if
"refs/heads/main" has changed and how it has changed. We will then use
that ref diff to update our own record of the "main" branch. That will
come later. In order to let git_refs take a back seat, I've also added
tags (like Git's lightweight tags) to the model in this commit.

I haven't ruled out *also* having some more persistent type of
branches (like Mercurials branches or topics).
2021-08-04 11:33:57 -07:00
Martin von Zweigbergk
b1e60b37ea view: add tests of merging views
I'm about to add some support for branches and tags (for issue #21)
and it seems that we didn't have explicit testing of merging of
views. There was `test_import_refs_merge()` in `test_git.rs` but
that's specifically for git refs. It seems that it's made obsolete by
the tests added by this commit, so I'm removing it.
2021-08-04 11:33:57 -07:00
Martin von Zweigbergk
9fb3521bf5 view: rename insert_git_ref() to set_git_ref()
I just feel like `set_git_ref()` is a more natural name (I was looking
for it the other day before I realized I had called it
`insert_git_ref()`).
2021-08-04 08:45:37 -07:00
Martin von Zweigbergk
2650681117 tests: randomize commit messages in test_git
I had previously created commit messages based only on the ref name,
which meant that `commit4` and `commit5` ended up being the same
commit. This fixes that problem.
2021-08-01 21:26:26 -07:00
Martin von Zweigbergk
7511b02da8 simple_op_store: add some tests
I'm about to start branches and tags in the view and we didn't have
any tests of the store itself (only via higher-level tests).
2021-07-31 19:49:30 -07:00
Martin von Zweigbergk
38032b0132 cleanup: commit transactions in tests when it's simpler
There were some tests that discarded a transaction only because it
used to be easier to do that than to commit and reload the repo. We
get the new repo back when we commit the transaction these days, so
now it's often easier to commit the transaction instead.
2021-07-30 17:47:00 -07:00
Martin von Zweigbergk
6b1ccd4512 view: add support for merging git ref targets
When there are two concurrent operations, we would resolve conflicting
updates of git refs quite arbitrarily before this change. This change
introduces a new `refs` module with a function for doing a 3-way merge
of ref targets. For example, if both sides moved a ref forward but by
different amounts, we pick the descendant-most target. If we can't
resolve it, we leave it as a conflict. That's fine to do for git refs
because they can be resolved by simply running `jj git refresh` to
import refs again (the underlying git repo is the source of truth).

As with the previous change, I'm doing this now because mostly because
it is a good stepping stone towards branch support (issue #21). We'll
soon use the same 3-way merging for updating the local branch
definition (once we add that) when a branch changes in the git repo or
on a remote.
2021-07-24 19:01:56 -07:00
Martin von Zweigbergk
0aa738a518 view: add support for conflicting git refs in the model
This adds support for having conflicting git refs in the view, but we
never create conflicts yet. The `git_refs()` revset includes all "add"
sides of any conflicts. Similarly `origin/main` (for example) resolves
to all "adds" if it's conflicted (meaning that `jj co origin/main` and
many other commands will error out if `origin/main` is
conflicted). The `git_refs` template renders the reference for all
"adds" and adds a "?" as suffix for conflicted refs.

The reason I'm adding this now is not because it's high priority on
its own (it's likely extremely uncommon to run two concurrent `jj git
refresh` and *also* update refs in the underlying git repo at the same
time) but because it's a building block for the branch support I've
planned (issue #21).
2021-07-24 19:01:56 -07:00
Martin von Zweigbergk
a14114256e cleanup: propagate some errors up when failing to write to file 2021-07-24 10:49:32 -07:00
Martin von Zweigbergk
d6a1f9848a cleanup: add explicit import of assert_matches, as required by new rustc 2021-07-24 10:48:52 -07:00
Martin von Zweigbergk
1a4d9d5644 evolution: don't create merge commits with one parent ancestor of another 2021-07-02 23:49:36 -07:00
Martin von Zweigbergk
443528159e conflicts: use new multi-way diff for materialized multi-way conflicts
This copies the conflict marker format I added a while ago to
Mercurial (https://phab.mercurial-scm.org/D9551), except that it uses
`+++++++` instead of `=======` for sections that are pure adds. The
reason I made that change is because we also have support for pure
removes (Mercurial never ends up in that situation because it has
exactly one remove and two adds).

This change resolves part of issue #19.
2021-06-30 12:29:20 -07:00
Martin von Zweigbergk
1390a044e7 files: make merge() accept any number of removes and adds as input 2021-06-30 12:09:36 -07:00
Martin von Zweigbergk
f8c016a8ea files: make MergeHunk support any number of removes and adds
I think `files::merge()` will be a useful place to share code for
resolving conflicting hunks after all. We'll want `MergeHunk` to
support multi-way merges then.
2021-06-30 09:55:16 -07:00
Martin von Zweigbergk
c93e806265 conflicts: make materialized tree/file conflicts etc a little more useful
When there are conflicts between different types of tree entries, we
currently materialize them as "Unresolved complex conflict.". This
change makes it so we mention what types were involved and what their
ids were (though we still don't have an easy way of resolving an id).
2021-06-29 10:49:15 -07:00
Martin von Zweigbergk
720677c7f3 cargo: update test-case to 1.2.0 now that frondeus/test-case#66 is fixed 2021-06-28 12:13:14 -07:00
Martin von Zweigbergk
7effefa802 files: rewrite 3-way content merge using new multi-way diff 2021-06-26 23:49:58 -07:00
Martin von Zweigbergk
81b51de300 diff: rewrite diff() using new multi-way diff 2021-06-26 23:49:58 -07:00
Martin von Zweigbergk
9448fe665a files: use diff::DiffHunk in DiffLine definition
The new `diff::DiffHunk` type is very similar but more generic. We
don't need the generality here. I just don't two very similar types
with the same name.
2021-06-26 23:49:58 -07:00
Martin von Zweigbergk
987aecc749 diff: add a type for diffing arbitrary number of inputs
I have been trying to figure out how to generalize diffs and merges
for arbitrary number of inputs. For example, I want to have an
internal representation of an octopus merge adding 5 inputs (file
states/contents) and removing 4 inputs. I also want to be to represent
a diff from a regular 3-way-conflict state to a resolved state. Such a
diff would be from a state adding two inputs and removing one, to a
state adding just one input.

I finally realized last week that the problem is simple if you don't
care about adds vs removes. Instead, you line up the matching and
differing parts of all the inputs. It's then up to the caller to use
it in an appropriate way for its use case. For example, a regular diff
would pass in two inputs and would get back a list of matching and
dffering hunks. It might then present the first element of differing
hunks in red and the second element in green. Similarly, a 3-way merge
would pass in three inputs with the base first. It would then compare
the sides and decide on a resolution (or leave it unresolved if all
three sides are different).

This change adds a type representing this kind of multi-way
diff. Coming changes will update existing code to use it. In addition
to making the existing code simpler and more consistent, having this
in place should also:

 * Make it much easier to present merge conflicts involving more than
   3 parts.

 * Experiment with different ways of displaying diffs from/to conflict
   states.

 * Experiment with sub-line-level merging.
2021-06-26 23:49:58 -07:00
Martin von Zweigbergk
f2100ed533 cargo: point test-case dependency to my fork
This is work around frondeus/test-case#66 until my pull request (or
other fix) gets accepted.
2021-06-23 17:07:51 -07:00
Martin von Zweigbergk
7360589246 working_copy: consider it an error if temp file cannot be renamed to target
Unlike the other places I fixed in 134940d2bb, the calls in
`working_copy.rs` should not simply use an existing file if the target
file was open. They should probably try again instead, but I'll leave
that for later.
2021-06-16 10:52:55 -07:00
Martin von Zweigbergk
4c416dd864 cleanup: let Clippy fix a bunch of warnings 2021-06-14 00:27:31 -07:00
Martin von Zweigbergk
134940d2bb windows: don't fail when concurrent threads/processes fail to rename file
On Windows, it seems that you can't rename a file if the target file
is open (Stebalien/tempfile#131). I think that's the reason for our
failing tests on Windows. This patch adds a simple wrapper around
`NamedTempFile::persist()` that returns the existing file instead of
failing, if there is one.
2021-06-14 00:09:22 -07:00
Martin von Zweigbergk
f26c9f01ce working_copy: silence some warnings about unused code on Windows 2021-06-13 22:34:33 -07:00
Martin von Zweigbergk
06cd688181 tests: enable concurrent commit tests on Windows
I don't know why these used to fail. Perhaps it was just that the
GitHub's Windows machines were not powerful to run them with 100
threads doing concurrent commits. Maybe they will pass now that we
limit the number of threads to the number of CPUs. This change enables
the tests so we can see what GitHub CI thinks.
2021-06-13 22:02:42 -07:00
Martin von Zweigbergk
408b0dc1d8 tests: enable test of file type transactions on Windows, only skip symlinks
I think all types but symlinks should work on Windows. Let's see if
GitHub CI agrees (I don't have access to a Windows machine).
2021-06-13 21:52:16 -07:00
Martin von Zweigbergk
1ac72b9807 cli: rewrite jj restore <path> to use a matcher created from arguments 2021-06-09 16:45:30 -07:00
Martin von Zweigbergk
dd4c47f373 tree: support filtering diff by matcher
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.
2021-06-09 16:26:58 -07:00
Martin von Zweigbergk
b593e552b8 cleanup: remove some Vec<_> annotations, mostly by using collect_vec() 2021-06-09 14:21:57 -07:00
Martin von Zweigbergk
0ce50e137a store: use RepoPathComponent in Tree 2021-06-05 23:36:38 -07:00
Martin von Zweigbergk
6b609a8a9f tree: use RepoPathComponent in merge_tree_value() 2021-06-05 23:01:23 -07:00
Martin von Zweigbergk
5ece748dff tree: make TreeEntryDiffIterator use RepoPathComponent 2021-06-05 22:57:57 -07:00
Martin von Zweigbergk
ac38c8b641 repo_path: rename value() to clearer as_str() 2021-06-05 22:49:52 -07:00
Martin von Zweigbergk
fdeb499836 trees: merge into tree module 2021-06-05 14:20:07 -07:00
Martin von Zweigbergk
61ffa66fb5 view: move merge_views() onto View 2021-06-05 14:08:04 -07:00
Martin von Zweigbergk
ac2530637a view: merge ReadonlyView and MutableView into a single View
The two types have become very similar so it doesn't seem that there's
any point in having two types. We should probably do the same with
`ReadonlyEvolution` and `MutableEvolution`.
2021-06-05 14:08:04 -07:00
Martin von Zweigbergk
f722e8662f revsets: replace while loop by for loop, as pointed out by clippy 2021-06-05 09:10:04 -07:00
Martin von Zweigbergk
b50ef1410d styler: rename Styler to more standard Formatter 2021-06-05 08:38:28 -07:00
Martin von Zweigbergk
f6a9523b75 revsets: resolve symbol as change id if nothing else matches
This patch makes it so we attempt to resolve a symbol as the
non-obsolete commits in a change id if all other resolutions
fail.

This addresses issue #15. I decided to not require any operator for
looking up by change id. I want to make it as easy as possible to use
change ids instead of commit ids to see how well it works to interact
mostly with change ids instead of commit ids (I'll try to test that by
using it myself).
2021-05-31 08:32:10 -07:00
Martin von Zweigbergk
ca1df00e05 git: make change id the reverse bits of commit id
The fact that the default change id in git repos is currently a prefix
of the commit id makes it impossible to use for resolving a prefix of
the change id to commits. This patch addresses that by reversing the
bits of the change id (relative to the commit id). The next patch will
make it so a change id (or a prefix thereof) is a valid revset.
2021-05-30 22:10:02 -07:00
Martin von Zweigbergk
c7f701fddb revsets: make resolve_symbol() return multiple revisions
I'd like to experiment with mostly using change ids instead of commit
ids on the CLI. Then it needs to be easy to refer to the non-obsolete
commits in a change, which means we probably don't want to require any
operators (i.e. a plain change id should resolve to the non-obsolete
commits in the change). This patch prepares for letting a change id
resolve to (possibly) many commits.
2021-05-30 13:39:24 -07:00
Martin von Zweigbergk
a3cb0ee3d1 index: add a type parameter to PrefixResolution to prepare for ChangeId prefix 2021-05-30 10:24:35 -07:00
Martin von Zweigbergk
0d9d141705 revsets: refactor symbol lookup to prepare for trying to look up change id 2021-05-29 23:48:48 -07:00
Martin von Zweigbergk
e658cc0084 revsets: add a RevsetExpression::evaluate() method for convenience 2021-05-28 09:01:34 -07:00
Martin von Zweigbergk
c4e2e6b598 revsets: remove unnecessary lifetime parameter 2021-05-28 08:58:44 -07:00
Martin von Zweigbergk
ba8ff31e32 cli: make the working copy changes in jj status clearer 2021-05-23 22:08:34 -07:00