3041 Commits

Author SHA1 Message Date
Yuya Nishihara
57167cefda git: on import_refs(), don't abandon ancestors of newly fetched refs
I made import_refs() not preserve commits referenced by remote branches at
520f692a4600 "git: on import_refs(), don't preserve old branches referenced by
remote refs." The idea is that remote branches are weak, and commits referenced
by these refs can be freely rewritten by future local changes without moving
the refs. I don't think that's wrong, but 520f692a4600 also made "new" remote
changes be abandoned by old remote refs. This problem occurs only when
git.auto-local-branch is off.

I think there are two ways to fix the problem:
 a. pin non-tracking remote branches just like local refs
 b. pin newly fetched refs in addition to local refs
This patch implements (b) because it's simpler and more obvious that the
fetched commits would never be abandoned immediately.
2023-10-17 14:49:49 +09:00
Martin von Zweigbergk
c3b45b6fd1 workspace: make working-copy type customizable
This add support for custom `jj` binaries to use custom working-copy
backends. It works in the same way as with the other backends, i.e. we
write a `.jj/working_copy/type` file when the working copy is
initialized, and then we let that file control which implementation to
use (see previous commit).

I included an example of a (useless) working-copy implementation. I
hope we can figure out a way to test the examples some day.
2023-10-16 22:33:44 -07:00
Martin von Zweigbergk
6bfd618275 workspace: load working copy implementation dynamically
This makes `Workspace::load()` look a new `.jj/working_copy/type` file
in order to load the right working copy implementation, just like
`Repo::load()` picks the right backends based on `.jj/store/type`,
`.jj/op_store/type`, etc. We don't write the file yet, and we don't
have a way of adding alternative working copy implementations, so it
will always be `LocalWorkingCopy` for now.
2023-10-16 22:33:44 -07:00
Martin von Zweigbergk
e1f00d9426 working copy: pass commit instead of tree into check_out()
Our internal working copy implementations at Google will need the
commit so they can walk history backwards until they get to a "public"
commit. They'll then use that to tell build tools and virtual file
systems to present that as a base.

I'm not sure if we'll need to update `reset()` too. It's currently
only used by `jj untrack`, which doesn't change the commit's parent,
so it wouldn't affect any history walks.
2023-10-16 22:33:44 -07:00
Martin von Zweigbergk
7c8a0a18f9 repo: define types for backend initializer functions
`ReadonlyRepo::init()` takes callbacks for initializing each kind of
backend. We called these things like `op_store_initializer`. I found
that confusing because it is not a `OpStoreFactory` (which is for
loading an existing backend). This patch tries to clarify that by
renaming the arguments and adding types for each kind of callback
function.
2023-10-16 22:33:44 -07:00
Yuya Nishihara
9cafff87e1 cli: add API and branch subcommand to track/untrack remote branches
This patch adds MutableRepo::track_remote_branch() as we'll probably need to
track the default branch on "jj git clone". untrack_remote_branch() is also
added for consistency.
2023-10-16 23:21:05 +09:00
Yuya Nishihara
4af678848d op_store: minimal change to load/store tracking state of remote branches
We could instead migrate the storage types to (local_branches, remote_views),
but that would be more involved and break forward compatibility with little
benefit. Maybe we can do that later when we introduce remote tags.
2023-10-16 23:21:05 +09:00
Yuya Nishihara
4cd2518be0 git: on import_refs(), respect tracking state of existing remote refs
In this commit, new behavior is tested by using in-memory view data. Data
persistence and track/untrack commands will be implemented soon.
2023-10-16 23:21:05 +09:00
Yuya Nishihara
a697175674 view: add tracking state to RemoteRef
The state field isn't saved yet. git import/export code paths are migrated,
but new tracking state is always calculated based on git.auto-local-branch
setting. So the tracking state is effectively a global flag.

As we don't know whether the existing remote branches have been merged in to
local branches, we assume that remote branches are "tracking" so long as the
local counterparts exist. This means existing locally-deleted branch won't
be pushed without re-tracking it. I think it's rare to leave locally-deleted
branches for long. For "git.auto-local-branch = false" setup, users might have
to untrack branches if they've manually "merged" remote branches and want to
continue that workflow. I considered using git.auto-local-branch setting in the
migration path, but I don't think that would give a better result. The setting
may be toggled after the branches got merged, and I'm planning to change it
default off for better Git interop.

