Commit graph

143 commits

Author SHA1 Message Date
Scott Taylor
5aa71d59a9 lib: replace MergedTreeId with MergedTree and Merge<TreeId>
After the previous commit, `MergedTree` and `MergedTreeId` are almost
identical, with the only difference being that `MergedTree` is attached
to a `Store` instance. `MergedTreeId` is also equivalent to
`Merge<TreeId>`, since it is just a wrapper around it.

In the future, `MergedTree` might contain additional metadata like
conflict labels. Therefore, I replaced `MergedTreeId` with `MergedTree`
wherever I think it would be required to pass this additional metadata,
or where the additional methods provided by `MergedTree` would be
useful. In any remaining places, I replaced it with `Merge<TreeId>`.

I also renamed some of the `tree_id()` methods to `tree_ids()` for
consistency, since now they return a merge of individual tree IDs
instead of a single "merged tree ID". Similarly, `MergedTree` no longer
has an `id()` method, since tree IDs won't fully identify a `MergedTree`
once it contains additional metadata.
2025-11-08 14:06:58 +00:00
Scott Taylor
79fc20e856 merged_tree: use Merge<TreeId> instead of Merge<Tree>
Currently, creating a `MergedTree` requires reading all of its root
trees from the store. However, this is often not actually required. For
instance, if the only reason to read the trees is to call
`MergedTree::merge`, and the merge is trivial, then there was no need to
read the trees. Changing `MergedTree` to only require a `Merge<TreeId>`
instead of a `Merge<Tree>` will make it possible to avoid reading trees
unnecessarily in these cases.

One benefit of this approach is that `Commit::tree` no longer requires
reading from the store, so it can be made synchronous and infallible,
which simplifies a lot of code.
2025-11-08 14:06:58 +00:00
Martin von Zweigbergk
b62438e398 repo: propagate error when there's a cycle in parent_mapping
We were sometimes seeing crashes at Google when a commit was rewritten
very quickly without any changes. This should prevent the crashes and
return an error to the user instead.
2025-10-27 14:16:34 +00:00
Yuya Nishihara
c7ffb5d42a view: rename remaining local "tag" functions 2025-09-30 13:51:40 +00:00
Martin von Zweigbergk
2e8d23739d rewrite: make merge_commit_trees_no_resolve_without_repo() non-recursive
We ran into the following error when upgrading to the latest unstable
rustc at Google when compiling our internal commit backend:

```
overflow evaluating the requirement `impl futures::Future<Output = Result<jj_lib::tree::Tree, jj_lib::backend::BackendError>>: Sized`
```

It seems to be some limitation of rustc related to recursion and async
functions but we don't know what exactly it means.

This patch works around that by making the async part of
`merge_commit_trees_no_resolve_without_repo()` non-recursive. There is
still a recursive part, but it's no longer async. The recursive part
now finds all the commit IDs involved. Then we do the lookup of them
afterwards.

We may want to make the remaining recursive part non-recursive as well
so don't run out of stack on a long braid of criss-cross merges, but
that can come later.
2025-08-20 13:58:10 +00:00
Martin von Zweigbergk
353be90e3d rewrite: add test of recursive criss-cross merge resolution
We didn't seem to have a test case of the recursive merge
implementation (no tests failed when I changed it to always use the
first ancestor instead of being recursive).
2025-08-20 13:58:10 +00:00
Martin von Zweigbergk
28562f1b10 tests: remove CommitGraphBuilder
The `CommitGraphBuilder` type doesn't seem to carry its weight
anymore.
2025-07-31 04:56:34 +00:00
Martin von Zweigbergk
ca6edfaab0 tests: add a helper for writing random commit with given parents 2025-07-31 04:56:34 +00:00
Martin von Zweigbergk
592df6a28b tests: leverage write_random_commit() in a few more places 2025-07-31 04:56:34 +00:00
Austin Seipp
ba24140f1d cli, lib: move to Rust 2024 language edition
This applies a `cargo fmt` and fixes clippy lints to keep the build
properly working.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2025-07-28 17:05:41 +00:00
Pablo Brasero
585a7426f5 everything: ensure consistent spelling of "behavior" 2025-07-28 16:19:31 +00:00
Ilya Grigoriev
6323764f69 lib: add rustversion, turn off a clippy lint in nightly in tests
This turns off the `clippy::cloned_ref_to_slice_refs` lint in some tests
and fixes it in others, for Rust 1.89+. This seems to make `cargo clippy
--workspace --all-targets --all-features` work in stable, beta, and
nightly (1.89).

