Skip to content

Commit f1e107a

Browse files
committed
simple creation of test-archives (#384)
XZ encoding isn't quite en par yet though.
1 parent c8d218c commit f1e107a

File tree

4 files changed

+95
-12
lines changed

4 files changed

+95
-12
lines changed

Cargo.lock

Lines changed: 45 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deny.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ allow = [
3939
"Apache-2.0",
4040
"BSD-3-Clause",
4141
"MIT",
42+
"ISC",
4243
"CC-PDDC",
4344
]
4445
# Lint level for licenses considered copyleft

tests/tools/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ tempfile = "3.2.0"
2222
fs_extra = "1.2.0"
2323
parking_lot = { version = "0.12.0" }
2424
is_ci = "1.1.1"
25+
io-close = "0.3.7"
26+
tar = { version = "0.4.38", default-features = false }
27+
lzma-rs = { version = "0.2.0", default-features = false }

tests/tools/src/lib.rs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::{
55

66
pub use bstr;
77
use bstr::{BStr, ByteSlice};
8+
use io_close::Close;
89
use nom::error::VerboseError;
910
use once_cell::sync::Lazy;
1011
use parking_lot::Mutex;
@@ -38,16 +39,14 @@ pub fn scripted_fixture_repo_read_only(script_name: impl AsRef<Path>) -> Result<
3839
scripted_fixture_repo_read_only_with_args(script_name, None)
3940
}
4041

41-
pub fn scripted_fixture_repo_writable(
42-
script_name: &str,
43-
) -> std::result::Result<tempfile::TempDir, Box<dyn std::error::Error>> {
42+
pub fn scripted_fixture_repo_writable(script_name: &str) -> Result<tempfile::TempDir> {
4443
scripted_fixture_repo_writable_with_args(script_name, None)
4544
}
4645

4746
pub fn scripted_fixture_repo_writable_with_args(
4847
script_name: &str,
4948
args: impl IntoIterator<Item = &'static str>,
50-
) -> std::result::Result<tempfile::TempDir, Box<dyn std::error::Error>> {
49+
) -> Result<tempfile::TempDir> {
5150
let ro_dir = scripted_fixture_repo_read_only_with_args(script_name, args)?;
5251
let dst = tempfile::TempDir::new()?;
5352
copy_recursively_into_existing_dir(&ro_dir, dst.path())?;
@@ -76,7 +75,7 @@ pub fn copy_recursively_into_existing_dir(src_dir: impl AsRef<Path>, dst_dir: im
7675
pub fn scripted_fixture_repo_read_only_with_args(
7776
script_name: impl AsRef<Path>,
7877
args: impl IntoIterator<Item = &'static str>,
79-
) -> std::result::Result<PathBuf, Box<dyn std::error::Error>> {
78+
) -> Result<PathBuf> {
8079
let script_name = script_name.as_ref();
8180
let script_path = fixture_path(script_name);
8281

@@ -109,7 +108,10 @@ pub fn scripted_fixture_repo_read_only_with_args(
109108
if !script_result_directory.is_dir() {
110109
match extract_archive(&archive_file_path, &script_result_directory, script_identity) {
111110
Ok(_) => {}
112-
Err(_err) => {
111+
Err(err) => {
112+
if err.kind() != std::io::ErrorKind::NotFound {
113+
eprintln!("{}", err);
114+
}
113115
std::fs::create_dir_all(&script_result_directory)?;
114116
let script_absolute_path = std::env::current_dir()?.join(script_path);
115117
let output = std::process::Command::new("bash")
@@ -144,21 +146,54 @@ pub fn scripted_fixture_repo_read_only_with_args(
144146

145147
/// The `script_identity` will be baked into the soon to be created `archive` as it identitifies the script
146148
/// that created the contents of `source_dir`.
147-
fn create_archive_if_not_on_ci(_source_dir: &Path, archive: &Path, _script_identity: u32) -> Result<()> {
149+
fn create_archive_if_not_on_ci(source_dir: &Path, archive: &Path, script_identity: u32) -> std::io::Result<()> {
148150
if is_ci::cached() {
149151
return Ok(());
150152
}
151153
std::fs::create_dir_all(archive.parent().expect("archive is a file"))?;
152-
// TODO
153-
Ok(())
154+
155+
let meta_dir = populate_meta_dir(&source_dir, script_identity)?;
156+
let res = (move || {
157+
let mut buf = Vec::<u8>::new();
158+
{
159+
let mut ar = tar::Builder::new(&mut buf);
160+
ar.mode(tar::HeaderMode::Deterministic);
161+
ar.append_dir_all(".", source_dir)?;
162+
ar.finish()?;
163+
}
164+
let mut archive = std::fs::OpenOptions::new()
165+
.write(true)
166+
.create(true)
167+
.append(false)
168+
.open(archive)?;
169+
lzma_rs::xz_compress(&mut &*buf, &mut archive)?;
170+
archive.close()
171+
})();
172+
std::fs::remove_dir_all(meta_dir)?;
173+
res
174+
}
175+
176+
const META_NAME: &str = "__gitoxide_meta__";
177+
const META_IDENTITY: &str = "identity";
178+
const META_GIT_VERSION: &str = "git-version";
179+
180+
fn populate_meta_dir(destination_dir: &Path, script_identity: u32) -> std::io::Result<PathBuf> {
181+
let meta_dir = destination_dir.join(META_NAME);
182+
std::fs::create_dir_all(&meta_dir)?;
183+
std::fs::write(meta_dir.join(META_IDENTITY), format!("{}", script_identity).as_bytes())?;
184+
std::fs::write(
185+
meta_dir.join(META_GIT_VERSION),
186+
&std::process::Command::new("git").arg("--version").output()?.stdout,
187+
)?;
188+
Ok(meta_dir)
154189
}
155190

156191
/// `required_script_identity` is the identity of the script that generated the state that is contained in `archive`.
157192
/// If this is not the case, the arvhive will be ignored.
158-
fn extract_archive(_archive: &Path, destination_dir: &Path, _required_script_identity: u32) -> Result<()> {
193+
fn extract_archive(_archive: &Path, destination_dir: &Path, _required_script_identity: u32) -> std::io::Result<()> {
159194
std::fs::create_dir_all(destination_dir)?;
160195
// TODO
161-
Err("to be done".into())
196+
Err(std::io::ErrorKind::NotFound.into())
162197
}
163198

164199
pub fn to_bstr_err(err: nom::Err<VerboseError<&[u8]>>) -> VerboseError<&BStr> {

0 commit comments

Comments
 (0)