Implementation-wise, the state enum can be a simple bool. It's enum just
because I originally considered to pack "forgotten" concept into it. I have
no idea which will be better for future extension.
2023-10-16 23:21:05 +09:00
Martin von Zweigbergk
0582893144 working copy: return Box<dyn LockedWorkingCopy> from start_mutation() 2023-10-15 16:13:19 -07:00
Martin von Zweigbergk
580586d008 working copy: return Box<dyn WorkingCopy> from finish() 2023-10-15 16:13:19 -07:00
Martin von Zweigbergk
6a13fa8264 working copy: add tree_id() to backend trait
Looks like I missed this earlier. I think it makes sense to have on
all working copy implementations.
2023-10-15 16:13:19 -07:00
Martin von Zweigbergk
a733fceba9 working copy: add functions to start/finish modification to backend trait
To keep this patch small, the functions still return the concrete
local-disk implementations. I'll fix that soon.
2023-10-15 16:13:19 -07:00
Martin von Zweigbergk
63654d064b working copy: add sparse pattern functions to backend trait 2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
6457a13260 working copy: add reset() function to the backend trait
This includes documenting the new function and the other types moved
to the `working_copy` module.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
0d2247b0df working copy: add check_out() function to the backend trait
This includes documenting the new function and the other types moved
to the `working_copy` module.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
781859cb51 working copy: add snapshot() function to the backend trait
This includes documenting the new function and the other types moved
to the `working_copy` module.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
3aa57b1a04 working copy: start defining a trait for a locked working copy
As with the `WorkingCopy` trait, this just contains some trivial
methods for now.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
49637cb0fd working copy: don't clear tree_state_dirty just before it's dropped 2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
8826639e4e working copy: remove reference from locked instance to base instance
It's going to be easier to define a `LockedWorkingCopy` trait if it
doesn't need to borrow from `WorkingCopy`, so let's remove the
reference we currently have and have
`LockedLocalWorkingCopy::finish()` return the new `LocalWorkingCopy`
instead.

I think the main disadvantage is that we now have to remember to
replace the old `LocalWorkingCopy` instance by the new one, whereas
the compiler would remind us before this commit. We could make
`start_modification()` take an owned `self`, but that would be a bit
annoying to work with when we have the instance stored in a field.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
c8184845d7 workspace: replace working_copy_mut() by wrapper type
I'm about to make `LockedLocalWorkingCopy` not borrow from
`LocalWorkingCopy`. That will make it easier to forget to update any
`LocalWorkingCopy` variables when the modifications have been
committed. This patch introduces a wrapper around
`LockedLocalWorkingCopy` to help prevent that.

Thanks to Yuya for the suggestion.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
35f9c12cb5 working copy: move LocalWorkingCopy::check_out() to Workspace
`LocalWorkingCopy::check_out()` can be expressed using the planned
`WorkingCopy` trait, so it doesn't need to be in the trait itself
`WorkingCopy`. I wasn't sure if I should make it a free function in
`working_copy`, but I ended up moving it onto `Workspace`.
2023-10-15 15:59:49 -07:00
Martin von Zweigbergk
9fb5a4bcef tests: rename a repo1 variable to repo since there's only one
I think the `repo1` name was a leftover from when `ReadonlyRepo` had a
`WorkingCopy`.
2023-10-15 15:59:49 -07:00
Yuya Nishihara
8b46712bcb view: add stub method to set remote branch target and state, migrate callers
Since set_remote_branch_target() is called while merging refs, its tracking
state shouldn't be reinitialized. The other callers are migrated to new setter
to keep the story simple.
2023-10-16 05:12:19 +09:00
Yuya Nishihara
35ea607abd view: make get_remote_branch() return RemoteRef instead of RefTarget
I'm going to add tracking state to RemoteRef, and we should compare both
target and state in the tests.
2023-10-16 05:12:19 +09:00
Yuya Nishihara
d730b250a0 view: add absent RemoteRef constructors, proxy methods, and conversion impls
Copied from RefTarget.
2023-10-16 05:12:19 +09:00
Yuya Nishihara
ab1a6e2f71 view: make remote branches iterator yield RemoteRef instead of RefTarget
git::import_refs() will need to read RemoteRef's tracking state.
2023-10-16 05:12:19 +09:00
Yuya Nishihara
e7d93e5bf1 view: turn BranchTarget into borrowed type
This isn't important, but I'm going to change remote_targets to store RemoteRef
instead of RefTarget, so I went ahead and change the other field types as well.
2023-10-16 05:12:19 +09:00
Yuya Nishihara
92facbf21a view: add method to iterate branches of specified remote 2023-10-16 05:12:19 +09:00
Yuya Nishihara
8bdef924c8 view: rename remote_branches() to all_remote_branches()
I'm going to add a method that iterates branches of certain remote, and I
can't find a better name for it than remote_branches(remote_name).
2023-10-16 05:12:19 +09:00
Martin von Zweigbergk
6ca7b5d352 repo: levarage the new static <backend type>::name() functions 2023-10-14 15:21:53 -07:00
Martin von Zweigbergk
f8be0b2030 backends: deduplicate definition of backend names
I copied the example set by `DefaultSubmoduleStore`.
2023-10-14 06:38:35 -07:00
Yuya Nishihara
9186d0fd38 workspace: convert external git repo path to store-relative by constructor
We could fix do_git_clone() instead, but it seemed a bit weird that the
git_repo_path is relative to the store path which is unknown to callers.

