@@ -158,22 +158,30 @@ pub trait LanguagePlugin {
158158 ///
159159 /// This will overwrite any existing files as long as they are not specified as student files
160160 /// by the language dependent student file policy.
161- fn extract_project ( & self , compressed_project : & Path , target_location : & Path ) -> Result < ( ) > {
161+ fn extract_project (
162+ & self ,
163+ compressed_project : & Path ,
164+ target_location : & Path ,
165+ clean : bool ,
166+ ) -> Result < ( ) > {
162167 let policy = Self :: get_student_file_policy ( target_location) ;
163- let zip = compressed_project;
164- let target = target_location;
165168
166- log:: debug!( "Unzipping {} to {}" , zip. display( ) , target. display( ) ) ;
169+ log:: debug!(
170+ "Unzipping {} to {}" ,
171+ compressed_project. display( ) ,
172+ target_location. display( )
173+ ) ;
167174
168- let file = File :: open ( zip) . map_err ( |e| TmcError :: OpenFile ( zip. to_path_buf ( ) , e) ) ?;
175+ let file = File :: open ( compressed_project)
176+ . map_err ( |e| TmcError :: OpenFile ( compressed_project. to_path_buf ( ) , e) ) ?;
169177 let mut zip_archive = ZipArchive :: new ( file) ?;
170178
179+ // find the exercise root directory inside the archive
171180 let project_dir = Self :: find_project_dir_in_zip ( & mut zip_archive) ?;
172181 log:: debug!( "Project dir in zip: {}" , project_dir. display( ) ) ;
173182
174183 let tmc_project_yml = policy. get_tmc_project_yml ( ) ?;
175184
176- // for each file in the zip, contains its path if unzipped
177185 // used to clean non-student files not in the zip later
178186 let mut unzip_paths = HashSet :: new ( ) ;
179187
@@ -187,18 +195,14 @@ pub trait LanguagePlugin {
187195 continue ;
188196 }
189197 } ;
190- let path_in_target = target . join ( & relative) ;
198+ let path_in_target = target_location . join ( & relative) ;
191199 log:: trace!( "processing {:?} -> {:?}" , file_path, path_in_target) ;
200+ unzip_paths. insert ( path_in_target. clone ( ) ) ;
192201
193202 if file. is_dir ( ) {
194203 log:: trace!( "creating {:?}" , path_in_target) ;
195204 fs:: create_dir_all ( & path_in_target)
196205 . map_err ( |e| TmcError :: CreateDir ( path_in_target. clone ( ) , e) ) ?;
197- unzip_paths. insert (
198- path_in_target
199- . canonicalize ( )
200- . map_err ( |e| TmcError :: Canonicalize ( path_in_target. clone ( ) , e) ) ?,
201- ) ;
202206 } else {
203207 let mut write = true ;
204208 let mut file_contents = vec ! [ ] ;
@@ -218,8 +222,11 @@ pub trait LanguagePlugin {
218222 . read_to_end ( & mut target_file_contents)
219223 . map_err ( |e| TmcError :: FileRead ( path_in_target. clone ( ) , e) ) ?;
220224 if file_contents == target_file_contents
221- || ( policy. is_student_file ( & path_in_target, & target, & tmc_project_yml) ?
222- && !policy. is_updating_forced ( & relative, & tmc_project_yml) ?)
225+ || ( policy. is_student_file (
226+ & path_in_target,
227+ & target_location,
228+ & tmc_project_yml,
229+ ) ? && !policy. is_updating_forced ( & relative, & tmc_project_yml) ?)
223230 {
224231 write = false ;
225232 }
@@ -237,37 +244,41 @@ pub trait LanguagePlugin {
237244 . map_err ( |e| TmcError :: Write ( path_in_target. clone ( ) , e) ) ?;
238245 }
239246 }
240- unzip_paths. insert (
241- path_in_target
242- . canonicalize ( )
243- . map_err ( |e| TmcError :: Canonicalize ( path_in_target. clone ( ) , e) ) ?,
244- ) ;
245247 }
246248
247- // delete non-student files that were not in zip
248- log:: debug!( "deleting non-student files not in zip" ) ;
249- log:: debug!( "{:?}" , unzip_paths) ;
250- for entry in WalkDir :: new ( target) . into_iter ( ) . filter_map ( |e| e. ok ( ) ) {
251- if !unzip_paths. contains (
252- & entry
253- . path ( )
254- . canonicalize ( )
255- . map_err ( |e| TmcError :: Canonicalize ( entry. path ( ) . to_path_buf ( ) , e) ) ?,
256- ) && ( policy. is_updating_forced ( entry. path ( ) , & tmc_project_yml) ?
257- || !policy. is_student_file ( entry. path ( ) , & target, & tmc_project_yml) ?)
249+ if clean {
250+ // delete non-student files that were not in zip
251+ log:: debug!( "deleting non-student files not in zip" ) ;
252+ log:: debug!( "{:?}" , unzip_paths) ;
253+ for entry in WalkDir :: new ( target_location)
254+ . into_iter ( )
255+ . filter_map ( |e| e. ok ( ) )
258256 {
259- log:: debug!( "rm {} {}" , entry. path( ) . display( ) , target. display( ) ) ;
260- if entry. path ( ) . is_dir ( ) {
261- // delete if empty
262- if WalkDir :: new ( entry. path ( ) ) . max_depth ( 1 ) . into_iter ( ) . count ( ) == 1 {
263- log:: debug!( "deleting empty directory {}" , entry. path( ) . display( ) ) ;
264- fs:: remove_dir ( entry. path ( ) )
265- . map_err ( |e| TmcError :: RemoveDir ( entry. path ( ) . to_path_buf ( ) , e) ) ?;
257+ if !unzip_paths. contains ( entry. path ( ) )
258+ && ( policy. is_updating_forced ( entry. path ( ) , & tmc_project_yml) ?
259+ || !policy. is_student_file (
260+ entry. path ( ) ,
261+ & target_location,
262+ & tmc_project_yml,
263+ ) ?)
264+ {
265+ log:: debug!(
266+ "rm {} {}" ,
267+ entry. path( ) . display( ) ,
268+ target_location. display( )
269+ ) ;
270+ if entry. path ( ) . is_dir ( ) {
271+ // delete if empty
272+ if WalkDir :: new ( entry. path ( ) ) . max_depth ( 1 ) . into_iter ( ) . count ( ) == 1 {
273+ log:: debug!( "deleting empty directory {}" , entry. path( ) . display( ) ) ;
274+ fs:: remove_dir ( entry. path ( ) )
275+ . map_err ( |e| TmcError :: RemoveDir ( entry. path ( ) . to_path_buf ( ) , e) ) ?;
276+ }
277+ } else {
278+ log:: debug!( "removing file {}" , entry. path( ) . display( ) ) ;
279+ fs:: remove_file ( entry. path ( ) )
280+ . map_err ( |e| TmcError :: RemoveFile ( entry. path ( ) . to_path_buf ( ) , e) ) ?;
266281 }
267- } else {
268- log:: debug!( "removing file {}" , entry. path( ) . display( ) ) ;
269- fs:: remove_file ( entry. path ( ) )
270- . map_err ( |e| TmcError :: RemoveFile ( entry. path ( ) . to_path_buf ( ) , e) ) ?;
271282 }
272283 }
273284 }
0 commit comments