Skip to content

Commit abcb145

Browse files
committed
Cleanup the worktree-changes data structure and make it fit snapshot requirements.
1 parent ab43e28 commit abcb145

File tree

8 files changed

+124
-148
lines changed

8 files changed

+124
-148
lines changed

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,6 @@ impl TreeChange {
6161
}
6262
}
6363

64-
impl std::fmt::Debug for TreeChange {
65-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66-
f.debug_struct("TreeChange")
67-
.field("path", &self.path)
68-
.field("status", &self.status)
69-
.finish()
70-
}
71-
}
72-
7364
impl std::fmt::Debug for IgnoredWorktreeChange {
7465
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7566
f.debug_struct("IgnoredWorktreeChange")

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ impl From<gix::object::tree::diff::ChangeDetached> for TreeChange {
8181
},
8282
is_untracked: false,
8383
},
84-
status_item: None,
8584
},
8685
Change::Deletion {
8786
location,
@@ -96,7 +95,6 @@ impl From<gix::object::tree::diff::ChangeDetached> for TreeChange {
9695
kind: entry_mode.kind(),
9796
},
9897
},
99-
status_item: None,
10098
},
10199
Change::Modification {
102100
location,
@@ -120,7 +118,6 @@ impl From<gix::object::tree::diff::ChangeDetached> for TreeChange {
120118
state,
121119
flags: ModeFlags::calculate(&previous_state, &state),
122120
},
123-
status_item: None,
124121
}
125122
}
126123
Change::Rewrite {
@@ -150,7 +147,6 @@ impl From<gix::object::tree::diff::ChangeDetached> for TreeChange {
150147
state,
151148
flags: ModeFlags::calculate(&previous_state, &state),
152149
},
153-
status_item: None,
154150
}
155151
}
156152
}

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

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -97,74 +97,102 @@ fn worktree_changes_inner(
9797
let work_dir = repo.workdir().context("need non-bare repository")?;
9898
let mut tmp = Vec::new();
9999
let mut ignored_changes = Vec::new();
100+
let mut index_conflicts = Vec::new();
101+
let mut index_changes = Vec::new();
100102
for change in status_changes {
101103
let change = change?;
102-
let change = match change.clone() {
104+
let change = match change {
103105
status::Item::TreeIndex(gix::diff::index::Change::Deletion {
104106
location,
107+
index,
105108
id,
106109
entry_mode,
107-
..
108-
}) => (
109-
Origin::TreeIndex,
110-
TreeChange {
111-
status: TreeStatus::Deletion {
112-
previous_state: ChangeState {
113-
id: id.into_owned(),
114-
kind: into_tree_entry_kind(entry_mode)?,
110+
}) => {
111+
let res = (
112+
Origin::TreeIndex,
113+
TreeChange {
114+
status: TreeStatus::Deletion {
115+
previous_state: ChangeState {
116+
id: id.clone().into_owned(),
117+
kind: into_tree_entry_kind(entry_mode)?,
118+
},
115119
},
120+
path: location.clone().into_owned(),
116121
},
117-
path: location.into_owned(),
118-
status_item: Some(change),
119-
},
120-
),
122+
);
123+
index_changes.push(gix::diff::index::Change::Deletion {
124+
location,
125+
index,
126+
id,
127+
entry_mode,
128+
});
129+
res
130+
}
121131
status::Item::TreeIndex(gix::diff::index::Change::Addition {
122132
location,
133+
index,
123134
entry_mode,
124135
id,
125-
..
126-
}) => (
127-
Origin::TreeIndex,
128-
TreeChange {
129-
path: location.into_owned(),
130-
status: TreeStatus::Addition {
131-
is_untracked: false,
132-
state: ChangeState {
133-
id: id.into_owned(),
134-
kind: into_tree_entry_kind(entry_mode)?,
136+
}) => {
137+
let res = (
138+
Origin::TreeIndex,
139+
TreeChange {
140+
path: location.clone().into_owned(),
141+
status: TreeStatus::Addition {
142+
is_untracked: false,
143+
state: ChangeState {
144+
id: id.clone().into_owned(),
145+
kind: into_tree_entry_kind(entry_mode)?,
146+
},
135147
},
136148
},
137-
status_item: Some(change),
138-
},
139-
),
149+
);
150+
index_changes.push(gix::diff::index::ChangeRef::Addition {
151+
location,
152+
index,
153+
entry_mode,
154+
id,
155+
});
156+
res
157+
}
140158
status::Item::TreeIndex(gix::diff::index::Change::Modification {
141159
location,
160+
previous_index,
142161
previous_entry_mode,
162+
index,
143163
entry_mode,
144164
previous_id,
145165
id,
146-
..
147166
}) => {
148167
let previous_state = ChangeState {
149-
id: previous_id.into_owned(),
168+
id: previous_id.clone().into_owned(),
150169
kind: into_tree_entry_kind(previous_entry_mode)?,
151170
};
152171
let state = ChangeState {
153-
id: id.into_owned(),
172+
id: id.clone().into_owned(),
154173
kind: into_tree_entry_kind(entry_mode)?,
155174
};
156-
(
175+
let res = (
157176
Origin::TreeIndex,
158177
TreeChange {
159-
path: location.into_owned(),
178+
path: location.clone().into_owned(),
160179
status: TreeStatus::Modification {
161180
previous_state,
162181
state,
163182
flags: ModeFlags::calculate(&previous_state, &state),
164183
},
165-
status_item: Some(change),
166184
},
167-
)
185+
);
186+
index_changes.push(gix::diff::index::Change::Modification {
187+
location,
188+
previous_index,
189+
previous_entry_mode,
190+
previous_id,
191+
index,
192+
entry_mode,
193+
id,
194+
});
195+
res
168196
}
169197
status::Item::IndexWorktree(index_worktree::Item::Modification {
170198
rela_path,
@@ -181,7 +209,6 @@ fn worktree_changes_inner(
181209
kind: into_tree_entry_kind(entry.mode)?,
182210
},
183211
},
184-
status_item: Some(change),
185212
},
186213
),
187214
status::Item::IndexWorktree(index_worktree::Item::Modification {
@@ -208,7 +235,6 @@ fn worktree_changes_inner(
208235
state,
209236
flags: ModeFlags::calculate(&previous_state, &state),
210237
},
211-
status_item: Some(change),
212238
},
213239
)
214240
}
@@ -245,7 +271,6 @@ fn worktree_changes_inner(
245271
state,
246272
flags: ModeFlags::calculate(&previous_state, &state),
247273
},
248-
status_item: Some(change),
249274
},
250275
)
251276
}
@@ -267,7 +292,6 @@ fn worktree_changes_inner(
267292
},
268293
is_untracked: false,
269294
},
270-
status_item: Some(change),
271295
},
272296
),
273297
status::Item::IndexWorktree(index_worktree::Item::DirectoryContents {
@@ -300,7 +324,6 @@ fn worktree_changes_inner(
300324
},
301325
is_untracked: true,
302326
},
303-
status_item: Some(change),
304327
},
305328
)
306329
}
@@ -340,7 +363,6 @@ fn worktree_changes_inner(
340363
state,
341364
flags: ModeFlags::calculate(&previous_state, &state),
342365
},
343-
status_item: Some(change),
344366
},
345367
)
346368
}
@@ -396,7 +418,6 @@ fn worktree_changes_inner(
396418
state,
397419
flags: ModeFlags::calculate(&previous_state, &state),
398420
},
399-
status_item: Some(change),
400421
},
401422
)
402423
}
@@ -427,19 +448,18 @@ fn worktree_changes_inner(
427448
state,
428449
flags: ModeFlags::calculate(&previous_state, &state),
429450
},
430-
status_item: Some(change),
431451
},
432452
)
433453
}
434454
status::Item::IndexWorktree(index_worktree::Item::Modification {
435455
rela_path,
436-
status: EntryStatus::Conflict { .. },
456+
status: EntryStatus::Conflict { entries, .. },
437457
..
438458
}) => {
459+
index_conflicts.push((rela_path.clone(), entries));
439460
ignored_changes.push(IgnoredWorktreeChange {
440461
path: rela_path,
441462
status: IgnoredWorktreeTreeChangeStatus::Conflict,
442-
status_item: Some(change),
443463
});
444464
continue;
445465
}
@@ -479,7 +499,6 @@ fn worktree_changes_inner(
479499
let mut path_check = gix::status::plumbing::SymlinkCheck::new(
480500
repo.workdir().map(ToOwned::to_owned).context("non-bare")?,
481501
);
482-
let original_changes = tmp.iter().map(|(_, change)| change.clone()).collect();
483502
for (_origin, change) in tmp {
484503
// At this point we know that the current `change` is the tree/index variant
485504
// of a prior change between index/worktree.
@@ -509,17 +528,15 @@ fn worktree_changes_inner(
509528
changes.push(merged);
510529
IgnoredWorktreeTreeChangeStatus::TreeIndex
511530
}
512-
[Some(mut first), Some(mut second)] => {
531+
[Some(first), Some(second)] => {
513532
ignored_changes.push(IgnoredWorktreeChange {
514533
path: first.path.clone(),
515534
status: IgnoredWorktreeTreeChangeStatus::TreeIndex,
516-
status_item: first.status_item.take(),
517535
});
518536
changes.push(first);
519537
ignored_changes.push(IgnoredWorktreeChange {
520538
path: second.path.clone(),
521539
status: IgnoredWorktreeTreeChangeStatus::TreeIndex,
522-
status_item: second.status_item.take(),
523540
});
524541
changes.push(second);
525542
continue;
@@ -528,7 +545,6 @@ fn worktree_changes_inner(
528545
ignored_changes.push(IgnoredWorktreeChange {
529546
path: change_path,
530547
status,
531-
status_item: None,
532548
});
533549
continue;
534550
}
@@ -539,7 +555,8 @@ fn worktree_changes_inner(
539555
Ok(WorktreeChanges {
540556
changes,
541557
ignored_changes,
542-
original_changes,
558+
index_changes,
559+
index_conflicts,
543560
})
544561
}
545562

@@ -698,8 +715,6 @@ fn merge_changes(
698715
status: TreeStatus::Deletion {
699716
previous_state: *previous_state,
700717
},
701-
// NOTE: not relevant, as renames are disabled for snapshots where this is used.
702-
status_item: None,
703718
}));
704719
}
705720
(
@@ -719,8 +734,6 @@ fn merge_changes(
719734
// It's just in the index, which to us doesn't exist.
720735
is_untracked: true,
721736
},
722-
// NOTE: not relevant, as renames are disabled for snapshots where this is used.
723-
status_item: None,
724737
}),
725738
Some(TreeChange {
726739
path: index_wt.path,
@@ -732,8 +745,6 @@ fn merge_changes(
732745
// read the initial state of a file from.
733746
is_untracked: true,
734747
},
735-
// NOTE: not relevant, as renames are disabled for snapshots where this is used.
736-
status_item: None,
737748
}),
738749
]);
739750
}