Fixes #2374
2023-10-14 22:20:09 +09:00
Yuya Nishihara
b7c7b19eb8 view: migrate in-memory structure to per-remote branches map
There's a subtle behavior change. Unlike the original remove_remote_branch(),
remote_views entry is not discarded when the branches map becomes empty. The
reasoning here is that the remote view can be added/removed when the remote
is added/removed respectively, though that's not implemented yet. Since the
serialized data cannot represent an empty remote, such view may generate
non-unique content hash.
2023-10-14 22:20:00 +09:00
Yuya Nishihara
3ec3cac90b revset: use op_store::View type to resolve branches()/remote_branches()
These functions depend heavily on the underlying data structure, and I haven't
decided abstract View API to access to per-remote data types. Let's use the
underlying data type for now.
2023-10-14 22:20:00 +09:00
Yuya Nishihara
0160eaefd9 view: add function that converts branches to/from per-remote view-like data 2023-10-14 22:20:00 +09:00
Yuya Nishihara
2b78275e22 view: add per-remote view types and iterator that reconstructs BranchTarget
I'm planning to add support for untracked remote branches, and under that
model, there will be many remote branches without local counterparts. That's
the main reason why remote branches are grouped by remote, not by branch name.

The added helper functions will be used by simple_op_store and view.
2023-10-14 22:20:00 +09:00
Yuya Nishihara
198dfa5cbe view: extract remove_remote() from git module
This will be just self.data.remote_views.remove(remote_name), so I'm not gonna
refactor the implementation at this point.
2023-10-13 18:12:45 +09:00
Yuya Nishihara
1d3c830e85 view: rewrite get_branch() callers in tests, remove the method
get_branch() would need to reconstruct the remote_targets map if we migrate
the underlying data structure to per-remote views. Let's remove the method as
it is only used in tests.
2023-10-13 18:12:45 +09:00
Yuya Nishihara
3fb0a3b926 view: add has_branch(name), replace some of get_branch(name) callers
get_branch(name) will be removed soon.
2023-10-13 18:12:45 +09:00
Yuya Nishihara
d840610bad view: rewrite set_branch() callers in tests, remove the method
I'm going to reorganize the underlying data structure, and set_branch() won't
be as simple as it is now.
2023-10-13 18:12:45 +09:00
Martin von Zweigbergk
0aa5f1ae10 working copy: rename working_copy_path() to just path()
It seems pretty clear from the context. Turns out we only use the
function in a test case. Maybe we don't even need it. It's easy to
provide it, though.
2023-10-12 16:10:38 -07:00
Martin von Zweigbergk
9e43207911 working copy: don't expose TreeStateError in LocalWorkingCopy API
The `TreeStateError` type is specific to the current local-disk
working-copy backend, so it should not be part of the generic
working-copy interface I'm trying to create.
2023-10-12 16:10:38 -07:00
Martin von Zweigbergk
0e09d53ce6 working copy: make some reset errors less specific
Same reasoning as the previous commits.
2023-10-12 16:10:38 -07:00
Martin von Zweigbergk
645be615b4 working copy: make some snapshot errors less specific
Same reasoning as the previous commit.
2023-10-12 16:10:38 -07:00
Martin von Zweigbergk
324c40d4c5 working copy: make some checkout errors less specific
I think some of the errors variants in `CheckoutError` are too
specific to the local-disk implementation. Let's merge them and make
them less specific, so it's easier to define a reasonable trait for
the working copy.
2023-10-12 16:10:38 -07:00
Martin von Zweigbergk
33d27ed09f working copy: start defining a working copy trait
This just extracts a trait for the trivial bits to start with.
2023-10-12 16:10:38 -07:00
Yuya Nishihara
69a30b47af refs: migrate classify_branch_push_action() to local/remote targets pair 2023-10-12 16:50:09 +09:00
Yuya Nishihara
420bf79217 view: add method to iterate local/remote pairs of certain remote
This is common operation, and we don't need a map of all remote targets
to calculate push action.
2023-10-12 16:50:09 +09:00
Yuya Nishihara
679a591a22 repo: rewrite diffing of named refs to compare each targets pair
As I'm going to split branches into per-remote map, .get_branch(name) will need
to gather remote branches by name to construct remote_targets map. Let's instead
iterate local/remote branches separately. I also migrated diffing of the other
kinds of refs to filter out unchanged entries upfront.
2023-10-11 19:24:24 +09:00