Skip to content

Commit ab43e28

Browse files
committed
Add the missing tests for index-snapshot handling.
1 parent e98e8da commit ab43e28

File tree

7 files changed

+113
-21
lines changed

7 files changed

+113
-21
lines changed

crates/but-core/src/diff/worktree.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ fn worktree_changes_inner(
479479
let mut path_check = gix::status::plumbing::SymlinkCheck::new(
480480
repo.workdir().map(ToOwned::to_owned).context("non-bare")?,
481481
);
482+
let original_changes = tmp.iter().map(|(_, change)| change.clone()).collect();
482483
for (_origin, change) in tmp {
483484
// At this point we know that the current `change` is the tree/index variant
484485
// of a prior change between index/worktree.
@@ -538,6 +539,7 @@ fn worktree_changes_inner(
538539
Ok(WorktreeChanges {
539540
changes,
540541
ignored_changes,
542+
original_changes,
541543
})
542544
}
543545

@@ -935,3 +937,12 @@ impl TreeChange {
935937
}
936938
}
937939
}
940+
941+
impl std::fmt::Debug for WorktreeChanges {
942+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
943+
f.debug_struct("WorktreeChanges")
944+
.field("changes", &self.changes)
945+
.field("ignored_changes", &self.ignored_changes)
946+
.finish()
947+
}
948+
}

crates/but-core/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,12 +346,16 @@ pub struct IgnoredWorktreeChange {
346346
}
347347

348348
/// The type returned by [`worktree_changes()`](diff::worktree_changes).
349-
#[derive(Debug, Clone)]
349+
#[derive(Clone)]
350350
pub struct WorktreeChanges {
351351
/// Changes that could be committed.
352352
pub changes: Vec<TreeChange>,
353353
/// Changes that were in the index that we can't handle. The user can see them and interact with them to clear them out before a commit can be made.
354354
pub ignored_changes: Vec<IgnoredWorktreeChange>,
355+
/// The unprocessed (but sorted, by path) changes which were used to produce `changes` and `ignored_changes`.
356+
/// This doesn't include index conflicts!
357+
/// TODO: can this be specific index changes? After all that's the only thing we need.
358+
pub original_changes: Vec<TreeChange>,
355359
}
356360

357361
/// Computed using the file kinds/modes of two [`ChangeState`] instances to represent

