Skip to content

Commit f635c38

Browse files
committed
improve terminology and documentation
1 parent 8df154b commit f635c38

File tree

5 files changed

+96
-80
lines changed

5 files changed

+96
-80
lines changed

gix-worktree/src/index/status.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//!
1+
//! Compute changes that need to be applied to the ! index to obtain a different
2+
//state (either a worktree or a second index). ! Also computes other related
3+
//information like conflicts/added files and provides ! everything necessary
4+
//for `gix diff`/`git status` (when not both arguments are revisions) ! and
5+
//dirtiness checks that are run before commands like `git merge`/`git rebase`
26

37
use bstr::BStr;
48

@@ -12,14 +16,14 @@ pub mod index;
1216
pub mod recorder;
1317

1418
///
15-
pub mod diff;
19+
pub mod content;
1620

1721
/// The status of an index entry in a worktree
1822
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
19-
pub enum Status<T = ()> {
23+
pub enum Change<T = ()> {
2024
#[default]
2125
/// The file in the worktree is identical to the index entry
22-
Unchanged,
26+
None,
2327
/// An index entry has no corresponding file in the worktree.
2428
Removed,
2529
/// The type of file changed (symlink <=> file) performing a
@@ -36,25 +40,44 @@ pub enum Status<T = ()> {
3640
/// which is a significant change itself (for git status)
3741
/// these files don't need to be rechanged
3842
executable_bit_changed: bool,
39-
/// The output of the diff run on this entry.
43+
/// The output of the [`ContentComparison`] run on this entry.
4044
/// if the there is no content change and only the executable bit
4145
/// changed than this is `None`
42-
diff: Option<T>,
46+
content_change: Option<T>,
4347
},
4448
/// An index entry that correspond to an untracked worktree file marked with `git add`
4549
Added,
4650
}
4751

48-
///
52+
/// Collects the changes produced by comparing an index entry to
53+
/// the worktree (or another index)
4954
pub trait Collector<'index>: Send {
5055
/// Data generated by comparing two files/entries
51-
type Diff;
56+
type ContentChange;
5257
///
5358
fn visit_entry(
5459
&mut self,
5560
entry: &'index gix_index::Entry,
5661
path: &'index BStr,
57-
status: Status<Self::Diff>,
62+
status: Change<Self::ContentChange>,
5863
conflict: bool,
5964
);
6065
}
66+
67+
/// Compares the content of two blobs while performing a diff
68+
pub trait ContentComparison: Send + Sync {
69+
/// Output data produced by this
70+
type Output;
71+
/// Compares an index entry to a different blob. The size of the blob
72+
/// and a lazy handle to read its data (from disk or ODB) is provided. If
73+
/// this function returns `None` the entry and the blob are assumed to be
74+
/// identical if this assumption is broken by a faulty implementation then
75+
/// the index state can be messed up
76+
fn compare_blob<'a, E>(
77+
&self,
78+
entry: &'a gix_index::Entry,
79+
blob_size: usize,
80+
blob: impl content::LazyBlob<'a, E>,
81+
resolve_oid: impl FnMut(gix_hash::ObjectId) -> Result<&'a [u8], E>,
82+
) -> Result<Option<Self::Output>, E>;
83+
}

gix-worktree/src/index/status/diff.rs renamed to gix-worktree/src/index/status/content.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,21 @@ use gix_index as index;
44
use gix_object::encode::loose_header;
55
use index::Entry;
66

7-
///
7+
use crate::index::status::ContentComparison;
8+
9+
/// Lazy borrwoed access to blob data from disk or ODB
810
pub trait LazyBlob<'a, E> {
9-
///
1011
fn read(self) -> Result<&'a [u8], E>;
1112
}
1213

13-
///
14-
pub trait Diff: Send + Sync {
15-
///
16-
type Output;
17-
///
18-
fn content_changed<'a, E>(
19-
&self,
20-
entry: &'a Entry,
21-
blob_size: usize,
22-
blob: impl LazyBlob<'a, E>,
23-
resolve_oid: impl FnMut(gix_hash::ObjectId) -> Result<&'a [u8], E>,
24-
) -> Result<Option<Self::Output>, E>;
25-
}
26-
27-
/// compares to blobs by comparing their size and oid, only looks at the file if
14+
/// Compares to blobs by comparing their size and oid, only looks at the file if
2815
/// the size matches, therefore very fast
29-
pub struct Fast;
16+
pub struct FastEq;
3017

