Commit graph

610 commits

Author SHA1 Message Date
Martin von Zweigbergk
f877610792 merge: add Merge::num_sides()
An alternative name for it would be `arity()`, but `num_sides()`
probably more clearly says that it's not about the number of removes
or the total number of terms.
2023-08-25 08:54:49 -07:00
Martin von Zweigbergk
416fa2741c merged_tree: add entry iterator 2023-08-25 07:06:20 -07:00
Martin von Zweigbergk
85bdba5bea working_copy: use MergedTree for diffing in reset() 2023-08-25 07:06:20 -07:00
Martin von Zweigbergk
23509e939e working_copy: get diff from MergedTrees
To support tree-level conflicts, we're going to need to update the
working copy from one `MergedTree` to another. We're going need to
store multiple tree ids in the `tree_state` file. This patch gets us
closer to that by getting the diff from `MergedTree`s`, even though we
assume that they are legacy trees for now, so we can write to the
single-tree `tree_state` file.
2023-08-25 06:40:36 -07:00
Martin von Zweigbergk
d5ceefcd8e merged_tree: add diff iterator
If we're going to be able to replace most instances of `Tree` by
`MergedTree`, we'll need to be able to diff two `MergedTree`s. This
implements support for that. The implementation copies a lot from the
diff iterator we have for `Tree`. I suspect we should be able to reuse
some of the code by introducing some traits that can then be
implemented by both `Tree` and `MergedTree`. I've left a TODO about
that.
2023-08-25 06:40:36 -07:00
Martin von Zweigbergk
e1c0d4fd5f cleanup: replace x[n..n+l] by x[n..][..l]
This avoids repeating the `n` in these expressions. Thanks to
@Dr-Emann for the suggestion.
2023-08-21 22:29:46 -07:00
Martin von Zweigbergk
c43a3067eb revset: pass all context arguments to parse() via an object
`revset::parse()` already has a `RevsetWorkspaceContext` argument, so
I think it makes sense to put that and the other context arguments
into a larger `RevsetParseContext` object.
2023-08-20 21:30:06 -07:00
Martin von Zweigbergk
5f3df4aaea revset: resolve "@" symbol's workspace id earlier (while parsing)
We resolve file paths into repo-relative paths while parsing the
revset expression, so I think it's consistent to also resolve which
workspace "@" refers to while parsing it. That means we won't need the
workspace context both while parsing and while resolving symbols.

In order to break things like `author("martinvonz@")` (thanks to @yuja
for catching this), I also changed the parsing of working-copy
expressions so they are not allowed to be
quoted. `author(martinvonz@)` will therefore be an error now. That
seems like a small improvement anyway, since we have recently talked
about making `root` and `[workspace]@` not parsed as other symbols.
2023-08-20 17:57:18 -07:00
Yuya Nishihara
b6794ca04a revset: rename literal:"" prefix to exact:""
Per discussion in #2107, I believe "exact" is preferred.

We can also change the default to exact match, but it doesn't always make
sense. Exact match would be useful for branches(), but not for description().
We could define default per predicate function, but I'm pretty sure I cannot
remember which one is which.
2023-08-19 11:33:57 +09:00
Emily Fox
3f8ac2198d commits: use empty strings instead of placeholders for missing name or email
This commit replaces the functions `UserSettings::user_name_placeholder()`` and
`UserSettings::user_email_placeholder()` with `const` `&str`s to emphasize that
the placeholder strings must not be changed to support commits without
names or email addresses made before this change.
2023-08-18 17:22:59 -05:00
Benjamin Saunders
4bd05e8285 tests: hack around broken lint 2023-08-17 19:29:38 -07:00
Benjamin Saunders
417035cb20 tests: validate snapshot.max-new-file-size behavior 2023-08-17 19:29:38 -07:00
Benjamin Saunders
54f1d310c4 testutils: propagate snapshot errors 2023-08-17 19:29:38 -07:00
Yuya Nishihara
81f1ae38b3 revset: add literal:"string" pattern syntax
The syntax is slightly different from Mercurial. In Mercurial, a pattern must
be quoted like "<kind>:<needle>". In JJ, <kind> is a separate parsing node, and
it must not appear in a quoted string. This allows us to report unknown prefix
as an error.

There's another subtle behavior difference. In Mercurial, branch(unknown) is
an error, whereas our branches(literal:unknown) is resolved to an empty set.
I think erroring out doesn't make sense for JJ since branches() by default
performs substring matching, so its behavior is more like a filter.