This depends on the `rustversion` crate. Other than that, it's based on
Austin's https://github.com/jj-vcs/jj/pull/6705.

Co-authored-by:  Austin Seipp <aseipp@pobox.com>
2025-06-24 01:01:25 +00:00
Martin von Zweigbergk
5ae5f9f75d async: avoid some async blocks by making whole functions async
This reduces indentation and makes it easier to add more async calls
to the functions.
2025-06-10 20:19:47 +00:00
Jonas Greitemann
9c165d6db3 tests: supplement create_tree() with a builder-style API
The original form of `create_tree()` is limited to creating (valid
UTF-8) text files but cannot create binary files, executable
files, or symlinks. Dedicated helpers like `write_executable_file()` or
`write_symlink()` partially compensated for this, but required manually
assembling the tree in the test code.

This commit introduces `TestTreeBuilder` which provides an API to
successively add entries to a tree which can represent all of the above.
`TestTreeBuilder` can then create either a single `Tree`, or a resolved
`MergedTree`.

In addition to using `TestTreeBuilder` directly, `create_tree_with()`
and `create_single_tree_with()` accept a closure which receives a
`TestTreeBuilder`. This allows test code to quickly describe the tree
without requiring the a named builder at caller scope. Riffing off
the familiar function names should help in discovering the new builder
facilities. However, it is completely possible to use `TestTreeBuilder`
directly, if preferred.
2025-06-02 17:40:26 +00:00
Scott Taylor
c406b3a929 rebase: skip duplicate divergent commits by default
This serves a similar purpose to Git's patch ID mechanism, however it is
slightly different in that it only compares commits which have the same
change ID as each other (divergent changes), and it does a full
comparison of the commits to see if they would have identical trees if
rebased onto the same parents. Since most changes aren't divergent, I
believe this should have a negligible performance cost in most cases.

I think skipping these commits by default makes sense for `jj rebase`,
since usually this will be a helpful behavior for the user. With this
behavior, a safe first step when encountering divergent changes would be
to rebase one branch on top of the other, since that will abandon any
divergent changes that have identical contents to existing commits,
leaving behind any non-trivial divergent changes for the user to resolve
manually.
2025-05-19 22:23:32 +00:00
Martin von Zweigbergk
f0545ee25c test: introduce test helpers for creating repo path types
I'm about to make the constructors return a `Result`. The helpers will
hide the unwrapping.
2025-04-15 14:42:23 +00:00
Yuya Nishihara
3f5f872204 view: rename workspace "id" to "name"
This matches the current implementation.
2025-03-31 03:39:29 +00:00
Yuya Nishihara
e66c545438 view: replace WorkspaceId by string-like newtypes
I think this makes more sense because WorkspaceId is currently a human-readable
name. In error/status messages, workspace names are now printed in revset
syntax.

New WorkspaceId types do not implement Default. It would be weird if string-like
type had non-empty Default::default(). The DEFAULT constant is provided instead.
2025-03-31 03:39:29 +00:00
Yuya Nishihara
f87db58617 view: rename RemoteRefState::Tracking to Tracked
In jj's model, a local bookmark "tracks" remote bookmarks. It's wrong to call
a remote bookmark state as "tracking".
2025-03-31 01:41:31 +00:00
Yuya Nishihara
02722eae54 view: port bookmark/tag name types to RefName/RemoteName
I tried to minimize this patch, but it seemed rather complicated than porting
most callers all at once. Remote management functions in git.rs are unchanged.
They'll be ported separately.

