From c151b8d2c4a36db76e8a63729e5b42584abbbb6d Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sat, 5 Apr 2025 23:10:41 +0900 Subject: [PATCH 1/3] add minimal test for sorting issues of loose refs (#1928) --- .../make_repo_for_1928_repro.tar | Bin 0 -> 53760 bytes .../fixtures/make_repo_for_1928_repro.sh | 17 ++++++++ gix-ref/tests/refs/file/store/iter.rs | 39 ++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 gix-ref/tests/fixtures/generated-archives/make_repo_for_1928_repro.tar create mode 100755 gix-ref/tests/fixtures/make_repo_for_1928_repro.sh diff --git a/gix-ref/tests/fixtures/generated-archives/make_repo_for_1928_repro.tar b/gix-ref/tests/fixtures/generated-archives/make_repo_for_1928_repro.tar new file mode 100644 index 0000000000000000000000000000000000000000..5b7540170fabaea1608430d297efe451df691ee7 GIT binary patch literal 53760 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 Uzr<=R`&d$7Nr5E=z8nSqAN08Ky#N3J literal 0 HcmV?d00001 diff --git a/gix-ref/tests/fixtures/make_repo_for_1928_repro.sh b/gix-ref/tests/fixtures/make_repo_for_1928_repro.sh new file mode 100755 index 00000000000..445f4107f99 --- /dev/null +++ b/gix-ref/tests/fixtures/make_repo_for_1928_repro.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -eu -o pipefail + +git init -q + +mkdir -p .git/refs/heads/a +cat <.git/packed-refs +# pack-refs with: peeled fully-peeled sorted +1111111111111111111111111111111111111111 refs/heads/a- +2222222222222222222222222222222222222222 refs/heads/a/b +3333333333333333333333333333333333333333 refs/heads/a0 +EOF + +mkdir -p .git/refs/heads/a +echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >.git/refs/heads/a- +echo bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb >.git/refs/heads/a/b +echo cccccccccccccccccccccccccccccccccccccccc >.git/refs/heads/a0 diff --git a/gix-ref/tests/refs/file/store/iter.rs b/gix-ref/tests/refs/file/store/iter.rs index 1d32428f07e..b406d23ccdf 100644 --- a/gix-ref/tests/refs/file/store/iter.rs +++ b/gix-ref/tests/refs/file/store/iter.rs @@ -464,6 +464,45 @@ fn overlay_iter_reproduce_1850() -> crate::Result { Ok(()) } +#[test] +fn overlay_iter_reproduce_1928() -> crate::Result { + let store = store_at("make_repo_for_1928_repro.sh")?; + let ref_names = store + .iter()? + .all()? + .map(|r| r.map(|r| (r.name.as_bstr().to_owned(), r.target))) + .collect::, _>>()?; + insta::assert_debug_snapshot!(ref_names, @r#" + [ + ( + "refs/heads/a-", + Object( + Sha1(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), + ), + ), + ( + "refs/heads/a/b", + Object( + Sha1(2222222222222222222222222222222222222222), + ), + ), + ( + "refs/heads/a0", + Object( + Sha1(cccccccccccccccccccccccccccccccccccccccc), + ), + ), + ( + "refs/heads/a/b", + Object( + Sha1(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + ), + ), + ] + "#); + Ok(()) +} + #[test] fn overlay_iter_with_prefix_wont_allow_absolute_paths() -> crate::Result { let store = store_with_packed_refs()?; From 38b63c2fc9d407b3c634d8b0c72d4d0c104aa5ad Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sat, 5 Apr 2025 21:22:06 +0900 Subject: [PATCH 2/3] fix: make `fs::walkdir_sorted_new()` sort entries by paths literally (#1928) This follows up 7b1b5bf864e74706aefeb1213e8bdb0545d5464a. Since packed-refs appears to be sorted by full ref name, loose-refs should also be emitted in that order. The comparison function is copied from gix::diff::object::tree::EntryRef. Non-utf8 file names are simply mapped to "" on Windows. We could add some fallback, but callers can't handle such file names anyway. --- Cargo.lock | 1 + gix-features/Cargo.toml | 3 ++- gix-features/src/fs.rs | 20 ++++++++++---------- gix-ref/tests/refs/file/store/iter.rs | 24 +++++++++--------------- gix-submodule/tests/file/baseline.rs | 4 ++-- gix/tests/gix/repository/reference.rs | 2 +- 6 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ad802139d5..7986bb76e46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1845,6 +1845,7 @@ dependencies = [ "crossbeam-channel", "document-features", "flate2", + "gix-path 0.10.15", "gix-trace 0.1.12", "gix-utils 0.2.0", "libc", diff --git a/gix-features/Cargo.toml b/gix-features/Cargo.toml index d30d39f2501..29cdad0d9ec 100644 --- a/gix-features/Cargo.toml +++ b/gix-features/Cargo.toml @@ -48,7 +48,7 @@ parallel = ["dep:crossbeam-channel", "dep:parking_lot"] once_cell = ["dep:once_cell"] ## Makes facilities of the `walkdir` crate partially available. ## In conjunction with the **parallel** feature, directory walking will be parallel instead behind a compatible interface. -walkdir = ["dep:walkdir", "dep:gix-utils"] +walkdir = ["dep:walkdir", "dep:gix-path", "dep:gix-utils"] #* an in-memory unidirectional pipe using `bytes` as efficient transfer mechanism. io-pipe = ["dep:bytes"] ## provide a proven and fast `crc32` implementation. @@ -106,6 +106,7 @@ required-features = ["io-pipe"] gix-trace = { version = "^0.1.12", path = "../gix-trace" } # for walkdir +gix-path = { version = "^0.10.15", path = "../gix-path", optional = true } gix-utils = { version = "^0.2.0", path = "../gix-utils", optional = true } # 'parallel' feature diff --git a/gix-features/src/fs.rs b/gix-features/src/fs.rs index 5cf5b7e1afa..f4c4cab97f5 100644 --- a/gix-features/src/fs.rs +++ b/gix-features/src/fs.rs @@ -217,19 +217,19 @@ pub mod walkdir { /// /// Use `precompose_unicode` to represent the `core.precomposeUnicode` configuration option. pub fn walkdir_sorted_new(root: &Path, _: Parallelism, precompose_unicode: bool) -> WalkDir { - fn ft_to_number(ft: std::fs::FileType) -> usize { - if ft.is_file() { - 1 - } else { - 2 - } - } WalkDir { inner: WalkDirImpl::new(root) .sort_by(|a, b| { - ft_to_number(a.file_type()) - .cmp(&ft_to_number(b.file_type())) - .then_with(|| a.file_name().cmp(b.file_name())) + // Ignore non-utf8 file name on Windows, which would probably be rejected by caller. + let a_name = gix_path::os_str_into_bstr(a.file_name()).unwrap_or("".as_ref()); + let b_name = gix_path::os_str_into_bstr(b.file_name()).unwrap_or("".as_ref()); + // "common." < "common/" < "common0" + let common = a_name.len().min(b_name.len()); + a_name[..common].cmp(&b_name[..common]).then_with(|| { + let a = a_name.get(common).or_else(|| a.file_type().is_dir().then_some(&b'/')); + let b = b_name.get(common).or_else(|| b.file_type().is_dir().then_some(&b'/')); + a.cmp(&b) + }) }) .into(), precompose_unicode, diff --git a/gix-ref/tests/refs/file/store/iter.rs b/gix-ref/tests/refs/file/store/iter.rs index b406d23ccdf..211332cddb7 100644 --- a/gix-ref/tests/refs/file/store/iter.rs +++ b/gix-ref/tests/refs/file/store/iter.rs @@ -31,8 +31,8 @@ mod with_namespace { .map(|r: gix_ref::Reference| r.name) .collect::>(); let expected_namespaced_refs = vec![ - "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/heads/multi-link-target1", + "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/remotes/origin/multi-link-target3", "refs/namespaces/bar/refs/tags/multi-link-target2", ]; @@ -50,8 +50,8 @@ mod with_namespace { .map(|r| r.name.into_inner()) .collect::>(), [ - "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/heads/multi-link-target1", + "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/tags/multi-link-target2" ] ); @@ -149,8 +149,8 @@ mod with_namespace { let packed = ns_store.open_packed_buffer()?; let expected_refs = vec![ - "refs/multi-link", "refs/heads/multi-link-target1", + "refs/multi-link", "refs/remotes/origin/multi-link-target3", "refs/tags/multi-link-target2", ]; @@ -198,8 +198,8 @@ mod with_namespace { .map(|r| r.name.into_inner()) .collect::>(), [ - "refs/multi-link", "refs/heads/multi-link-target1", + "refs/multi-link", "refs/tags/multi-link-target2", ], "loose iterators have namespace support as well" @@ -214,8 +214,8 @@ mod with_namespace { .map(|r| r.name.into_inner()) .collect::>(), [ - "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/heads/multi-link-target1", + "refs/namespaces/bar/refs/multi-link", "refs/namespaces/bar/refs/tags/multi-link-target2", "refs/namespaces/foo/refs/remotes/origin/HEAD" ], @@ -291,14 +291,14 @@ fn loose_iter_with_broken_refs() -> crate::Result { ref_paths, vec![ "d1", - "loop-a", - "loop-b", - "multi-link", "heads/A", "heads/d1", "heads/dt1", "heads/main", "heads/multi-link-target1", + "loop-a", + "loop-b", + "multi-link", "remotes/origin/HEAD", "remotes/origin/main", "remotes/origin/multi-link-target3", @@ -483,7 +483,7 @@ fn overlay_iter_reproduce_1928() -> crate::Result { ( "refs/heads/a/b", Object( - Sha1(2222222222222222222222222222222222222222), + Sha1(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), ), ), ( @@ -492,12 +492,6 @@ fn overlay_iter_reproduce_1928() -> crate::Result { Sha1(cccccccccccccccccccccccccccccccccccccccc), ), ), - ( - "refs/heads/a/b", - Object( - Sha1(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - ), - ), ] "#); Ok(()) diff --git a/gix-submodule/tests/file/baseline.rs b/gix-submodule/tests/file/baseline.rs index 8d03b89804f..6971cdb33a7 100644 --- a/gix-submodule/tests/file/baseline.rs +++ b/gix-submodule/tests/file/baseline.rs @@ -24,10 +24,10 @@ fn common_values_and_names_by_path() -> crate::Result { "recursive-clone/submodule/.gitmodules", "relative-clone/.gitmodules", "relative-clone/submodule/.gitmodules", - "super/.gitmodules", - "super/submodule/.gitmodules", "super-clone/.gitmodules", "super-clone/submodule/.gitmodules", + "super/.gitmodules", + "super/submodule/.gitmodules", "top-only-clone/.gitmodules" ] .into_iter() diff --git a/gix/tests/gix/repository/reference.rs b/gix/tests/gix/repository/reference.rs index acea4e016ed..94e9e8574d2 100644 --- a/gix/tests/gix/repository/reference.rs +++ b/gix/tests/gix/repository/reference.rs @@ -102,10 +102,10 @@ mod iter_references { "refs/heads/d1", "refs/heads/dt1", "refs/heads/main", + "refs/heads/multi-link-target1", "refs/loop-a", "refs/loop-b", "refs/multi-link", - "refs/heads/multi-link-target1", "refs/remotes/origin/HEAD", "refs/remotes/origin/main", "refs/remotes/origin/multi-link-target3", From 7e6e7518c78ba925382c0d4654b9e11b4cd641e9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 6 Apr 2025 10:37:36 +0800 Subject: [PATCH 3/3] refactor - make sure we fallback to something *probably* better than the empty string. --- gix-features/src/fs.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/gix-features/src/fs.rs b/gix-features/src/fs.rs index f4c4cab97f5..5fc1a62021b 100644 --- a/gix-features/src/fs.rs +++ b/gix-features/src/fs.rs @@ -4,8 +4,7 @@ //! along with runtime costs for maintaining a global [`rayon`](https://docs.rs/rayon) thread pool. //! //! For information on how to use the [`WalkDir`] type, have a look at -//! * [`jwalk::WalkDir`](https://docs.rs/jwalk/0.5.1/jwalk/type.WalkDir.html) if `parallel` feature is enabled -//! * [walkdir::WalkDir](https://docs.rs/walkdir/2.3.1/walkdir/struct.WalkDir.html) otherwise +// TODO: Move all this to `gix-fs` in a breaking change. #[cfg(feature = "walkdir")] mod shared { @@ -220,9 +219,22 @@ pub mod walkdir { WalkDir { inner: WalkDirImpl::new(root) .sort_by(|a, b| { - // Ignore non-utf8 file name on Windows, which would probably be rejected by caller. - let a_name = gix_path::os_str_into_bstr(a.file_name()).unwrap_or("".as_ref()); - let b_name = gix_path::os_str_into_bstr(b.file_name()).unwrap_or("".as_ref()); + let storage_a; + let storage_b; + let a_name = match gix_path::os_str_into_bstr(a.file_name()) { + Ok(f) => f, + Err(_) => { + storage_a = a.file_name().to_string_lossy(); + storage_a.as_ref().into() + } + }; + let b_name = match gix_path::os_str_into_bstr(b.file_name()) { + Ok(f) => f, + Err(_) => { + storage_b = b.file_name().to_string_lossy(); + storage_b.as_ref().into() + } + }; // "common." < "common/" < "common0" let common = a_name.len().min(b_name.len()); a_name[..common].cmp(&b_name[..common]).then_with(|| {