Skip to content

Commit

Permalink
Add compression support to gix archive, which is where it should sh…
Browse files Browse the repository at this point in the history
…ine.
  • Loading branch information
Byron committed Jul 22, 2023
1 parent 61aed0e commit 567b1a4
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ overflow-checks = false
# this bloats files but assures destructors are called, important for tempfiles. One day I hope we
# can wire up the 'abrt' signal handler so tempfiles will be removed in case of panics.
panic = 'unwind'
codegen-units = 1
#codegen-units = 1
incremental = false
build-override = { opt-level = 0 }

Expand Down
3 changes: 2 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ allow = [
"MIT-0",
"ISC",
"Unicode-DFS-2016",
"LicenseRef-ring"
"LicenseRef-ring",
"Zlib"
]
# Lint level for licenses considered copyleft
copyleft = "allow"
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ serde = ["gix/serde", "dep:serde_json", "dep:serde", "bytesize/serde"]
gix = { version = "^0.49.1", path = "../gix", default-features = false }
gix-pack-for-configuration-only = { package = "gix-pack", version = "^0.40.0", path = "../gix-pack", default-features = false, features = ["pack-cache-lru-dynamic", "pack-cache-lru-static"] }
gix-transport-configuration-only = { package = "gix-transport", version = "^0.34.0", path = "../gix-transport", default-features = false }
gix-archive-for-configuration-only = { package = "gix-archive", version = "^0.2.0", path = "../gix-archive", optional = true, features = ["tar"] }
gix-archive-for-configuration-only = { package = "gix-archive", version = "^0.2.0", path = "../gix-archive", optional = true, features = ["tar", "tar_gz"] }
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
anyhow = "1.0.42"
thiserror = "1.0.34"
Expand Down
37 changes: 17 additions & 20 deletions gitoxide-core/src/repository/archive.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use anyhow::bail;
use gix::worktree::archive;
use gix::Progress;
use std::ops::Add;
use std::path::Path;

pub fn stream(
repo: gix::Repository,
destination_path: Option<&Path>,
destination_path: &Path,
rev_spec: Option<&str>,
mut progress: impl Progress,
format: Option<archive::Format>,
Expand All @@ -24,13 +23,7 @@ pub fn stream(
bytes.init(None, gix::progress::bytes());

let mut file = gix::progress::Write {
inner: match destination_path {
Some(path) => Box::new(std::io::BufWriter::with_capacity(
128 * 1024,
std::fs::File::create(path)?,
)) as Box<dyn std::io::Write>,
None => Box::new(std::io::sink()),
},
inner: std::io::BufWriter::with_capacity(128 * 1024, std::fs::File::create(destination_path)?),
progress: &mut bytes,
};
repo.worktree_archive(
Expand All @@ -41,9 +34,12 @@ pub fn stream(
gix::worktree::archive::Options {
format,
tree_prefix: None,
modification_time: modification_date
.map(|t| std::time::UNIX_EPOCH.add(std::time::Duration::from_secs(t as u64)))
.unwrap_or_else(std::time::SystemTime::now),
modification_time: modification_date.unwrap_or_else(|| {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or_default() as gix::date::SecondsSinceUnixEpoch
}),
},
)?;

Expand All @@ -67,14 +63,15 @@ fn fetch_rev_info(
})
}

fn format_from_ext(path: Option<&Path>) -> anyhow::Result<archive::Format> {
Ok(match path {
Some(path) => match path.extension().and_then(|ext| ext.to_str()) {
None => bail!("Cannot derive archive format from a file without extension"),
Some("tar") => archive::Format::Tar,
Some("stream") => archive::Format::InternalTransientNonPersistable,
Some(ext) => bail!("Format for extendion '{ext}' is unsupported"),
fn format_from_ext(path: &Path) -> anyhow::Result<archive::Format> {
Ok(match path.extension().and_then(std::ffi::OsStr::to_str) {
None => bail!("Cannot derive archive format from a file without extension"),
Some("tar") => archive::Format::Tar,
Some("gz") => archive::Format::TarGz,
Some("zip") => archive::Format::Zip {
compression_level: None,
},
None => archive::Format::InternalTransientNonPersistable,
Some("stream") => archive::Format::InternalTransientNonPersistable,
Some(ext) => bail!("Format for extension '{ext}' is unsupported"),
})
}
7 changes: 6 additions & 1 deletion src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub fn main() -> Result<()> {
#[cfg(feature = "gitoxide-core-tools-archive")]
Subcommands::Archive(crate::plumbing::options::archive::Platform {
format,
compression_level,
output_file,
treeish,
}) => prepare_and_run(
Expand All @@ -150,14 +151,18 @@ pub fn main() -> Result<()> {
move |progress, _out, _err| {
core::repository::archive::stream(
repository(Mode::Lenient)?,
output_file.as_deref(),
&output_file,
treeish.as_deref(),
progress,
format.map(|f| match f {
crate::plumbing::options::archive::Format::Internal => {
gix::worktree::archive::Format::InternalTransientNonPersistable
}
crate::plumbing::options::archive::Format::Tar => gix::worktree::archive::Format::Tar,
crate::plumbing::options::archive::Format::TarGz => gix::worktree::archive::Format::TarGz,
crate::plumbing::options::archive::Format::Zip => {
gix::worktree::archive::Format::Zip { compression_level }
}
}),
)
},
Expand Down
12 changes: 10 additions & 2 deletions src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,24 @@ pub mod archive {
Internal,
/// Use the `.tar` file format, uncompressed.
Tar,
/// Use the `.tar.gz` file format, compressed with `gzip`.
TarGz,
/// Use the `.zip` container format.
Zip,
}

#[derive(Debug, clap::Parser)]
pub struct Platform {
/// Explicitly set the format. Otherwise derived from the suffix of the output file.
#[clap(long, short = 'f', value_enum)]
pub format: Option<Format>,
/// The file to write the archive to, or discard the output immediately.
/// The compression strength to use. Currently only used for `.zip` archives, valid from 0-9.
#[clap(long, short = 'c', value_enum)]
pub compression_level: Option<u8>,
/// The file to write the archive to.
///
/// It's extension determines the archive format, unless `--format` is set.
pub output_file: Option<PathBuf>,
pub output_file: PathBuf,

/// The revspec of the commit or tree to traverse, or the tree at `HEAD` if unspecified.
///
Expand Down

0 comments on commit 567b1a4

Please sign in to comment.