Skip to content

Commit 3753592

Browse files
committed
assure submodule status doesn't operate if there is no worktree checkout
1 parent da45d92 commit 3753592

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

gix/src/submodule/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ pub mod status {
382382
return Ok(status);
383383
}
384384

385+
if !state.worktree_checkout {
386+
return Ok(status);
387+
}
385388
let statusses = adjust_options(sm_repo.status(gix_features::progress::Discard)?)
386389
.index_worktree_options_mut(|opts| {
387390
if ignore == config::Ignore::Untracked {
@@ -408,7 +411,7 @@ pub mod status {
408411
/// Return `None` if the repository clone or the worktree are missing entirely, which would leave
409412
/// it to the caller to determine if that's considered dirty or not.
410413
pub fn is_dirty(&self) -> Option<bool> {
411-
if !self.state.worktree_checkout && !self.state.repository_exists {
414+
if !self.state.worktree_checkout || !self.state.repository_exists {
412415
return None;
413416
}
414417
let is_dirty =
Binary file not shown.

gix/tests/fixtures/make_submodules.sh

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ git init submodule-head-changed
2121
cd m1 && git checkout @~1
2222
)
2323

24+
git init submodule-head-changed-no-worktree
25+
(cd submodule-head-changed-no-worktree
26+
git submodule add ../module1 m1
27+
git commit -m "add submodule"
28+
29+
(cd m1 && git checkout @~1)
30+
rm -Rf m1 && mkdir m1
31+
)
32+
2433
git init modified-and-untracked
2534
(cd modified-and-untracked
2635
git submodule add ../module1 m1

gix/tests/submodule/mod.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ mod open {
6363
worktree_checkout: false,
6464
superproject_configuration: true,
6565
},
66-
Some(true),
66+
None,
6767
)],
6868
),
6969
] {
@@ -241,6 +241,39 @@ mod open {
241241
Ok(())
242242
}
243243

244+
#[test]
245+
fn changed_head_empty_worktree() -> crate::Result {
246+
let repo = repo("submodule-head-changed-no-worktree")?;
247+
let sm = repo.submodules()?.into_iter().flatten().next().expect("one submodule");
248+
249+
let status = sm.status(gix::submodule::config::Ignore::None, false)?;
250+
assert_eq!(
251+
status.state,
252+
gix::submodule::State {
253+
repository_exists: true,
254+
is_old_form: false,
255+
worktree_checkout: false,
256+
superproject_configuration: true,
257+
}
258+
);
259+
assert_eq!(
260+
status.is_dirty(),
261+
None,
262+
"a missing worktree counts as no-dirty, even though the checked out HEAD changed. \
263+
Git does the same, even though as we express it as 'not determined'"
264+
);
265+
assert_ne!(
266+
status.index_id, status.checked_out_head_id,
267+
"not considered dirty despite head mismatch"
268+
);
269+
assert!(
270+
status.changes.is_none(),
271+
"Detailed changes are never done if there is no worktree"
272+
);
273+
274+
Ok(())
275+
}
276+
244277
#[test]
245278
fn is_dirty_skips_expensive_checks() -> crate::Result {
246279
let repo = repo("submodule-head-changed-and-modified")?;

0 commit comments

Comments
 (0)