Skip to content

Commit dad2a82

Browse files
authored
Merge pull request #2437 from GitoxideLabs/copilot/fix-issue-2435-in-gix-crate
status: ignore assume-unchanged submodule paths replaced by symlinks
2 parents 6a7287c + 34d3c17 commit dad2a82

6 files changed

Lines changed: 124 additions & 2 deletions

File tree

gix-dir/src/walk/classify.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,23 @@ fn resolve_file_type_with_index(
372372
None
373373
};
374374
(
375-
kind.filter(|_| entry.flags.contains(gix_index::entry::Flags::UPTODATE)),
375+
kind.filter(|_| {
376+
entry
377+
.flags
378+
.intersects(gix_index::entry::Flags::UPTODATE | gix_index::entry::Flags::ASSUME_VALID)
379+
}),
376380
kind,
377381
)
378382
}
379383

380384
fn icase_directory_to_kinds(dir: Option<&gix_index::Entry>) -> (Option<entry::Kind>, Option<entry::Kind>) {
381385
let index_kind = dir.map(|_| entry::Kind::Directory);
382386
let uptodate_kind = dir
383-
.filter(|entry| entry.flags.contains(gix_index::entry::Flags::UPTODATE))
387+
.filter(|entry| {
388+
entry
389+
.flags
390+
.intersects(gix_index::entry::Flags::UPTODATE | gix_index::entry::Flags::ASSUME_VALID)
391+
})
384392
.map(|_| entry::Kind::Directory);
385393
(uptodate_kind, index_kind)
386394
}

gix-dir/tests/dir/walk.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,67 @@ fn root_may_be_a_symlink_if_it_is_the_worktree() -> crate::Result {
245245
Ok(())
246246
}
247247

248+
#[test]
249+
#[cfg(unix)]
250+
fn assume_unchanged_submodule_replaced_with_symlink_is_hidden() -> crate::Result {
251+
let root = fixture_in("many-symlinks", "submodule-assume-unchanged-symlink");
252+
let ((out, _root), entries) = try_collect_filtered_opts_collect(
253+
&root,
254+
None,
255+
|keep, ctx| walk(&root, ctx, options(), keep),
256+
None::<&str>,
257+
Options {
258+
fresh_index: false,
259+
..Default::default()
260+
},
261+
)?;
262+
263+
assert_eq!(
264+
out,
265+
walk::Outcome {
266+
read_dir_calls: 1,
267+
returned_entries: entries.len(),
268+
seen_entries: 3,
269+
}
270+
);
271+
assert!(
272+
entries.is_empty(),
273+
"assume-unchanged entries should use index type information and stay hidden"
274+
);
275+
Ok(())
276+
}
277+
278+
#[test]
279+
#[cfg(unix)]
280+
fn submodule_replaced_with_symlink_without_assume_unchanged_is_untracked() -> crate::Result {
281+
let root = fixture_in("many-symlinks", "submodule-symlink");
282+
let ((out, _root), entries) = try_collect_filtered_opts_collect(
283+
&root,
284+
None,
285+
|keep, ctx| walk(&root, ctx, options(), keep),
286+
None::<&str>,
287+
Options {
288+
fresh_index: false,
289+
..Default::default()
290+
},
291+
)?;
292+
293+
assert_eq!(
294+
out,
295+
walk::Outcome {
296+
read_dir_calls: 1,
297+
returned_entries: entries.len(),
298+
seen_entries: 3,
299+
}
300+
);
301+
assert_eq!(
302+
entries,
303+
[entry("sub", Untracked, Symlink).with_index_kind(Repository)],
304+
"without assume-unchanged, the replaced submodule appears as an untracked symlink"
305+
);
306+
Ok(())
307+
}
308+
248309
#[test]
249310
fn should_interrupt_works_even_in_empty_directories() {
250311
let root = fixture("empty");

gix-dir/tests/fixtures/many-symlinks.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,27 @@ EOF
4242
)
4343

4444
ln -s excluded-symlinks-to-dir worktree-root-is-symlink
45+
46+
git init -q module
47+
(cd module
48+
touch this
49+
git add this
50+
git commit -q -m c1
51+
)
52+
53+
git init -q submodule-assume-unchanged-symlink
54+
(cd submodule-assume-unchanged-symlink
55+
git submodule add ../module sub
56+
git commit -q -m "add submodule"
57+
git update-index --assume-unchanged sub
58+
rm -Rf sub
59+
ln -s ../module sub
60+
)
61+
62+
git init -q submodule-symlink
63+
(cd submodule-symlink
64+
git submodule add ../module sub
65+
git commit -q -m "add submodule"
66+
rm -Rf sub
67+
ln -s ../module sub
68+
)
176 KB
Binary file not shown.

gix/tests/fixtures/make_status_repos.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,19 @@ git init symlink-replaces-tracked-dir
5353
rm -rf tracked
5454
ln -s target tracked
5555
)
56+
57+
git init -q module
58+
(cd module
59+
touch this
60+
git add this
61+
git commit -q -m c1
62+
)
63+
64+
git init -q submodule-assume-unchanged-symlink
65+
(cd submodule-assume-unchanged-symlink
66+
git submodule add ../module sub
67+
git commit -q -m "add submodule"
68+
git update-index --assume-unchanged sub
69+
rm -Rf sub
70+
ln -s ../module sub
71+
)

gix/tests/gix/status.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,19 @@ mod into_iter {
265265
Ok(())
266266
}
267267

268+
#[test]
269+
#[cfg(unix)]
270+
fn submodule_assume_unchanged_replaced_with_symlink_is_ignored() -> crate::Result {
271+
let repo = repo("submodule-assume-unchanged-symlink")?;
272+
let mut status = repo.status(gix::progress::Discard)?.into_iter(None)?;
273+
let items: Vec<_> = status.by_ref().filter_map(Result::ok).collect();
274+
assert!(
275+
items.is_empty(),
276+
"assume-unchanged submodule should not show up in status"
277+
);
278+
Ok(())
279+
}
280+
268281
#[test]
269282
fn error_during_tree_traversal_causes_failure() -> crate::Result {
270283
let repo = repo("untracked-only")?;

0 commit comments

Comments
 (0)