Skip to content

Commit 3bd6308

Browse files
committed
Sketch of the APIs involved in branch::apply().
1 parent c1e23e9 commit 3bd6308

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

crates/but-workspace/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![deny(missing_docs, rust_2018_idioms)]
1+
#![deny(missing_docs)]
22
#![deny(clippy::indexing_slicing)]
33

44
//! ### Terminology
@@ -55,6 +55,8 @@ pub use head::{head, merge_worktree_with_workspace};
5555
/// Ignore the name of this module; it's just a place to put code by now.
5656
pub mod branch;
5757

58+
pub mod snapshot;
59+
5860
mod changeset;
5961

6062
mod commit;

crates/but-workspace/src/snapshot.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//! The ability to create a Git representation of diverse 'state' that can be restored at a later time.
2+
3+
///
4+
pub mod create_tree {
5+
use bstr::BString;
6+
7+
/// A way to determine what should be included in the snapshot when calling [create_tree()](function::create_tree).
8+
pub struct State<'a> {
9+
/// The result of a previous worktree changes call.
10+
///
11+
/// It contains detailed information about the complete set of possible changes to become part of the worktree.
12+
pub changes: &'a but_core::WorktreeChanges,
13+
/// Repository-relative and slash-separated paths that match any change in the [`changes`](State::changes) field.
14+
/// **It's an error if there is no match.** as there is not supposed to be a snapshot without a change to the working tree.
15+
pub selection: Vec<BString>,
16+
}
17+
18+
/// Contains all state that the snapshot contains.
19+
#[derive(Debug, Copy, Clone)]
20+
pub struct Outcome {
21+
/// The snapshot itself, with all the subtrees available that are also listed in this structure.
22+
pub snapshot_tree: gix::ObjectId,
23+
/// For good measure, the input `HEAD^{tree}` that is used as the basis to learn about worktree changes.
24+
pub head_tree: gix::ObjectId,
25+
/// The `head_tree` with the selected worktree changes applied, suitable for being stored in a commit.
26+
pub wortree: gix::ObjectId,
27+
/// The tree representing the current changed index, without conflicts, or `None` if there was no change to the index.
28+
pub index: Option<gix::ObjectId>,
29+
/// A tree with files in a custom storage format to allow keeping conflicting blobs reachable, along with detailed conflict information
30+
/// to allow restoring the conflict entries in the index.
31+
pub index_conflicts: Option<gix::ObjectId>,
32+
/// The tree representing the reference targets of all references within the *workspace*.
33+
pub workspace_reference: Option<gix::ObjectId>,
34+
/// The tree representing the metadata of all references within the *workspace*.
35+
pub metadata: Option<gix::ObjectId>,
36+
}
37+
38+
pub(super) mod function {
39+
use super::{Outcome, State};
40+
use but_core::RefMetadata;
41+
/// Create a tree that represents the snapshot for the given `selection`, with the basis for everything
42+
/// being the `head_tree_id` (i.e. the tree to which `HEAD` is ultimately pointing to).
43+
///
44+
/// If `workspace_and_meta` is not `None`, the workspace and metadata to store in the snapshot.
45+
/// We will only store reference positions, and assume that their commits are safely stored in the reflog to not
46+
/// be garbage collected. Metadata is only stored for the references that are included in the `workspace`.
47+
/// This way we will also store the `HEAD` position to keep track of where the user is located.
48+
///
49+
/// Note that objects will be written into the repository behind `head_tree_id` unless it's configured
50+
/// to keep everything in memory.
51+
pub fn create_tree(
52+
head_tree_id: gix::Id<'_>,
53+
selection: State,
54+
workspace_and_meta: Option<(&but_graph::projection::Workspace, &impl RefMetadata)>,
55+
) -> anyhow::Result<Outcome> {
56+
todo!()
57+
}
58+
}
59+
}
60+
pub use create_tree::function::create_tree;
61+
62+
/// Utilities related to resolving previously created snapshots.
63+
pub mod resolve_tree {
64+
65+
/// The information extracted from [`resolve_tree`](function::resolve_tree()).
66+
pub struct Outcome<'repo> {
67+
/// The cherry-pick result as merge between the target worktree and the snapshot, **possibly with conflicts**.
68+
///
69+
/// This tree, may be checked out to the working tree, with or without conflicts.
70+
pub workspace_cherry_pick: gix::merge::tree::Outcome<'repo>,
71+
/// If an index was stored in the snapshot, this is the reconstructed index, including conflicts.
72+
pub index: Option<gix::index::State>,
73+
/// Reference edits that when applied in a transaction will set the workspace back to where it was. Only available
74+
/// if it was part of the snapshot to begin with.
75+
pub workspace_references: Option<Vec<gix::refs::transaction::RefEdit>>,
76+
/// The metadata to be applied to the ref-metadata store.
77+
pub metadata: Option<MetadataEdits>,
78+
}
79+
80+
/// Edits for application via [`but_core::RefMetadata`].
81+
pub struct MetadataEdits {
82+
/// The workspace metadata stored in the snapshot.
83+
pub workspace: (gix::refs::FullName, but_core::ref_metadata::Workspace),
84+
/// The branch metadata stored in snapshots.
85+
pub branches: Vec<(gix::refs::FullName, but_core::ref_metadata::Branch)>,
86+
}
87+
88+
pub(super) mod function {
89+
use super::Outcome;
90+
91+
/// Given the `snapshot` tree as previously returned via [super::create_tree::Outcome::snapshot_tree], extract the data and…
92+
///
93+
/// * …cherry-pick the worktree changes onto the `target_worktree_tree_id`, which is assumed to represent the future working directory state
94+
/// and which either contains the worktree changes or *preferably* is the `HEAD^{tree}` as the working directory is clean.
95+
/// * …reconstruct the index to write into `.git/index`, assuming that the current `.git/index` is clean.
96+
/// * …produce reference edits to put the workspace refs back into place with.
97+
/// * …produce metadata that if set will represent the metadata of the entire workspace.
98+
///
99+
/// Note that none of this data is actually manifested in the repository or working tree, they only exists as objects in the Git database,
100+
/// assuming in-memory objects aren't used in the repository.
101+
pub fn resolve_tree<'repo>(
102+
snapshot: gix::Id<'_>,
103+
target_worktree_tree_id: gix::ObjectId,
104+
) -> anyhow::Result<Outcome<'_>> {
105+
todo!()
106+
}
107+
}
108+
}
109+
pub use resolve_tree::function::resolve_tree;

0 commit comments

Comments
 (0)