crates/but-core/src/lib.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
use bstr::BString;
4545
use gix::object::tree::EntryKind;
4646
use gix::refs::FullNameRef;
47+
use gix::status::plumbing::index_as_worktree::ConflictIndexEntry;
4748
use serde::Serialize;
4849
use std::any::Any;
4950
use std::ops::{Deref, DerefMut};
@@ -233,16 +234,12 @@ pub fn open_repo(path: impl Into<PathBuf>) -> anyhow::Result<gix::Repository> {
233234
///
234235
/// For simplicity, copy-tracking is not representable right now, but `copy: bool` could be added
235236
/// if needed. Copy-tracking is deactivated as well.
236-
#[derive(Clone)]
237+
#[derive(Debug, Clone)]
237238
pub struct TreeChange {
238239
/// The *relative* path in the worktree where the entry can be found.
239240
pub path: BString,
240241
/// The specific information about this change.
241242
pub status: TreeStatus,
242-
/// The status item that this change is derived from, used in places that need detailed information.
243-
/// This is only set if this instance was created from a worktree-status, and is `None` when created
244-
/// from a tree-diff.
245-
pub status_item: Option<gix::status::Item>,
246243
}
247244

248245
/// Specifically defines a [`TreeChange`].
@@ -339,10 +336,6 @@ pub struct IgnoredWorktreeChange {
339336
pub path: BString,
340337
/// The status that caused this change to be ignored.
341338
pub status: IgnoredWorktreeTreeChangeStatus,
342-
/// The status item that this change is derived from, used in places that need detailed information.
343-
/// It's `None` if the status item is already present in non-ignored changes.
344-
#[serde(skip)]
345-
pub status_item: Option<gix::status::Item>,
346339
}
347340

348341
/// The type returned by [`worktree_changes()`](diff::worktree_changes).
@@ -352,10 +345,10 @@ pub struct WorktreeChanges {
352345
pub changes: Vec<TreeChange>,
353346
/// 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.
354347
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>,
348+
/// All unprocessed changes to the index.
349+
pub index_changes: Vec<gix::diff::index::Change>,
350+
/// The conflicting index entries, along with their relative path `(rela_path, [Entries(base, ours, theirs)])`.
351+
pub index_conflicts: Vec<(BString, Box<[Option<ConflictIndexEntry>; 3]>)>,
359352
}
360353

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

0 commit comments

Comments
 (0)