The parser abuses DAG range syntax for now. It can be rewritten once we remove
the deprecated x:y range syntax.
2023-08-17 07:42:12 +09:00
Emily Fox
9ba9ecd708 revset: add function mine() 2023-08-16 11:00:14 -05:00
Martin von Zweigbergk
1d55a404cc merged_tree: add path_value() 2023-08-15 07:56:55 -07:00
Martin von Zweigbergk
2238c87da1 merged_tree: import create_tree() in tests to reduce line wrapping 2023-08-15 07:56:55 -07:00
Martin von Zweigbergk
0b3b62a777 conflicts: remove redundant num_removes argument from parse_conflict()
Merges always have exactly one more "adds" than "removes" these days.
2023-08-13 09:54:16 +00:00
Martin von Zweigbergk
4c46398b1c conflicts: make update_from_content() write resolved content to store
`update_from_content()` already writes file content for each term of
an unresolved merge, so it seems consistent for it to also write the
file content for resolved merges. I think this should simplify further
refactoring for tree-level conflicts and for preserving the executable
bit.
2023-08-11 23:59:44 +00:00
Martin von Zweigbergk
0b85f06e3d conflicts: make update_from_content() work with only FileIds
Since `update_from_contents()` only works with file contents and not
the executable or other kinds of paths, I think it makes more sense
for it to deal with `FileId`s instead of `TreeValue`s.
2023-08-11 23:59:44 +00:00
Martin von Zweigbergk
94c14d454a tests: levarage the materialize_conflict_string() helper in more places 2023-08-11 23:59:44 +00:00
Martin von Zweigbergk
a995c66635 merge: move some methods back to conflicts as free functions
I think I moved way too many functions onto `Merge<Option<TreeValue>>`
in 82883e648d. This effectively reverts almost all of that
commit. The `Merge<T>` type is simple container and it seems like it
should be at fairly low level in the dependency graph. By moving
functions off of it, we can get rid of the back-depdencies from the
`merge` module to the `conflict` module that I introduced when I moved
`Merge` to the `merge` module. I'm thinking the `conflict` module can
focus on materialized conflicts.
2023-08-11 21:11:25 +00:00
Yuya Nishihara
925d54614d revset: remove round-trip conversion from heads() evaluation
This wouldn't matter much in practice, but I think it's better to stick to
low-level index primitives during revset evaluation.
2023-08-12 02:16:29 +09:00
Martin von Zweigbergk
d1dbe6de98 git: propagate errors for missing commits when importing refs 2023-08-11 05:06:36 +00:00
Yuya Nishihara
530547eb9c tests: test that git::import_refs() can update conflicted remote branch
Per discussion in #2009. This behavior isn't affected by e7e49527ef "git:
ensure that remote branches never diverge", but it's subtle enough to write
a test.
2023-08-10 06:27:16 +09:00
Yuya Nishihara
552c71ed36 tests: move commit_transactions() helper to testutils 2023-08-10 06:27:16 +09:00
Martin von Zweigbergk
ef5f97f8d7 conflicts: move Merge<T> to merge module
The `merge` module now seems like the obvious place for this type.
2023-08-06 22:08:09 +00:00
Martin von Zweigbergk
ecc030848d conflicts: rename Conflict<T> to Merge<T>
Since `Conflict<T>` can also represent a non-conflict state (a single
term), `Merge<T>` seems like better name.

Thanks to @ilyagr for the suggestion in
https://github.com/martinvonz/jj/pull/1774#discussion_r1257547709

Sorry about the churn. It would have been better if I thought of this
name before I introduced `Conflict<T>`.
2023-08-06 22:08:09 +00:00
Martin von Zweigbergk
56109bda38 tests: another attempt to fix remaining flaky tests in test_view.rs
This is another commit like 0f3bd7fb03 and 8e7e32710d. I don't
know how I didn't catch all remaining instances last time :(
2023-08-04 23:36:15 +00:00
Martin von Zweigbergk
4a10ea4e3e tests: attempt to fix more flaky tests in test_view.rs
This is the same kind of fix as in 8e7e3271. I should have just fixed
all instances then.
2023-08-04 21:13:30 +00:00
Martin von Zweigbergk
48b1a1c533 working_copy: in ignored directories, visit only already tracked paths
`.gitignores` in ignored directories should be ignored. Before this
commit, we would visit ignored directories like any others if there
were any ignored paths in them.

I've done a lot of preparation for this commit, but There's still a
bit of duplication between the new code and the existing code. I don't
mind improving it if anyone has suggestions. Otherwise I might end up
doing that when I get back to working on snapshotting tree-level
conflicts soon.

This fixes #1785.
2023-08-01 06:31:52 +00:00
Martin von Zweigbergk
02f2325fae working_copy: add test for .gitignores in ignored directory
This tests the scenario that was repored in #1785.
2023-08-01 06:31:52 +00:00
Martin von Zweigbergk
aff483c431 working_copy: test changes in tracked-but-ignored directory
It's currently the same code path for handling changes to tracked
paths in ignored directories as outside ignored directories, but I'm
about to change that.

