Skip to content

Commit adea17e

Browse files
committed
Create xz/gz files in parallel
1 parent fbb00db commit adea17e

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

src/tarballer.rs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
// except according to those terms.
1010

1111
use std::fs::File;
12-
use std::io::{self, Write};
12+
use std::io::Write;
1313
use std::path::Path;
14+
use std::sync::Arc;
15+
use std::thread;
1416

1517
use flate2;
1618
use flate2::write::GzEncoder;
@@ -55,15 +57,9 @@ impl Tarballer {
5557
.chain_err(|| "failed to collect file paths")?;
5658
files.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev()));
5759

58-
// Prepare the .tar.gz file
59-
let gz = GzEncoder::new(create_new_file(tar_gz)?, flate2::Compression::Best);
60-
61-
// Prepare the .tar.xz file
62-
let xz = XzEncoder::new(create_new_file(tar_xz)?, 9);
63-
6460
// Write the tar into both encoded files. We write all directories
6561
// first, so files may be directly created. (see rustup.rs#1092)
66-
let mut builder = Builder::new(Tee(gz, xz));
62+
let mut builder = Builder::new(Vec::new());
6763
for path in dirs {
6864
let src = Path::new(&self.work_dir).join(&path);
6965
builder.append_dir(&path, &src)
@@ -75,12 +71,25 @@ impl Tarballer {
7571
builder.append_data(&mut header(&src, &file)?, &path, &file)
7672
.chain_err(|| format!("failed to tar file '{}'", src.display()))?;
7773
}
78-
let Tee(gz, xz) = builder.into_inner()
74+
let contents = builder.into_inner()
7975
.chain_err(|| "failed to finish writing .tar stream")?;
76+
let contents = Arc::new(contents);
77+
78+
// Prepare the .tar.gz file
79+
let contents2 = contents.clone();
80+
let t = thread::spawn(move || {
81+
let mut gz = GzEncoder::new(create_new_file(tar_gz)?,
82+
flate2::Compression::Best);
83+
gz.write_all(&contents2).chain_err(|| "failed to write .gz")?;
84+
gz.finish().chain_err(|| "failed to finish .gz")
85+
});
86+
87+
// Prepare the .tar.xz file
88+
let mut xz = XzEncoder::new(create_new_file(tar_xz)?, 9);
89+
xz.write_all(&contents).chain_err(|| "failed to write .xz")?;
90+
xz.finish().chain_err(|| "failed to finish .xz")?;
8091

81-
// Finish both encoded files
82-
gz.finish().chain_err(|| "failed to finish .tar.gz file")?;
83-
xz.finish().chain_err(|| "failed to finish .tar.xz file")?;
92+
t.join().unwrap()?;
8493

8594
Ok(())
8695
}
@@ -129,17 +138,3 @@ fn get_recursive_paths<P, Q>(root: P, name: Q) -> Result<(Vec<String>, Vec<Strin
129138
}
130139
Ok((dirs, files))
131140
}
132-
133-
struct Tee<A, B>(A, B);
134-
135-
impl<A: Write, B: Write> Write for Tee<A, B> {
136-
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
137-
self.0.write_all(buf)
138-
.and(self.1.write_all(buf))
139-
.and(Ok(buf.len()))
140-
}
141-
142-
fn flush(&mut self) -> io::Result<()> {
143-
self.0.flush().and(self.1.flush())
144-
}
145-
}

0 commit comments

Comments
 (0)