With this change, many non-template bookmark/remote name outputs should be
rendered in revset syntax.
2025-03-26 11:07:06 +00:00
Yuya Nishihara
cc8a80c548 ref_name: move RemoteRefSymbol types from refs module 2025-03-26 11:07:06 +00:00
Ilya Grigoriev
acaedc3382 cleanup: enable unused_trait_names clippy lint and run clippy --fix 2025-03-16 00:35:56 +00:00
Evan Mesterhazy
0edf23eb16 lib rewrite: Add a test for CommitWithSelection
This is in preparation for adding a new function that inverts the selection.
2025-03-08 00:11:29 +00:00
Yuya Nishihara
ae8e6e8e8e view: port remote_bookmark accessors to RemoteRefSymbol 2025-02-26 03:17:45 +00:00
Martin von Zweigbergk
4ac970fcc5 cleanup: prefer MutableRepo::repo() over repo_mut()
When we don't need a mutable reference, we should be using `repo()`.
2025-01-31 18:03:01 +00:00
Yuya Nishihara
c50a70906b rewrite: add option to delete abandoned bookmarks
I'll make "jj abandon" delete bookmarks by default. This could be handled by
cmd_abandon(), but we'll need a repo API if we also want to change the behavior
of "jj rebase --skip-emptied".
2025-01-21 02:37:07 +00:00
Yuya Nishihara
ace041ec96 rewrite: add a few more bookmarks to abandoning test, remove redundant assertion 2025-01-21 02:37:07 +00:00
Yuya Nishihara
83d40d2c42 repo: move rebase_descendants_with_options_return_map() to tests 2025-01-18 01:21:28 +00:00
Yuya Nishihara
e3efb0d614 rewrite: pass RebaseOptions by reference
Since we've removed DescendantRebaser, it no longer makes sense to pass options
by value. This patch also replaces Default::default() for clarity.
2025-01-18 01:21:28 +00:00
Yuya Nishihara
5d1f3d006d repo: pass &Commit to record_abandoned_commit() to simplify error handling 2025-01-17 00:28:25 +00:00
Yuya Nishihara
cff73841ed repo: remove &UserSettings argument from new/rewrite_commit(), use self.settings 2024-12-31 10:51:57 +09:00
Yuya Nishihara
14b52205fb repo: remove &UserSettings argument from start_transaction(), use self.settings 2024-12-31 10:51:57 +09:00
Benjamin Tan
dddeb8b526 lib: fix various typos
This commit fixes typos unintentionally introduced in d9c68e08, when
renaming `jj branch` to `jj bookmark`.
2024-12-21 02:46:24 +08:00
Martin von Zweigbergk
de6da1a088 transaction: propagate errors from commit() 2024-11-13 23:05:24 -08:00
Benjamin Tan
1aad724798 repo: remove MutableRepo::rebase_descendants_return_map
This function is merely a simple wrapper around
`MutableRepo::rebase_descendants_with_options_return_map`.
2024-11-12 14:00:00 +08:00
Martin von Zweigbergk
1aa2aec141 bookmarks: update some leftover uses of the word "branch" 2024-09-11 19:19:31 -07:00
Philip Metzger
d9c68e08b1 everything: Rename branches to bookmarks
Jujutsu's branches do not behave like Git branches, which is a major
hurdle for people adopting it from Git. They rather behave like
Mercurial's (hg) bookmarks. 

We've had multiple discussions about it in the last ~1.5 years about this rename in the Discord, 
where multiple people agreed that this _false_ familiarity does not help anyone. Initially we were 
reluctant to do it but overtime, more and more users agreed that `bookmark` was a better for name 
the current mechanism. This may be hard break for current `jj branch` users, but it will immensly 
help Jujutsu's future, by defining it as our first own term. The `[experimental-moving-branches]` 
config option is currently left alone, to force not another large config update for
users, since the last time this happened was when `jj log -T show` was removed, which immediately 
resulted in breaking users and introduced soft deprecations.

