Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn stream(
.ok_or_else(|| anyhow!("Adding files requires a worktree directory that contains them"))?,
)?;
for path in add_paths {
stream.add_entry_from_path(&root, &gix::path::realpath(&path)?)?;
stream.add_entry_from_path(&root, &gix::path::realpath(&path)?, repo.object_hash())?;
}
}
for (path, content) in files {
Expand Down
9 changes: 5 additions & 4 deletions gix-archive/tests/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,12 @@ mod from_tree {
.map(|_| ())
},
);
let hash_kind = gix_testtools::hash_kind_from_env().unwrap_or_default();
stream
.add_entry_from_path(&dir, &dir.join("extra-file"))?
.add_entry_from_path(&dir, &dir.join("extra-exe"))?
.add_entry_from_path(&dir, &dir.join("extra-dir-empty"))?
.add_entry_from_path(&dir, &dir.join("extra-dir").join("symlink-to-extra"))?;
.add_entry_from_path(&dir, &dir.join("extra-file"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-exe"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-dir-empty"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-dir").join("symlink-to-extra"), hash_kind)?;

let mut buf = Vec::new();
if format == Format::InternalTransientNonPersistable {
Expand Down
2 changes: 1 addition & 1 deletion gix-odb/src/store_impls/dynamic/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl TryFrom<&super::Store> for super::Store {
&mut s.replacements(),
crate::store::init::Options {
slots: crate::store::init::Slots::Given(s.files.len().try_into().expect("BUG: too many slots")),
object_hash: Default::default(),
object_hash: s.object_hash,
use_multi_pack_index: false,
alloc_limit_bytes: s.alloc_limit_bytes,
current_dir: s.current_dir.clone().into(),
Expand Down
3 changes: 3 additions & 0 deletions gix-worktree-stream/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ doctest = false
[features]
## Enable support for the SHA-1 hash by forwarding the feature to dependencies.
sha1 = ["gix-filter/sha1", "gix-hash/sha1", "gix-object/sha1", "gix-traverse/sha1"]
## Enable support for the SHA-256 hash by forwarding the feature to dependencies.
sha256 = ["gix-hash/sha256"]

[dependencies]
gix-features = { version = "^0.47.0", path = "../gix-features", features = ["progress", "io-pipe"] }
Expand All @@ -33,6 +35,7 @@ parking_lot = "0.12.4"

[dev-dependencies]
gix-testtools = { path = "../tests/tools" }
gix-hash = { version = "^0.24.0", path = "../gix-hash", features = ["sha1", "sha256"] }
gix-odb = { path = "../gix-odb" }
gix-worktree = { path = "../gix-worktree", default-features = false, features = ["attributes"] }

Expand Down
9 changes: 7 additions & 2 deletions gix-worktree-stream/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,16 @@ impl Stream {
///
/// Note that the created entries will always have a null SHA1, and that we access this path
/// to determine its type, and will access it again when it is requested.
pub fn add_entry_from_path(&mut self, root: &Path, path: &Path) -> std::io::Result<&mut Self> {
pub fn add_entry_from_path(
&mut self,
root: &Path,
path: &Path,
hash_kind: gix_hash::Kind,
) -> std::io::Result<&mut Self> {
let rela_path = path.strip_prefix(root).map_err(std::io::Error::other)?;
let meta = path.symlink_metadata()?;
let relative_path = gix_path::to_unix_separators_on_windows(gix_path::into_bstr(rela_path)).into_owned();
let id = gix_hash::ObjectId::null(gix_hash::Kind::Sha1);
let id = hash_kind.null();

let entry = if meta.is_symlink() {
let content = std::fs::read_link(path)?;
Expand Down
4 changes: 4 additions & 0 deletions gix-worktree-stream/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ pub(crate) fn write_stream(
fn byte_to_hash(b: u8) -> gix_hash::Kind {
match b {
0 => gix_hash::Kind::Sha1,
#[cfg(feature = "sha256")]
1 => gix_hash::Kind::Sha256,
_ => unreachable!("BUG: we control the protocol"),
}
}
Expand All @@ -111,6 +113,8 @@ fn byte_to_mode(b: u8) -> gix_object::tree::EntryMode {
fn hash_to_byte(h: gix_hash::Kind) -> u8 {
match h {
gix_hash::Kind::Sha1 => 0,
#[cfg(feature = "sha256")]
gix_hash::Kind::Sha256 => 1,
_ => unreachable!("BUG: not implemented for hash kind {h}"),
}
}
Expand Down
117 changes: 73 additions & 44 deletions gix-worktree-stream/tests/stream.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/// Convert a hexadecimal hash into its corresponding `ObjectId` or _panic_.
fn hex_to_id(hex: &str) -> gix_hash::ObjectId {
gix_hash::ObjectId::from_hex(hex.as_bytes()).expect("40 bytes hex")
fn hex_to_id(hex_sha1: &str, hex_sha256: &str) -> gix_hash::ObjectId {
match gix_testtools::hash_kind_from_env().unwrap_or_default() {
gix_hash::Kind::Sha1 => gix_hash::ObjectId::from_hex(hex_sha1.as_bytes()).expect("40 bytes hex"),
gix_hash::Kind::Sha256 => gix_hash::ObjectId::from_hex(hex_sha256.as_bytes()).expect("64 bytes hex"),
_ => unimplemented!(),
}
}

mod from_tree {
Expand Down Expand Up @@ -35,7 +39,7 @@ mod from_tree {
#[test]
fn can_receive_err_if_root_is_not_found() {
let mut stream = gix_worktree_stream::from_tree(
gix_hash::Kind::Sha1.null(),
gix_testtools::hash_kind_from_env().unwrap_or_default().null(),
FailObjectRetrieval,
mutating_pipeline(false),
|_, _, _| -> Result<_, Infallible> { unreachable!("must not be called") },
Expand All @@ -58,11 +62,6 @@ mod from_tree {
Ok(())
}

#[cfg(target_pointer_width = "64")]
const EXPECTED_BUFFER_LENGTH: usize = 320302;
#[cfg(target_pointer_width = "32")]
const EXPECTED_BUFFER_LENGTH: usize = 320198;

#[test]
fn will_provide_all_information_and_respect_export_ignore() -> gix_testtools::Result {
let (dir, head_tree, odb, mut cache) = basic()?;
Expand All @@ -77,12 +76,13 @@ mod from_tree {
.map(|_| ())
},
);
let hash_kind = gix_testtools::hash_kind_from_env().unwrap_or_default();
stream
.add_entry_from_path(&dir, &dir.join("extra-file"))?
.add_entry_from_path(&dir, &dir.join("extra-bigfile"))?
.add_entry_from_path(&dir, &dir.join("extra-exe"))?
.add_entry_from_path(&dir, &dir.join("extra-dir-empty"))?
.add_entry_from_path(&dir, &dir.join("extra-dir").join("symlink-to-extra"))?;
.add_entry_from_path(&dir, &dir.join("extra-file"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-bigfile"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-exe"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-dir-empty"), hash_kind)?
.add_entry_from_path(&dir, &dir.join("extra-dir").join("symlink-to-extra"), hash_kind)?;

let tee_read = TeeToMemory {
read: stream.into_read(),
Expand Down Expand Up @@ -121,77 +121,99 @@ mod from_tree {
(
".gitattributes".into(),
EntryKind::Blob,
hex_to_id("45c160c35c17ad264b96431cceb9793160396e99")
hex_to_id(
"45c160c35c17ad264b96431cceb9793160396e99",
"e34ae8e2c517230c6c613202a955b5f2095567830de5c3bb7081d72f1af393dd"
)
),
(
"a".into(),
EntryKind::Blob,
hex_to_id("45b983be36b73c0788dc9cbcb76cbb80fc7bb057")
hex_to_id(
"45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
"96c18f0297e38d01f4b2dacddea4259aea6b2961eb0822bd2c0c3f6029030045"
)
),
(
"bigfile".into(),
EntryKind::Blob,
hex_to_id("4995fde49ed64e043977e22539f66a0d372dd129")
hex_to_id(
"4995fde49ed64e043977e22539f66a0d372dd129",
"527a170c0c29520af58bf61a383c4e99a7a7c63c0475cbb630cf98d38d6c0dce"
)
),
(
"symlink-to-a".into(),
EntryKind::Link,
hex_to_id("2e65efe2a145dda7ee51d1741299f848e5bf752e")
hex_to_id(
"2e65efe2a145dda7ee51d1741299f848e5bf752e",
"eb337bcee2061c5313c9a1392116b6c76039e9e30d71467ae359b36277e17dc7"
)
),
(
"dir/.gitattributes".into(),
EntryKind::Blob,
hex_to_id("81b9a375276405703e05be6cecf0fc1c8b8eed64")
hex_to_id(
"81b9a375276405703e05be6cecf0fc1c8b8eed64",
"4b74474eca46ad7e1807afe8855e7a511d132b314d3d0f481bb55a331b249fb7"
)
),
(
"dir/b".into(),
EntryKind::Blob,
hex_to_id("ab4a98190cf776b43cb0fe57cef231fb93fd07e6")
hex_to_id(
"ab4a98190cf776b43cb0fe57cef231fb93fd07e6",
"cf84f9ae227fa5c481dacd97f6d6506de727dabd30377c6907f623ef1192637a"
)
),
(
"dir/subdir/exe".into(),
EntryKind::BlobExecutable,
hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
hex_to_id(
"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
"473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"
)
),
(
"dir/subdir/streamed".into(),
EntryKind::Blob,
hex_to_id("08991f58f4de5d85b61c0f87f3ac053c79d0e739")
),
(
"extra-file".into(),
EntryKind::Blob,
hex_to_id("0000000000000000000000000000000000000000")
),
(
"extra-bigfile".into(),
EntryKind::Blob,
hex_to_id("0000000000000000000000000000000000000000")
hex_to_id(
"08991f58f4de5d85b61c0f87f3ac053c79d0e739",
"8c13ad7df9686daf00357f34700922485802cb0be33e684ec5171f7d0d8a84fd"
)
),
("extra-file".into(), EntryKind::Blob, hash_kind.null()),
("extra-bigfile".into(), EntryKind::Blob, hash_kind.null()),
(
"extra-exe".into(),
if cfg!(windows) {
EntryKind::Blob
} else {
EntryKind::BlobExecutable
},
hex_to_id("0000000000000000000000000000000000000000")
),
(
"extra-dir-empty".into(),
EntryKind::Tree,
hex_to_id("0000000000000000000000000000000000000000")
hash_kind.null()
),
(
"extra-dir/symlink-to-extra".into(),
EntryKind::Link,
hex_to_id("0000000000000000000000000000000000000000")
)
("extra-dir-empty".into(), EntryKind::Tree, hash_kind.null()),
("extra-dir/symlink-to-extra".into(), EntryKind::Link, hash_kind.null())
]
);

#[cfg(target_pointer_width = "64")]
let expected_buffer_length: usize = match gix_testtools::hash_kind_from_env().unwrap_or_default() {
gix_hash::Kind::Sha1 => 320302,
gix_hash::Kind::Sha256 => 320458,
_ => unimplemented!(),
};
#[cfg(target_pointer_width = "32")]
let expected_buffer_length: usize = match gix_testtools::hash_kind_from_env().unwrap_or_default() {
gix_hash::Kind::Sha1 => 320198,
gix_hash::Kind::Sha256 => todo!("let the test fail on CI and add the value here"),
_ => unimplemented!(),
};

assert_eq!(
copy.lock().len(),
EXPECTED_BUFFER_LENGTH,
expected_buffer_length,
"keep track of file size changes of the streaming format"
);

Expand Down Expand Up @@ -237,7 +259,14 @@ mod from_tree {
let hex = std::fs::read(dir.join("head.hex"))?;
gix_hash::ObjectId::from_hex(hex.trim())?
};
let odb = gix_odb::at(dir.join(".git").join("objects"))?;
let odb = gix_odb::at_opts(
dir.join(".git").join("objects"),
Vec::new(),
gix_odb::store::init::Options {
object_hash: gix_testtools::hash_kind_from_env().unwrap_or_default(),
..Default::default()
},
)?;

let mut collection = Default::default();
let mut buf = Default::default();
Expand Down
2 changes: 2 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ unit-tests:
cargo nextest run -p gix-blame --no-fail-fast
env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-refspec --no-fail-fast
env GIX_TEST_FIXTURE_HASH=sha256 cargo nextest run -p gix-refspec --no-fail-fast
env GIX_TEST_FIXTURE_HASH=sha1 cargo nextest run -p gix-worktree-stream --no-fail-fast
env GIX_TEST_FIXTURE_HASH=sha256 cargo nextest run -p gix-worktree-stream --features sha256 --no-fail-fast
cargo nextest run -p gix --no-default-features --no-fail-fast
cargo nextest run -p gix --no-default-features --features basic,comfort,max-performance-safe --no-fail-fast
cargo nextest run -p gix --no-default-features --features basic,extras,comfort,need-more-recent-msrv --no-fail-fast
Expand Down
Loading