@@ -5,6 +5,7 @@ use std::{
5
5
6
6
pub use bstr;
7
7
use bstr:: { BStr , ByteSlice } ;
8
+ use io_close:: Close ;
8
9
use nom:: error:: VerboseError ;
9
10
use once_cell:: sync:: Lazy ;
10
11
use parking_lot:: Mutex ;
@@ -38,16 +39,14 @@ pub fn scripted_fixture_repo_read_only(script_name: impl AsRef<Path>) -> Result<
38
39
scripted_fixture_repo_read_only_with_args ( script_name, None )
39
40
}
40
41
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 > {
44
43
scripted_fixture_repo_writable_with_args ( script_name, None )
45
44
}
46
45
47
46
pub fn scripted_fixture_repo_writable_with_args (
48
47
script_name : & str ,
49
48
args : impl IntoIterator < Item = & ' static str > ,
50
- ) -> std :: result :: Result < tempfile:: TempDir , Box < dyn std :: error :: Error > > {
49
+ ) -> Result < tempfile:: TempDir > {
51
50
let ro_dir = scripted_fixture_repo_read_only_with_args ( script_name, args) ?;
52
51
let dst = tempfile:: TempDir :: new ( ) ?;
53
52
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
76
75
pub fn scripted_fixture_repo_read_only_with_args (
77
76
script_name : impl AsRef < Path > ,
78
77
args : impl IntoIterator < Item = & ' static str > ,
79
- ) -> std :: result :: Result < PathBuf , Box < dyn std :: error :: Error > > {
78
+ ) -> Result < PathBuf > {
80
79
let script_name = script_name. as_ref ( ) ;
81
80
let script_path = fixture_path ( script_name) ;
82
81
@@ -109,7 +108,10 @@ pub fn scripted_fixture_repo_read_only_with_args(
109
108
if !script_result_directory. is_dir ( ) {
110
109
match extract_archive ( & archive_file_path, & script_result_directory, script_identity) {
111
110
Ok ( _) => { }
112
- Err ( _err) => {
111
+ Err ( err) => {
112
+ if err. kind ( ) != std:: io:: ErrorKind :: NotFound {
113
+ eprintln ! ( "{}" , err) ;
114
+ }
113
115
std:: fs:: create_dir_all ( & script_result_directory) ?;
114
116
let script_absolute_path = std:: env:: current_dir ( ) ?. join ( script_path) ;
115
117
let output = std:: process:: Command :: new ( "bash" )
@@ -144,21 +146,54 @@ pub fn scripted_fixture_repo_read_only_with_args(
144
146
145
147
/// The `script_identity` will be baked into the soon to be created `archive` as it identitifies the script
146
148
/// 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 < ( ) > {
148
150
if is_ci:: cached ( ) {
149
151
return Ok ( ( ) ) ;
150
152
}
151
153
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)
154
189
}
155
190
156
191
/// `required_script_identity` is the identity of the script that generated the state that is contained in `archive`.
157
192
/// 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 < ( ) > {
159
194
std:: fs:: create_dir_all ( destination_dir) ?;
160
195
// TODO
161
- Err ( "to be done" . into ( ) )
196
+ Err ( std :: io :: ErrorKind :: NotFound . into ( ) )
162
197
}
163
198
164
199
pub fn to_bstr_err ( err : nom:: Err < VerboseError < & [ u8 ] > > ) -> VerboseError < & BStr > {
0 commit comments