31-
impl Diff for Fast {
18+
impl ContentComparison for FastEq {
3219
type Output = ();
3320

34-
fn content_changed<'a, E>(
21+
fn compare_blob<'a, E>(
3522
&self,
3623
entry: &'a Entry,
3724
blob_size: usize,
@@ -58,12 +45,12 @@ impl Diff for Fast {
5845
/// Compares files to blobs by comparing their oids. Same as [`Fast`] but does
5946
/// not contain a fast path for files with mismatched files and therefore always
6047
/// returns an OID that can be reused later
61-
pub struct Hash;
48+
pub struct HashEq;
6249

63-
impl Diff for Hash {
50+
impl ContentComparison for HashEq {
6451
type Output = ObjectId;
6552

66-
fn content_changed<'a, E>(
53+
fn compare_blob<'a, E>(
6754
&self,
6855
entry: &'a Entry,
6956
_blob_size: usize,

gix-worktree/src/index/status/recorder.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@ use bstr::BStr;
22

33
use gix_index as index;
44

5-
use crate::index::status::{Collector, Status};
5+
use crate::index::status::{Collector, Change};
66

77
///
88
#[derive(Debug, Default)]
99
pub struct Recorder<'index, T = ()> {
1010
/// collected records, unchanged fields are excluded
11-
pub records: Vec<(&'index BStr, Status<T>, bool)>,
11+
pub records: Vec<(&'index BStr, Change<T>, bool)>,
1212
}
1313

1414
impl<'index, T: Send> Collector<'index> for Recorder<'index, T> {
15-
type Diff = T;
15+
type ContentChange = T;
1616

1717
fn visit_entry(
1818
&mut self,
1919
_entry: &'index index::Entry,
2020
path: &'index BStr,
21-
status: Status<Self::Diff>,
21+
status: Change<Self::ContentChange>,
2222
conflict: bool,
2323
) {
24-
if !matches!(status, Status::Unchanged) {
24+
if !matches!(status, Change::None) {
2525
self.records.push((path, status, conflict))
2626
}
2727
}

gix-worktree/src/index/status/worktree.rs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::io;
22
use std::marker::PhantomData;
33
use std::path::Path;
44

5-
use crate::index::status::diff::{self, Diff};
6-
use crate::index::status::{Collector, Status};
5+
use crate::index::status::content::{self, ContentComparison};
6+
use crate::index::status::{Change, Collector};
77
use crate::{fs, read};
88
use bstr::BStr;
99
use filetime::FileTime;
@@ -62,12 +62,18 @@ impl Default for Options {
6262
}
6363
}
6464

65-
/// Calculates the status of worktree
66-
pub fn status<'index, T: Send>(
65+
/// Calculates the changes that need to be applied to an index to obtain a
66+
/// worktree. Note that this isn't technically quite what this function does
67+
/// as this also provides some additional information (whether a file has
68+
/// conflicts) and files that were added with `git add` are shown as a special
69+
/// changes despite not technically requiring a change to the index (since `gid
70+
/// add` already added the file to the index) but the naming matches the intuition
71+
/// of a git user (and matches `git status`/git diff`)
72+
pub fn changes_to_obtain<'index, T: Send>(
6773
index: &'index mut index::State,
6874
worktree: &Path,
69-
collector: &mut impl Collector<'index, Diff = T>,
70-
diff: &impl Diff<Output = T>,
75+
collector: &mut impl Collector<'index, ContentChange = T>,
76+
diff: &impl ContentComparison<Output = T>,
7177
options: Options,
7278
) -> Result<(), Error> {
7379
// the order is absoluty critical here
@@ -116,13 +122,13 @@ struct State<'a, 'b> {
116122
options: &'a Options,
117123
}
118124

119-
type StatusResult<'index, T> = Result<(&'index index::Entry, &'index BStr, Status<T>, bool), Error>;
125+
type StatusResult<'index, T> = Result<(&'index index::Entry, &'index BStr, Change<T>, bool), Error>;
120126

121127
impl<'index> State<'_, 'index> {
122128
fn process<T>(
123129
&mut self,
124130
entry: &'index mut index::Entry,
125-
diff: &impl Diff<Output = T>,
131+
diff: &impl ContentComparison<Output = T>,
126132
) -> Option<StatusResult<'index, T>> {
127133
let conflict = match entry.stage() {
128134
0 => false,
@@ -146,8 +152,8 @@ impl<'index> State<'_, 'index> {
146152
&mut self,
147153
entry: &mut index::Entry,
148154
git_path: &BStr,
149-
diff: &impl Diff<Output = T>,
150-
) -> Result<Status<T>, Error> {
155+
diff: &impl ContentComparison<Output = T>,
156+
) -> Result<Change<T>, Error> {
151157
// TODO fs caache
152158
let worktree_path = path::try_from_bstr(git_path).map_err(|_| Error::IllformedUtf8)?;
153159
let worktree_path = self.worktree.join(worktree_path);
@@ -163,24 +169,24 @@ impl<'index> State<'_, 'index> {
163169
// TODO: submodules:
164170
// if entry.mode.contains(Mode::COMMIT) &&
165171
// resolve_gitlink_ref(ce->name, "HEAD", &sub))
166-
return Ok(Status::Removed);
172+
return Ok(Change::Removed);
167173
}
168174
Ok(metadata) => metadata,
169-
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(Status::Removed),
175+
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(Change::Removed),
170176
Err(err) => {
171177
return Err(err.into());
172178
}
173179
};
174180
if self.options.check_added && entry.flags.contains(index::entry::Flags::INTENT_TO_ADD) {
175-
return Ok(Status::Added);
181+
return Ok(Change::Added);
176182
}
177183
let new_stat = index::entry::Stat::from_fs(&metadata)?;
178184
let executable_bit_changed =
179185
match entry
180186
.mode
181187
.change_to_match_fs(&metadata, self.options.fs.symlink, self.options.fs.executable_bit)
182188
{
183-
Some(index::entry::mode::Change::Type { .. }) => return Ok(Status::TypeChange),
189+
Some(index::entry::mode::Change::Type { .. }) => return Ok(Change::TypeChange),
184190
Some(index::entry::mode::Change::ExecutableBit) => true,
185191
None => false,
186192
};
@@ -202,7 +208,7 @@ impl<'index> State<'_, 'index> {
202208
{
203209
racy_clean = new_stat.is_racy(self.timestamp, self.options.stat);
204210
if !racy_clean {
205-
return Ok(Status::Unchanged);
211+
return Ok(Change::None);
206212
}
207213
}
208214

@@ -219,15 +225,15 @@ impl<'index> State<'_, 'index> {
219225
entry.stat.size = 0;
220226
}
221227
if diff.is_some() || executable_bit_changed {
222-
Ok(Status::Modified {
228+
Ok(Change::Modified {
223229
executable_bit_changed,
224-
diff,
230+
content_change: diff,
225231
})
226232
} else {
227233
// don't diff against this file next time since
228234
// we know the file is unchanged
229235
entry.stat = new_stat;
230-
Ok(Status::Unchanged)
236+
Ok(Change::None)
231237
}
232238
}
233239
}
@@ -237,7 +243,7 @@ struct Reducer<'a, 'index, T: Collector<'index>> {
237243
phantom: PhantomData<fn(&'index ())>,
238244
}
239245

240-
impl<'index, T, C: Collector<'index, Diff = T>> Reduce for Reducer<'_, 'index, C> {
246+
impl<'index, T, C: Collector<'index, ContentChange = T>> Reduce for Reducer<'_, 'index, C> {
241247
type Input = Vec<StatusResult<'index, T>>;
242248

243249
type FeedProduce = ();
@@ -265,7 +271,7 @@ struct WorktreeFile<'a> {
265271
options: &'a Options,
266272
}
267273

268-
impl<'a> diff::LazyBlob<'a, Error> for WorktreeFile<'a> {
274+
impl<'a> content::LazyBlob<'a, Error> for WorktreeFile<'a> {
269275
fn read(self) -> Result<&'a [u8], Error> {
270276
let res = read::data_to_buf_with_meta(
271277
self.path,

0 commit comments

Comments
 (0)