Skip to content

Commit 39f3f95

Browse files
committed
Implement snapshot::create_tree() with worktree snapshot supports
1 parent 1b0f59d commit 39f3f95

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

crates/but-core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,9 @@ pub enum IgnoredWorktreeTreeChangeStatus {
332332
pub struct IgnoredWorktreeChange {
333333
/// The worktree-relative path to the change.
334334
#[serde(serialize_with = "gitbutler_serde::bstring_lossy::serialize")]
335-
path: BString,
335+
pub path: BString,
336336
/// The status that caused this change to be ignored.
337-
status: IgnoredWorktreeTreeChangeStatus,
337+
pub status: IgnoredWorktreeTreeChangeStatus,
338338
}
339339

340340
/// The type returned by [`worktree_changes()`](diff::worktree_changes).

crates/but-workspace/src/snapshot.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33
///
44
pub mod create_tree {
55
use bstr::BString;
6+
use but_graph::VirtualBranchesTomlMetadata;
7+
use std::collections::BTreeSet;
68

79
/// A way to determine what should be included in the snapshot when calling [create_tree()](function::create_tree).
8-
pub struct State<'a> {
10+
#[derive(Debug, Clone)]
11+
pub struct State {
912
/// The result of a previous worktree changes call.
1013
///
1114
/// It contains detailed information about the complete set of possible changes to become part of the worktree.
12-
pub changes: &'a but_core::WorktreeChanges,
15+
pub changes: but_core::WorktreeChanges,
1316
/// Repository-relative and slash-separated paths that match any change in the [`changes`](State::changes) field.
1417
/// **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>,
18+
pub selection: BTreeSet<BString>,
1619
/// If `true`, store the current `HEAD` reference, i.e. its target, as well as the targets of all refs it's pointing to by symbolic link.
1720
pub head: bool,
1821
}
@@ -40,11 +43,21 @@ pub mod create_tree {
4043
pub metadata: Option<gix::ObjectId>,
4144
}
4245

46+
/// A utility to more easily use *no* workspace or metadata.
47+
pub fn no_workspace_and_meta() -> Option<(
48+
&'static but_graph::projection::Workspace<'static>,
49+
&'static VirtualBranchesTomlMetadata,
50+
)> {
51+
None
52+
}
53+
4354
pub(super) mod function {
4455
use super::{Outcome, State};
4556
use but_core::RefMetadata;
57+
4658
/// Create a tree that represents the snapshot for the given `selection`, with the basis for everything
4759
/// being the `head_tree_id` (i.e. the tree to which `HEAD` is ultimately pointing to).
60+
/// Make this an empty tree if the `HEAD` is unborn.
4861
///
4962
/// If `workspace_and_meta` is not `None`, the workspace and metadata to store in the snapshot.
5063
/// We will only store reference positions, and assume that their commits are safely stored in the reflog to not
@@ -53,10 +66,17 @@ pub mod create_tree {
5366
/// Note that objects will be written into the repository behind `head_tree_id` unless it's configured
5467
/// to keep everything in memory.
5568
pub fn create_tree(
56-
_head_tree_id: gix::Id<'_>,
57-
_selection: State,
69+
head_tree_id: gix::Id<'_>,
70+
State {
71+
changes: _,
72+
selection: _,
73+
head: _,
74+
}: State,
5875
_workspace_and_meta: Option<(&but_graph::projection::Workspace, &impl RefMetadata)>,
5976
) -> anyhow::Result<Outcome> {
77+
let repo = head_tree_id.repo;
78+
// TODO: refactor tree-creation to not assume commits anymore.
79+
// commit_engine::tree::create_tree(repo, )
6080
todo!()
6181
}
6282
}
@@ -91,6 +111,7 @@ pub mod resolve_tree {
91111

92112
pub(super) mod function {
93113
use super::Outcome;
114+
use crate::commit_engine;
94115

95116
/// Given the `snapshot_tree` as previously returned via [super::create_tree::Outcome::snapshot_tree], extract data and…
96117
///

crates/but-workspace/tests/workspace/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod branch_details;
55
mod commit_engine;
66
mod flatten_diff_specs;
77
mod ref_info;
8+
mod snapshot;
89
mod tree_manipulation;
910
mod ui;
1011

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
mod create_tree {
2+
use crate::utils::read_only_in_memory_scenario;
3+
use but_graph::VirtualBranchesTomlMetadata;
4+
use but_testsupport::visualize_tree;
5+
use but_workspace::snapshot;
6+
use gix::prelude::ObjectIdExt;
7+
8+
#[test]
9+
fn worktree_all_filetypes() -> anyhow::Result<()> {
10+
let repo = read_only_in_memory_scenario("all-file-types-changed")?;
11+
let (head_tree_id, state, no_workspace_and_meta) = args_for_worktree_changes(&repo)?;
12+
13+
let out = snapshot::create_tree(head_tree_id, state, no_workspace_and_meta)?;
14+
insta::assert_snapshot!(visualize_tree(out.snapshot_tree.attach(&repo)), @r"");
15+
16+
insta::assert_debug_snapshot!(out, @r"");
17+
Ok(())
18+
}
19+
20+
/// Produce all args needed for creating a snapshot tree, and assure everything is selected.
21+
fn args_for_worktree_changes(
22+
repo: &gix::Repository,
23+
) -> anyhow::Result<(
24+
gix::Id<'_>,
25+
snapshot::create_tree::State,
26+
Option<(
27+
&'static but_graph::projection::Workspace<'static>,
28+
&'static VirtualBranchesTomlMetadata,
29+
)>,
30+
)> {
31+
let changes = but_core::diff::worktree_changes(repo)?;
32+
let state = snapshot::create_tree::State {
33+
selection: changes
34+
.changes
35+
.iter()
36+
.map(|c| c.path.clone())
37+
.chain(changes.ignored_changes.iter().map(|c| c.path.clone()))
38+
.collect(),
39+
changes,
40+
head: false,
41+
};
42+
let head_tree_id = repo.head_tree_id_or_empty()?;
43+
44+
Ok((head_tree_id, state, None))
45+
}
46+
}

0 commit comments

Comments
 (0)