I also updated the assertion in the test to compare all entries
instead of just the tree id, so it's easier to spot errors if it
fails.
2023-08-01 06:31:52 +00:00
Yuya Nishihara
b3ae7e7657 revset_graph: preserve original parents order
It seemed awkward if merged PR is sometimes rendered as a first branch.
Instead of sorting edges in index order, let's build a HashSet only when
deduplication is needed.
2023-07-29 05:36:09 +09:00
Martin von Zweigbergk
3ef552c4c1 tests: add TestWorkspace::snapshot() to simplify snapshotting
It's currently a bit complicated to snapshot the working copy and
there's a lot of duplication in tests. This commit introduces a
function to simplify it. I made the function snapshot the working copy
and save the updated state. Some of the tests I changed previously
discarded the changes instead of saving them, but I think they all did
so because it was simpler. I left a few call sites unchanged because
they make concurrent changes.
2023-07-28 09:32:18 -07:00
Martin von Zweigbergk
2ccd3247f9 tests: remove a duplicate code block
It looks like this has been duplicated since I added the test in
cd4fbd3565.
2023-07-28 09:32:18 -07:00
Yuya Nishihara
4834d12c37 simple_op_store: serialize RefTarget in new format (breaks downgrades)
This is breaking change. Old jj binary will panic if it sees a view saved by
new jj. Alternatively, we can store both new and legacy data for backward
compatibility.
2023-07-27 15:32:48 +09:00
Martin von Zweigbergk
4348d0b487 working_copy: leverage create_tree() in test
This also lets us compare the resulting tree because the working copy
now exactly matches the tree (it used to be that the `.gitignore` file
wasn't initially snapshotted).
2023-07-26 23:30:10 -07:00
Martin von Zweigbergk
84a60d15bc op_store: make ViewId and OperationId implement ObjectId 2023-07-26 14:17:21 -07:00
Waleed Khan
70d3c64b1e operation: propagate OpStoreError
This is a rote propagation of the error value to hopefully improve the panic in https://github.com/martinvonz/jj/issues/1907.
2023-07-25 12:46:59 -05:00
Martin von Zweigbergk
8d1cb1e1d7 working_copy: add test of racy checkout followed by file write
We don't seem to have any tests that our protection from undetected
changes caused by writes happening right after checkout, so let's add
one. The test case loops 100 times and each iteration fails slightly
more than 80% of the time on my machine (if I remove the protection in
`TreeState::update_file_state()`), so it seems quite good at
triggering the race.
2023-07-24 16:41:44 -07:00
Martin von Zweigbergk
e364c49854 test_working_copy_concurrent: run only with git backend
I don't see any reason for these tests to differ depending on backend,
so let's avoid running them twice (there are probably lots of other
tests that we're also running with different backends for little
reason).
2023-07-24 16:41:44 -07:00
Yuya Nishihara
e2f9ed439e revset: extract graph-related types to separate module
I'm going to add a topo-grouping iterator adapter, and the revset module is
already big enough to split.
2023-07-25 01:45:37 +09:00
Yuya Nishihara
2bbaa4352a refs: rename RefTarget::is_conflict() to has_conflict()
Copied from MergedTree::has_conflict(). I feel it's slightly better since
RefTarget "is" always a Conflict-based type. It could be inverted to
RefTarget::is_resolved(), but refs are usually resolved, and all callers
have special case for !is_resolved() state.
2023-07-23 22:25:57 +09:00
Martin von Zweigbergk
deb4ae476d merged_tree: add an iterator over conflicts
With `MergedTree`, we can iterate over conflicts by descending into
only the subdirectories that cannot be trivially resolved. We assume
that the trees have previously been resolved as much as possible, so
we don't attempt to resolve conflicts again.
2023-07-19 22:04:16 -07:00
Martin von Zweigbergk
828d528361 merged_tree: add a function for resolving conflicts
This adds a function for resolving conflicts that can be automatically
resolved, i.e. like our current `merge_trees()` function. However, the
new function is written to merge an arbitrary number of trees and, in
case of unresolvable conflicts, to produce a `Conflict<TreeId>` as
result instead of writing path-level conflicts to the backend. Like
`merge_trees()`, it still leaves conflicts unresolved at the file
level if any hunks conflict, and it resolves paths that can be
trivially resolved even if there are other paths that do conflict.
2023-07-19 22:04:16 -07:00
Martin von Zweigbergk
4f30417ffd merged_tree: introduce a type for a set of trees to merge on the fly
In order to store conflicts in the commit, as conflicts between a set
of trees, we want to be able merge those trees on the fly. This
introduces a type for that. It has a `Merge(Conflict(Tree))` variant,
where the individual trees cannot have path-level conflicts. It also
has a `Legacy(Tree)` variant, which does allow path-level conflicts. I
think that should help us with the migration.
2023-07-19 22:04:16 -07:00
Yuya Nishihara
84f0c96c8f view: replace .tags().get(name) with .get_tag(name) 2023-07-19 08:27:42 +09:00
Yuya Nishihara
bf46eb5ad2 view: replace .branches().get(name) with .get_branch(name) 2023-07-19 08:27:42 +09:00
Yuya Nishihara
ecb0850f1a view: return RefTarget by reference, clone() by caller 2023-07-19 08:27:42 +09:00