64 Commits

Author SHA1 Message Date
Martin von Zweigbergk
f32b67ac3d tree: leverage Conflict::flatten() etc 2023-06-30 14:43:58 +02:00
Martin von Zweigbergk
24c0190f74 conflicts: rename try_map() to maybe_map()
I'm going to add a `Result` version and it makes more sense to call
that `try_map()`.
2023-06-30 14:43:58 +02:00
Martin von Zweigbergk
6bd13382f4 backend: add a function for setting or removing a tree entry 2023-06-30 14:43:58 +02:00
Martin von Zweigbergk
c0ffce781e store: cache tree on write and return it
This matches what we do when writing commits.
2023-06-30 14:12:36 +02:00
Martin von Zweigbergk
35e4d5f205 conflicts: add take(), returning the removes and adds Vecs 2023-06-27 21:06:32 +02:00
Martin von Zweigbergk
b1f2e80349 files: add a newtype around Vec<u8> for content hunks
It's useful to have a more readable `Debug` format for `Vec<u8>`
(`"foo"` is better than `[102, 111, 111]`). It might also make types
in function signatures and elsewhere more readable.
2023-06-27 21:06:32 +02:00
Martin von Zweigbergk
b8221d4e21 conflicts: add try_map() method
This simplifies `to_file_conflict()` and `try_resolve_file_conflict()`
a bit.
2023-06-26 13:47:33 +02:00
Martin von Zweigbergk
9c486ebe45 conflicts: add a method returning the resolved value, if resolved 2023-06-26 13:47:33 +02:00
Yuya Nishihara
55f93bfa04 tree: reuse caller-provided path in known_sub_tree(), mark it as private 2023-06-15 00:45:07 +09:00
Yuya Nishihara
db7facb78e tree: rewrite sub_tree_recursive() to not use known_sub_tree()
This is the only place where the caller of known_sub_tree() doesn't know
the full repo path.
2023-06-15 00:45:07 +09:00
Martin von Zweigbergk
02bb3aecf3 tree: don't read file contents on contents/executable "conflict"
If one side changes the contents and one side changes the executable
bit, we get a non-trivial conflict in the `TreeValue`s, but once we've
split them up into `FileId`s and bools, we can trivially resolve them
separately, without having to read file contents.
2023-06-13 08:49:46 +02:00
Martin von Zweigbergk
6e6ca16fd4 tree: make try_resolve_file_conflict() write resolved file to store
The function takes a `&Conflict<Option<TreeValue>>` argument so it
seems it should return an `Option<TreeValue>` for symmetry.
2023-06-13 08:49:46 +02:00
Martin von Zweigbergk
1f1c6867c7 conflicts: add a simplify() method, taken from tree.rs
It seems generally useful to be able to simplify a conflict, and it's
not specific to merging trees, so let's move it to
`conflicts.rs`. Once we're done with the migration to tree-level
conflicts, I think `Conflict::simplify()` will remain but
`tree::simplify_conflict()` will be gone.