This name change will also make it easier to introduce Topics (#3402) as _topological branches_ 
with a easier model. 

This was mostly done via LSP, ripgrep and sed and a whole bunch of manual changes either from
me being lazy or thankfully pointed out by reviewers.
2024-09-11 18:54:45 +02:00
Martin von Zweigbergk
8d090628c3 transaction: rename mut_repo() to idiomatic repo_mut()
We had both `repo()` and `mut_repo()` on `Transaction` and I think it
was easy to get confused and think that the former returned a
`&ReadonlyRepo` but both of them actually return a reference to
`MutableRepo` (the latter obviously returns a mutable reference). I
hope that renaming to the more idiomatic `repo_mut()` will help
clarify.

We could instead have renamed them to `mut_repo()` and
`mut_repo_mut()` but that seemed unnecessarily long. It would better
match the `mut_repo` variables we typically use, though.
2024-09-07 10:51:43 -07:00
Yuya Nishihara
cb16b5afd0 rewrite: ensure that rewritten refs move across divergent entries
This is closer to the original behavior before 5e8d7f8c "rewrite: update
references after rewriting all commits." References can move to divergent
commits, so they should propagate further if there are more rewrites. See
the inline comment for subtle behavior difference.

We could instead replay parent_mapping in topological order, but we would
still need to flatten abandon records.
2024-09-01 11:11:12 +09:00
Yuya Nishihara
1fe9422a6e rewrite: deduplicate parent ids per remap iteration
If merge-heavy history was abandoned, intermediate parent chains can have tons
of duplicates, and the process explodes soon. Instead, we can skip any parent
ids that have been remapped.

We can no longer detect cycles reliably, but I think that's okay so long as
the function terminates.

Fixes #4352
2024-08-29 08:59:22 +09:00
Matt Kulukundis
8ead72e99f formatting only: switch to Item level import ganularity 2024-08-22 14:52:54 -04:00
Martin von Zweigbergk
e02622b143 repo: when abandoning a working copy that a merge, recreate it
I recently needed to test something on top of a two branches at the
same time, so I created a new commit on top of both of them (i.e. a
merge commit). I then ran tests and made some adjustments to the
code. These adjustments belonged in one of the parent branches, so I
used `jj squash --into` to squash it in there. Unfortunately, that
meant that my working copy became a single-parent commit based on one
of the branches only. We already had #2859 for tracking this issue.

This patch changes the behavior so we create a new working-copy commit
with all of the previous parents.
2024-05-29 06:54:30 -07:00
Martin von Zweigbergk
1970ddef15 tree: propagate errors from sub_tree()/path_value() 2024-05-22 06:46:38 -07:00
Martin von Zweigbergk
2859277941 rewrite: pass CommitRewriter into rebase_commit_with_options()
`CommitRewriter` wraps 3 of the arguments, so I think it makes sense
to pass it instead. More importantly, I hope to continue refactoring
so many of the callers already have a `CommitRewriter`.
2024-04-18 08:08:51 -07:00
Martin von Zweigbergk
b13cb8db26 rewrite: make EmptyBehavior implement Copy 2024-04-18 08:08:51 -07:00
Martin von Zweigbergk
93baff0b8a rewrite: pass just IDs of new parents into rewrite::rebase*()
It's cheap to look up commits again from the cache in `Store` but it
can be expensive to look up commits we didn't end up needing. This
will make it easier to refactor further and be able to cheaply set
preliminary parents for a rewritten commits and then let the caller
update them.
2024-04-17 06:13:54 -07:00
Martin von Zweigbergk
057b7c8d0b rewrite: take commit and new parents by value in rebase_commit()
I'm going to add a helper struct to help with rewriting commits. I
want to make that struct own the old commit and the new parents to
simplify lifetimes. This patch prepares for that by passing the
commits by value to `rebase_commit()`.
2024-04-17 06:13:54 -07:00
Martin von Zweigbergk
5e8d7f8c6f rewrite: update references after rewriting all commits 2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
d2043f069e repo: delete record_rewritten_commit()
I don't think we have any callers left that call
`record_rewritten_commit()` multiple times within a transaction and
expect it to result in divergence. I think we should consider it a bug
to do that.
2024-03-25 06:53:14 -07:00
Martin von Zweigbergk
1cbf2b4acf rewrite: allow working-copy to be abandoned
This removes the special handling of the working-copy commit. By
recording when an empty/emptied commit was abanoned, we rebase
descendants correctly and create a new empty working-copy commit on
top.
2024-02-25 16:39:05 -08:00