9
9
// except according to those terms.
10
10
11
11
use std:: fs:: File ;
12
- use std:: io:: { self , Write } ;
12
+ use std:: io:: Write ;
13
13
use std:: path:: Path ;
14
+ use std:: sync:: Arc ;
15
+ use std:: thread;
14
16
15
17
use flate2;
16
18
use flate2:: write:: GzEncoder ;
@@ -55,15 +57,9 @@ impl Tarballer {
55
57
. chain_err ( || "failed to collect file paths" ) ?;
56
58
files. sort_by ( |a, b| a. bytes ( ) . rev ( ) . cmp ( b. bytes ( ) . rev ( ) ) ) ;
57
59
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
-
64
60
// Write the tar into both encoded files. We write all directories
65
61
// 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 ( ) ) ;
67
63
for path in dirs {
68
64
let src = Path :: new ( & self . work_dir ) . join ( & path) ;
69
65
builder. append_dir ( & path, & src)
@@ -75,12 +71,25 @@ impl Tarballer {
75
71
builder. append_data ( & mut header ( & src, & file) ?, & path, & file)
76
72
. chain_err ( || format ! ( "failed to tar file '{}'" , src. display( ) ) ) ?;
77
73
}
78
- let Tee ( gz , xz ) = builder. into_inner ( )
74
+ let contents = builder. into_inner ( )
79
75
. 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" ) ?;
80
91
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 ( ) ?;
84
93
85
94
Ok ( ( ) )
86
95
}
@@ -129,17 +138,3 @@ fn get_recursive_paths<P, Q>(root: P, name: Q) -> Result<(Vec<String>, Vec<Strin
129
138
}
130
139
Ok ( ( dirs, files) )
131
140
}
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