alpm_compress/tarball/
builder.rs1use std::{fmt, fmt::Debug, fs::File};
4
5use tar::Builder;
6
7use crate::{
8 Error,
9 compression::{CompressionEncoder, CompressionSettings},
10};
11
12pub struct TarballBuilder<'c> {
17 inner: Builder<CompressionEncoder<'c>>,
18}
19
20impl Debug for TarballBuilder<'_> {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.debug_struct("TarballBuilder")
23 .field("inner", &"Builder<CompressionEncoder>")
24 .finish()
25 }
26}
27
28impl<'c> TarballBuilder<'c> {
29 pub fn new(file: File, settings: &CompressionSettings) -> Result<Self, Error> {
36 CompressionEncoder::new(file, settings).map(Self::from)
37 }
38
39 pub fn inner_mut(&mut self) -> &mut Builder<CompressionEncoder<'c>> {
56 &mut self.inner
57 }
58
59 pub fn finish(self) -> Result<(), Error> {
67 self.inner
68 .into_inner()
69 .map_err(|source| Error::IoWrite {
70 context: "writing the archive",
71 source,
72 })?
73 .finish()?;
74 Ok(())
75 }
76}
77
78impl<'c> From<CompressionEncoder<'c>> for TarballBuilder<'c> {
79 fn from(encoder: CompressionEncoder<'c>) -> Self {
81 Self {
82 inner: Builder::new(encoder),
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use std::io::Write;
90
91 use rstest::rstest;
92 use tempfile::{NamedTempFile, tempfile};
93 use testresult::TestResult;
94
95 use super::*;
96 use crate::compression::{
97 Bzip2CompressionLevel,
98 CompressionSettings,
99 GzipCompressionLevel,
100 XzCompressionLevel,
101 ZstdCompressionLevel,
102 ZstdThreads,
103 };
104
105 #[rstest]
106 #[case::bzip2(CompressionSettings::Bzip2 { compression_level: Bzip2CompressionLevel::default() })]
107 #[case::gzip(CompressionSettings::Gzip { compression_level: GzipCompressionLevel::default() })]
108 #[case::xz(CompressionSettings::Xz { compression_level: XzCompressionLevel::default() })]
109 #[case::zstd(CompressionSettings::Zstd { compression_level: ZstdCompressionLevel::default(), threads: ZstdThreads::all() })]
110 #[case::no_compression(CompressionSettings::None)]
111 fn test_tarball_builder_write_file(
112 #[case] compression_settings: CompressionSettings,
113 ) -> TestResult {
114 let mut builder = TarballBuilder::new(tempfile()?, &compression_settings)?;
115 let test_file = NamedTempFile::new()?;
116 {
117 let mut f = test_file.reopen()?;
118 f.write_all(b"alpm4ever")?;
119 f.flush()?;
120 }
121
122 builder
123 .inner_mut()
124 .append_path_with_name(test_file.path(), "testfile")?;
125 builder.finish()?;
126
127 Ok(())
128 }
129
130 #[rstest]
131 #[case::bzip2(CompressionSettings::Bzip2 { compression_level: Bzip2CompressionLevel::default() })]
132 #[case::gzip(CompressionSettings::Gzip { compression_level: GzipCompressionLevel::default() })]
133 #[case::xz(CompressionSettings::Xz { compression_level: XzCompressionLevel::default() })]
134 #[case::zstd(CompressionSettings::Zstd { compression_level: ZstdCompressionLevel::default(), threads: ZstdThreads::all() })]
135 #[case::no_compression(CompressionSettings::None)]
136 fn test_tarball_builder_debug(#[case] compression_settings: CompressionSettings) -> TestResult {
137 let builder = TarballBuilder::new(tempfile()?, &compression_settings)?;
138 let dbg = format!("{:?}", builder);
139 assert!(dbg.contains("TarballBuilder"));
140 Ok(())
141 }
142}