crates/but-core/src/ui.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ impl From<crate::WorktreeChanges> for WorktreeChanges {
2929
crate::WorktreeChanges {
3030
changes,
3131
ignored_changes,
32+
original_changes: _,
3233
}: crate::WorktreeChanges,
3334
) -> Self {
3435
WorktreeChanges {

crates/but-workspace/src/snapshot/create_tree.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ pub(super) mod function {
9898
/// even though it might be that the respective objects aren't written to disk yet.
9999
/// - Note that this tree may contain files with conflict markers as it will pick up the conflicting state visible on disk.
100100
/// * `index`
101-
/// - A representation of the non-conflicting and changed portions of the index, without its meta-data.
102-
/// - may be empty if only conflicts exist.
101+
/// - A representation of the non-conflicting portions of the index, without its meta-data,
102+
/// ready to be read back as an index.
103+
/// - It's present only if there is at least one modification compared to the `HEAD^{tree}`.
103104
/// * `index-conflicts`
104105
/// - `<entry-path>/[1,2,3]` - the blobs at their respective stages.
105106
#[instrument(skip(changes, _workspace_and_meta), err(Debug))]
@@ -212,29 +213,26 @@ pub(super) mod function {
212213
changes: but_core::WorktreeChanges,
213214
selection: BTreeSet<BString>,
214215
) -> anyhow::Result<Option<(Option<gix::ObjectId>, Option<gix::ObjectId>)>> {
215-
let mut conflicts = Vec::new();
216-
let changes: Vec<_> = changes
217-
.changes
216+
let conflicts: Vec<_> = changes
217+
.ignored_changes
218218
.into_iter()
219-
.filter_map(|c| c.status_item)
220-
.chain(
221-
changes
222-
.ignored_changes
223-
.into_iter()
224-
.filter_map(|c| c.status_item),
225-
)
226-
.filter_map(|item| match item {
227-
gix::status::Item::IndexWorktree(
219+
.filter_map(|c| match c.status_item {
220+
Some(gix::status::Item::IndexWorktree(
228221
gix::status::index_worktree::Item::Modification {
229222
status: EntryStatus::Conflict { entries, .. },
230223
rela_path,
231224
..
232225
},
233-
) => {
234-
conflicts.push((rela_path, entries));
235-
None
236-
}
237-
gix::status::Item::TreeIndex(c) => Some(c),
226+
)) => Some((rela_path, entries)),
227+
_ => None,
228+
})
229+
.collect();
230+
231+
let changes: Vec<_> = changes
232+
.original_changes
233+
.into_iter()
234+
.filter_map(|c| match c.status_item {
235+
Some(gix::status::Item::TreeIndex(c)) => Some(c),
238236
_ => None,
239237
})
240238
.filter(|c| selection.iter().any(|path| path == c.location()))

crates/but-workspace/tests/fixtures/generated-archives/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@
2828
/with-remotes-and-workspace.tar
2929
/with-conflict.tar
3030
/journey*.tar
31-
/single-branch*.tar
31+
/single-branch*.tar
32+
/index*.tar
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
3+
### Description
4+
# A commit with an executable, a normal file, and an untracked fifo,
5+
# which subsequently get modified and deleted in the index, with the symlink being added to it.
6+
set -eu -o pipefail
7+
8+
git init
9+
echo content > modified-content
10+
echo change-exe-bit > modified-exe
11+
echo "soon deleted in index but left on disk" > deleted-exe && chmod +x deleted-exe
12+
mkfifo fifo-should-be-ignored
13+
14+
git add . && git commit -m "init"
15+
16+
echo index-content >modified-content && \
17+
git add modified-content && \
18+
echo content >modified-content
19+
20+
ln -s only-in-index link && \
21+
git add link && \
22+
rm link
23+
24+
git rm --cached deleted-exe
25+
26+
chmod +x modified-exe && \
27+
git add modified-exe && \
28+
chmod -x modified-exe
29+

crates/but-workspace/tests/workspace/snapshot/index_create_and_resolve.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,51 @@ fn with_conflicts() -> anyhow::Result<()> {
125125
);
126126
Ok(())
127127
}
128+
129+
#[test]
130+
fn index_added_modified_deleted() -> anyhow::Result<()> {
131+
let repo = read_only_in_memory_scenario("index-modified-added-deleted")?;
132+
let (head_tree_id, state, no_workspace_and_meta) = args_for_worktree_changes(&repo)?;
133+
134+
let out = snapshot::create_tree(head_tree_id, state, no_workspace_and_meta)?;
135+
insta::assert_snapshot!(visualize_tree(out.snapshot_tree.attach(&repo)), @r#"
136+
449404d
137+
└── index:3fd7ead
138+
├── link:120000:e940347 "only-in-index"
139+
├── modified-content:100644:70c2547 "index-content\n"
140+
└── modified-exe:100755:ef1943d "change-exe-bit\n"
141+
"#);
142+
insta::assert_debug_snapshot!(out, @r"
143+
Outcome {
144+
snapshot_tree: Sha1(449404df68c6041fc4f9b2f1cd30725bdb7ba329),
145+
head_tree: Sha1(632babec715de181e63036ee0cc3686efa67528d),
146+
worktree: None,
147+
index: Some(
148+
Sha1(3fd7ead2468a4def3db4c946c0f3b933eb8f2682),
149+
),
150+
index_conflicts: None,
151+
workspace_references: None,
152+
head_references: None,
153+
metadata: None,
154+
}
155+
");
156+
157+
let res_out = snapshot::resolve_tree(
158+
out.snapshot_tree.attach(&repo),
159+
out.head_tree,
160+
snapshot::resolve_tree::Options::default(),
161+
)?;
162+
let index = res_out.index.expect("the index was altered");
163+
insta::assert_snapshot!(visualize_index(&index), @r"
164+
120000:e940347 link
165+
100644:70c2547 modified-content
166+
100755:ef1943d modified-exe
167+
");
168+
169+
assert!(res_out.metadata.is_none());
170+
assert!(
171+
res_out.workspace_references.is_none(),
172+
"didn't ask to store this"
173+
);
174+
Ok(())
175+
}

0 commit comments

Comments
 (0)