Skip to content

Commit aa0554f

Browse files
committed
Sketch of the APIs involved in branch::apply().
1 parent b1855a2 commit aa0554f

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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 combined tree with all snapshot information, suitable for being stored in a commit.
22+
pub snapshot_tree: gix::ObjectId,
23+
/// The tree representing the current index, without conflicts.
24+
pub index: gix::ObjectId,
25+
/// The in a custom storage format to allow keeping conflicting blobs reachable, along with detailed conflict information.
26+
pub index_conflicts: gix::ObjectId,
27+
}
28+
29+
pub(super) mod function {
30+
use super::{Outcome, State};
31+
use but_core::RefMetadata;
32+
/// Create a tree that represents the snapshot for the given `selection`, with the basis for everything
33+
/// being the `head_tree_id` (i.e. the tree to which `HEAD` is ultimately pointing to).
34+
///
35+
/// If `workspace_and_meta` is not `None`, the workspace and metadata to store in the snapshot.
36+
/// We will only store reference positions, and assume that their commits are safely stored in the reflog to not
37+
/// be garbage collected. Metadata is only stored for the references that are included in the `workspace`.
38+
/// This way we will also store the `HEAD` position to keep track of where the user is located.
39+
///
40+
/// Note that objects will be written into the repository behind `head_tree_id` unless it's configured
41+
/// to keep everything in memory.
42+
pub fn create_tree(
43+
head_tree_id: gix::Id<'_>,
44+
selection: State,
45+
workspace_and_meta: Option<(&but_graph::projection::Workspace, &impl RefMetadata)>,
46+
) -> anyhow::Result<Outcome> {
47+
todo!()
48+
}
49+
}
50+
}
51+
pub use create_tree::function::create_tree;
52+
53+
/// Utilities related to resolving previously created snapshots.
54+
pub mod resolve_tree {
55+
56+
/// The information extracted from [`resolve_tree`](function::resolve_tree()).
57+
pub struct Outcome<'repo> {
58+
/// The cherry-pick result as merge between the target worktree and the snapshot, **possibly with conflicts**.
59+
///
60+
/// This tree, may be checked out to the working tree, with or without conflicts.
61+
pub workspace_cherry_pick: gix::merge::tree::Outcome<'repo>,
62+
/// If an index was stored in the snapshot, this is the reconstructed index, including conflicts.
63+
pub index: Option<gix::index::State>,
64+
/// Reference edits that when applied in a transaction will set the workspace back to where it was. Only available
65+
/// if it was part of the snapshot to begin with.
66+
pub workspace_reference_edits: Option<Vec<gix::refs::transaction::RefEdit>>,
67+
/// The metadata to be applied to the ref-metadata store.
68+
pub metadata_edits: Option<MetadataEdits>,
69+
}
70+
71+
/// Edits for application via [`but_core::RefMetadata`].
72+
pub struct MetadataEdits {
73+
/// The workspace metadata stored in the snapshot.
74+
pub workspace: (gix::refs::FullName, but_core::ref_metadata::Workspace),
75+
/// The branch metadata stored in snapshots.
76+
pub branches: Vec<(gix::refs::FullName, but_core::ref_metadata::Branch)>,
77+
}
78+
79+
pub(super) mod function {
80+
use super::Outcome;
81+
82+
/// Given the `snapshot` tree as previously returned via [super::create_tree::Outcome::snapshot_tree], extract the data and…
83+
///
84+
/// * …cherry-pick the worktree changes onto the `target_worktree_tree_id`, which is assumed to represent the future working directory state
85+
/// and which either contains the worktree changes or *preferably* is the `HEAD^{tree}` as the working directory is clean.
86+
/// * …reconstruct the index to write into `.git/index`, assuming that the current `.git/index` is clean.
87+
/// * …produce reference edits to put the workspace refs back into place with.
88+
/// * …produce metadata that if set will represent the metadata of the entire workspace.
89+
///
90+
/// Note that none of this data is actually manifested in the repository or working tree, they only exists as objects in the Git database,
91+
/// assuming in-memory objects aren't used in the repository.
92+
pub fn resolve_tree<'repo>(
93+
snapshot: gix::Id<'_>,
94+
target_worktree_tree_id: gix::ObjectId,
95+
) -> anyhow::Result<Outcome<'_>> {
96+
todo!()
97+
}
98+
}
99+
}
100+
pub use resolve_tree::function::resolve_tree;

0 commit comments

Comments
 (0)