The tests I added there are quite similar to those of
`trivial_merge()`. I hope we can make `Conflict::simplify()` call
`trivial_merge()` later. I think it would also make sense to move
`trivial_merge()` onto `Conflict`, or at least have a
`Conflict::resolve_trivial()` calling `trivial_merge()`.
2023-06-13 08:49:46 +02:00
Martin von Zweigbergk
e5a28996b4 tree: specialize and inline tree_value_to_conflict()
It seems that this function didn't serve the purpose I intended it to;
we only passed in `TreeValue::Conflict` variants to it.
2023-06-13 08:49:46 +02:00
Martin von Zweigbergk
ee98d1eee8 tree: remove check for conflict-simplification resulting in deletion
Since we switched to the new `conflicts::Conflict` type, we represent
a missing tree entry by a `None` value in the conflict, not a missing
"add", so the condition removed in this commit will never happen, and
the case will be handled by the case just below it instead.
2023-06-13 08:49:46 +02:00
Martin von Zweigbergk
29b676f24f store: do conversion to/from backend::Conflict
We now convert to/from `backend::Conflict` right before/after calling
the `Store` methods, so we can simplify by having the `Store` do the
conversion.
2023-06-04 06:48:34 -07:00
Martin von Zweigbergk
43c55fcbc9 tree: replace uses of backend::Conflict 2023-06-04 06:48:34 -07:00
Martin von Zweigbergk
a5883eba15 merge: make trivial_merge() return a reference
I don't know why I made it return an owned value. It seems like an
unnecessary restriction that the value implements `Clone`, so let's
return a reference instead.
2023-05-31 06:28:01 -07:00
Martin von Zweigbergk
d047a8fbd4 tree: respect matcher.visit() when walking entries
This handles the basic case of where the matcher says that a whole
subtree is not matched. In the Linux repo, That's already enough to
speed up `jj --ignore-working-copy files samples` from 298 ms to 129
ms.
2023-05-28 07:28:16 -07:00
Martin von Zweigbergk
dbcecf7244 tree: rewrite recursive entries iterator to not use machine stack
In the same vein as c02c4168fe2f.
2023-05-28 07:28:16 -07:00
Martin von Zweigbergk
97c64d8071 tree: leverage trivial_merge() for file executable bit 2023-05-24 22:00:38 -07:00
Martin von Zweigbergk
451af92912 tree: leverage trivial_merge() in merge_trees() 2023-05-24 22:00:38 -07:00
Yuya Nishihara
770ea0c705 tree: rewrite recursive diff iterator to not use machine stack
While mutable borrow in the next() method is a bit tricky, I think it's
easier to follow than invoking iterators recursively.
2023-05-06 14:50:37 +09:00
Yuya Nishihara
a8f77e46a9 tree: extract helper method that sets up subdir iterator
This will be reimplemented as a constructor of subdir item.
2023-05-06 14:50:37 +09:00
Yuya Nishihara
3f7b0929d7 tree: make internal TreeEntryDiffIterator yield all values by reference
This isn't important, but I feel it's a bit inconsistent that name is cloned
by callee, but tree values aren't.
2023-05-06 14:50:37 +09:00
Martin von Zweigbergk
cd0023e796 tree: if matcher says that tree should be skipped, skip it
When using a sparse working copy (e.g. with no files at all) and
updating the working copy from the root commit to a commit with
millions of files, we shouldn't have to walk the parts of the diff
that doesn't match the sparse patterns. However, we still do the full
walk because our `Tree::diff()` currently doesn't care about what the
matcher tells us to visit, it only filters out unwanted files after
visiting them. This commit fixes that for the special (but common)
case of matching nothing in a directory.

I tried also adding special handling for when the matcher says that we
should only visit a few entries, but it wasn't clearly better in the
cases I tested it on. I'll keep that patch around and might send it if
I find some cases where it helps.
2023-05-03 18:21:51 -07:00
Martin von Zweigbergk
92f9fe5a1b tree: make conflict_term_to_conflict() take a TreeValue
The function only needs the `TreeValue` so it makes more sense this
way, I think. That will also let the caller keep the rest of the
`Conflict` value owned (though there is nothing but the `value` field
in it right now).
2023-02-18 00:09:51 -08:00
Martin von Zweigbergk
cf672de792 tree: avoid some cloning by passing by value 2023-02-18 00:09:51 -08:00
Martin von Zweigbergk
a87125d08b backend: rename ConflictPart to ConflictTerm
It took a while before I realized that conflicts could be modeled as
simple algebraic expressions with positive and negative terms (they
were modeled as recursive 3-way conflicts initially). We've been
thinking of them that way for a while now, so let's make the
`ConflictPart` name match that model.
2023-02-17 23:28:50 -08:00
Martin von Zweigbergk
7f334656b1 tree: return early when trying to resolve modify/delete conflict
Modify/delete conflicts cannot be automatically resolved, so there's
no point in wasting resources calculating the diff(s).
2023-02-17 22:05:44 -08:00
Waleed Khan
7f8a196ab2 backend: create ObjectId trait
This lets us operate over various kinds of objects polymorphically (e.g. call `.hex()` on any kind of object hash).
2023-01-02 12:28:51 -06:00
Yuya Nishihara
ffbd6eb945 tree: ensure Tree outlives its iterator on dropping self-referential struct
Just for sanity. It wouldn't matter unless the iterator implements Drop.

