Skip to content

Commit 8fe6e86

Browse files
committed
fix: Submodule::status() now konws about tree-index changes as well.
This completes the status implementation.
1 parent 3eadb0e commit 8fe6e86

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

gix/src/submodule/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ pub mod status {
323323
/// Return the status of the submodule, just like [`status`](Self::status), but allows to adjust options
324324
/// for more control over how the status is performed.
325325
///
326+
/// If `check_dirty` is `true`, the computation will stop once the first in a ladder operations
327+
/// ordered from cheap to expensive shows that the submodule is dirty. When checking for detailed
328+
/// status information (i.e. untracked file, modifications, HEAD-index changes) only the first change
329+
/// will be kept to stop as early as possible.
330+
///
326331
/// Use `&mut std::convert::identity` for `adjust_options` if no specific options are desired.
327332
/// A reason to change them might be to enable sorting to enjoy deterministic order of changes.
328333
///
@@ -389,6 +394,9 @@ pub mod status {
389394
let mut changes = Vec::new();
390395
for change in statuses {
391396
changes.push(change?);
397+
if check_dirty {
398+
break;
399+
}
392400
}
393401
status.changes = Some(changes);
394402
Ok(status)
Binary file not shown.

gix/tests/fixtures/make_submodules.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ git init submodule-head-changed
2121
cd m1 && git checkout @~1
2222
)
2323

24+
git init submodule-index-changed
25+
(cd submodule-index-changed
26+
git submodule add ../module1 m1
27+
git commit -m "add submodule"
28+
29+
(cd m1
30+
git mv subdir subdir-renamed
31+
git mv this that
32+
)
33+
)
34+
2435
git init submodule-head-changed-no-worktree
2536
(cd submodule-head-changed-no-worktree
2637
git submodule add ../module1 m1

gix/tests/gix/submodule.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,37 @@ mod open {
186186
Ok(())
187187
}
188188

189+
#[test]
190+
fn modified_in_index_only() -> crate::Result {
191+
let repo = repo("submodule-index-changed")?;
192+
let sm = repo.submodules()?.into_iter().flatten().next().expect("one submodule");
193+
194+
for mode in [
195+
gix::submodule::config::Ignore::Untracked,
196+
gix::submodule::config::Ignore::None,
197+
] {
198+
for check_dirty in [false, true] {
199+
let status = sm.status_opts(mode, check_dirty, &mut |platform| platform)?;
200+
assert_eq!(
201+
status.is_dirty(),
202+
Some(true),
203+
"two files were renamed using `git mv` for an HEAD^{{tree}}-index change"
204+
);
205+
assert_eq!(
206+
status.changes.expect("present").len(),
207+
if check_dirty { 1 } else { 3 },
208+
"in is-dirty mode, we don't collect all changes"
209+
);
210+
}
211+
}
212+
213+
assert!(
214+
repo.is_dirty()?,
215+
"superproject should see submodule changes in the index as well"
216+
);
217+
Ok(())
218+
}
219+
189220
#[test]
190221
fn modified_and_untracked() -> crate::Result {
191222
let repo = repo("modified-and-untracked")?;
@@ -194,7 +225,7 @@ mod open {
194225
let status = sm.status(gix::submodule::config::Ignore::Dirty, false)?;
195226
assert_eq!(status.is_dirty(), Some(false), "Dirty skips worktree changes entirely");
196227

197-
let status = sm.status_opts(
228+
let mut status = sm.status_opts(
198229
gix::submodule::config::Ignore::None,
199230
false,
200231
&mut |status: gix::status::Platform<'_, gix::progress::Discard>| {
@@ -217,16 +248,18 @@ mod open {
217248

218249
let status_with_dirty_check = sm.status_opts(
219250
gix::submodule::config::Ignore::None,
220-
true,
251+
true, /* check-dirty */
221252
&mut |status: gix::status::Platform<'_, gix::progress::Discard>| {
222253
status.index_worktree_options_mut(|opts| {
223254
opts.sorting = Some(gix_status::index_as_worktree_with_renames::Sorting::ByPathCaseSensitive);
224255
})
225256
},
226257
)?;
258+
status.changes.as_mut().expect("two changes").pop();
227259
assert_eq!(
228260
status_with_dirty_check, status,
229-
"it cannot abort early as the only change it sees is the modification check"
261+
"it cannot abort early as the only change it sees is the modification check.\
262+
However, with check-dirty, it would only gather the changes"
230263
);
231264

232265
let status = sm.status(gix::submodule::config::Ignore::Untracked, false)?;

0 commit comments

Comments
 (0)