https://doc.rust-lang.org/reference/destructors.html
2022-12-15 01:51:25 +09:00
Ilya Grigoriev
acb0e9751d Add a Tree method to return conflicts matching a matcher
This is useful for `jj resolve`.
2022-12-04 22:39:45 -08:00
Martin von Zweigbergk
d8feed9be4 copyright: change from "Google LLC" to "The Jujutsu Authors"
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.
2022-11-28 06:05:45 -10:00
Martin von Zweigbergk
780d7fb59c backend: rename NormalFile to just File
There are no "non-normal" files, so "normal" is not needed. We have
symlinks and conflicts, but they are not files, so I think just "file"
is unambiguous.

I left `testutils::write_normal_file()` because there it's used to
mean "not executable file" (there's also a `write_executable_file()`).

I left `working_copy::FileType::Normal` since renaming `Normal` there
to `File` would also suggest we should rename `FileType`, and I don't
know what would be a better name for that type.
2022-11-14 23:36:43 -08:00
Martin von Zweigbergk
e4f83e353e errors: use custom error for failed tree merge
Tree merges can currently fail because of a failure to look up an
object, or because of a failure to read its contents. Both results in
`BackendError` because of a `impl From<std::io::Error> for
BackendError`. That's kind of correct in this case, but it wasn't
intentional (that impl was from `local_backend`), and we need to
making errors more specific for better error handling.
2022-05-03 06:52:00 -07:00
Martin von Zweigbergk
99d2ef8883 cleanup: simplify some uses of Option, mostly by using ? 2022-04-25 13:09:24 -07:00
Martin von Zweigbergk
762c8984c6 trees: when merging trees and one is missing, treat it as empty
When a directory is missing in one merge input (base or one side), we
would consider that a merge conflict. This patch changes that so we
instead merge trees by treating the missing tree as empty.
2022-04-20 13:47:03 -07:00
Martin von Zweigbergk
f16d2a237b backend: pass in path when reading/writing conflicts as well
We do it for all the other kinds of objects already. It's useful to
have the path for backends that store objects by path (we don't have
any such backends yet). I think the reason I didn't do it from the
beginning was because we had separate `RepoPath` types for files and
directories back then.
2022-03-31 10:23:33 -07:00
Martin von Zweigbergk
41860692e9 trees: pass a matcher to the entry iterator 2021-11-14 22:00:46 -08:00
Martin von Zweigbergk
f2d5aa188d tree: refactor TreeEntriesIterator to look like TreeDiffIterator
Consistency is better, and I think this will make it a little easier
to add support for restricting the iterator by a `Matcher`.
2021-11-14 21:50:10 -08:00
Martin von Zweigbergk
e5dd93cbf7 cleanup: make Vec inside CommitId etc. non-public 2021-11-10 10:46:10 -08:00
Martin von Zweigbergk
c0ae4b16e8 trees: try to resolve file conflicts after simplifying conflicts
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.
2021-10-22 09:20:50 -07:00
Martin von Zweigbergk
f1e2124a64 trees: make simplify_conflict() always return a Conflict
The interface is much cleaner this way. The function no longer makes
any writes to the store.
2021-10-20 22:07:42 -07:00
Martin von Zweigbergk
0c1ce664ea store: remove (weak) self-reference and take &Arc<Self> arguments instead
The `weak_self` stuff was from before I knew that `self` could be of
type `&Arc<Self>`.
2021-09-16 23:30:30 -07:00
Martin von Zweigbergk
ce5e95fa80 store: rename Store to Backend and StoreWrapper to Store
For what's currently called `Store` in the code, I have been using
"backend" in plain text. That probably means that `Backend` is a good
name for it.
2021-09-12 12:02:10 -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
4c416dd864 cleanup: let Clippy fix a bunch of warnings 2021-06-14 00:27:31 -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