@@ -68,13 +68,12 @@ impl CourseRefresher {
6868 // create new cache path
6969 let old_version = course_cache_path
7070 . to_str ( )
71- . unwrap ( )
72- . split ( '-' )
73- . last ( )
74- . unwrap ( )
75- . parse :: < u32 > ( )
76- . unwrap ( ) ;
71+ . and_then ( |s| s. split ( '-' ) . last ( ) )
72+ . and_then ( |s| s. parse :: < u32 > ( ) . ok ( ) )
73+ . ok_or_else ( || UtilError :: InvalidCachePath ( course_cache_path. clone ( ) ) ) ?;
7774 let new_cache_path = cache_root. join ( format ! ( "{}-{}" , course_name, old_version + 1 ) ) ;
75+ log:: info!( "next cache path: {}" , new_cache_path. display( ) ) ;
76+
7877 if new_cache_path. exists ( ) {
7978 log:: info!( "clearing new cache path at {}" , new_cache_path. display( ) ) ;
8079 file_util:: remove_dir_all ( & new_cache_path) ?;
@@ -85,9 +84,8 @@ impl CourseRefresher {
8584
8685 // initialize new clone path and verify directory names
8786 let new_clone_path = new_cache_path. join ( "clone" ) ;
88- log:: info!( "updating repository to {}" , new_clone_path. display( ) ) ;
8987 let old_clone_path = course_cache_path. join ( "clone" ) ;
90- update_or_clone_repository (
88+ initialize_new_cache_clone (
9189 & new_cache_path,
9290 & new_clone_path,
9391 & old_clone_path,
@@ -98,7 +96,6 @@ impl CourseRefresher {
9896 self . progress_reporter
9997 . finish_step ( "Updated repository" . to_string ( ) , None ) ?;
10098
101- log:: info!( "updating course options" ) ;
10299 let course_options = get_course_options ( & new_clone_path, & course_name) ?;
103100 self . progress_reporter
104101 . finish_step ( "Updated course options" . to_string ( ) , None ) ?;
@@ -108,7 +105,7 @@ impl CourseRefresher {
108105
109106 let exercise_dirs = task_executor:: find_exercise_directories ( & new_clone_path) ?
110107 . into_iter ( )
111- . map ( |ed| ed. strip_prefix ( & new_clone_path) . unwrap ( ) . to_path_buf ( ) )
108+ . map ( |ed| ed. strip_prefix ( & new_clone_path) . unwrap ( ) . to_path_buf ( ) ) // safe
112109 . collect ( ) ;
113110
114111 // make_solutions
@@ -133,23 +130,23 @@ impl CourseRefresher {
133130 self . progress_reporter
134131 . finish_step ( "Prepared stubs" . to_string ( ) , None ) ?;
135132
136- // find exercises in new clone path
137- log:: info!( "finding exercises" ) ;
138- // (exercise name, exercise path)
139133 let exercises = get_exercises ( exercise_dirs, & new_clone_path, & new_stub_path) ?;
140134 self . progress_reporter
141135 . finish_step ( "Located exercises" . to_string ( ) , None ) ?;
142136
143137 // make_zips_of_solutions
144138 let new_solution_zip_path = new_cache_path. join ( "solution_zip" ) ;
145- log:: info!( "compressing solutions" ) ;
146139 execute_zip ( & exercises, & new_solution_path, & new_solution_zip_path) ?;
147140 self . progress_reporter
148141 . finish_step ( "Compressed solutions" . to_string ( ) , None ) ?;
149142
150143 // make_zips_of_stubs
151144 let new_stub_zip_path = new_cache_path. join ( "stub_zip" ) ;
152- log:: info!( "compressing stubs" ) ;
145+ log:: info!(
146+ "compressing stubs from {} to {}" ,
147+ new_stub_path. display( ) ,
148+ new_stub_zip_path. display( )
149+ ) ;
153150 execute_zip ( & exercises, & new_stub_path, & new_stub_zip_path) ?;
154151 self . progress_reporter
155152 . finish_step ( "Compressed stubs" . to_string ( ) , None ) ?;
@@ -193,15 +190,17 @@ pub fn refresh_course(
193190/// If found, copies it to course_clone_path fetches origin from course_source_url, checks out origin/course_git_branch, cleans and checks out the repo.
194191/// If not found or found but one of the git commands causes an error, deletes course_clone_path and clones course_git_branch from course_source_url there.
195192/// NOP during testing.
196- fn update_or_clone_repository (
193+ fn initialize_new_cache_clone (
197194 new_course_root : & Path ,
198195 new_clone_path : & Path ,
199196 old_clone_path : & Path ,
200197 course_source_url : & str ,
201198 course_git_branch : & str ,
202199) -> Result < ( ) , UtilError > {
200+ log:: info!( "initializing repository at {}" , new_clone_path. display( ) ) ;
201+
203202 if old_clone_path. join ( ".git" ) . exists ( ) {
204- // Try a fast path: copy old clone and git fetch new stuff
203+ log :: info! ( "trying to copy clone from previous cache" ) ;
205204
206205 // closure to collect any error that occurs during the process
207206 let copy_and_update_repository = || -> Result < ( ) , UtilError > {
@@ -238,6 +237,8 @@ fn update_or_clone_repository(
238237 }
239238 } ;
240239
240+ log:: info!( "could not copy from previous cache, cloning" ) ;
241+
241242 // clone_repository
242243 TmcCommand :: new ( "git" . to_string ( ) )
243244 . with ( |e| {
@@ -255,9 +256,11 @@ fn update_or_clone_repository(
255256/// Makes sure no directory directly under path is an exercise directory containing a dash in the relative path from path to the dir.
256257/// A dash is used as a special delimiter.
257258fn check_directory_names ( path : & Path ) -> Result < ( ) , UtilError > {
259+ log:: info!( "checking directory names for dashes" ) ;
260+
258261 // exercise directories in canonicalized form
259262 for exercise_dir in task_executor:: find_exercise_directories ( path) ? {
260- let relative = exercise_dir. strip_prefix ( path) . unwrap ( ) ;
263+ let relative = exercise_dir. strip_prefix ( path) . unwrap ( ) ; // safe
261264 if relative. to_string_lossy ( ) . contains ( '-' ) {
262265 return Err ( UtilError :: InvalidDirectory ( exercise_dir) ) ;
263266 }
@@ -269,10 +272,16 @@ fn check_directory_names(path: &Path) -> Result<(), UtilError> {
269272/// If found, course-specific options are merged into it and it is returned.
270273/// Else, an empty mapping is returned.
271274fn get_course_options ( course_clone_path : & Path , course_name : & str ) -> Result < Mapping , UtilError > {
275+ log:: info!(
276+ "collecting course options for {} in {}" ,
277+ course_name,
278+ course_clone_path. display( )
279+ ) ;
280+
272281 let options_file = course_clone_path. join ( "course_options.yml" ) ;
273282 if options_file. exists ( ) {
274283 let file = file_util:: open_file ( options_file) ?;
275- let mut course_options: Mapping = serde_yaml:: from_reader ( file) . unwrap ( ) ;
284+ let mut course_options: Mapping = serde_yaml:: from_reader ( file) ? ;
276285 // try to remove the "courses" map
277286 if let Some ( serde_yaml:: Value :: Mapping ( mut courses) ) =
278287 course_options. remove ( & serde_yaml:: Value :: String ( "courses" . to_string ( ) ) )
@@ -300,6 +309,8 @@ fn get_exercises(
300309 course_clone_path : & Path ,
301310 course_stub_path : & Path ,
302311) -> Result < Vec < RefreshExercise > , UtilError > {
312+ log:: info!( "finding exercise checksums and points" ) ;
313+
303314 let exercises = exercise_dirs
304315 . into_iter ( )
305316 . map ( |exercise_dir| {
@@ -308,10 +319,7 @@ fn get_exercises(
308319 exercise_dir. display( )
309320 ) ;
310321 let name = exercise_dir. to_string_lossy ( ) . replace ( "/" , "-" ) ;
311-
312- // checksum
313322 let checksum = calculate_checksum ( & course_stub_path. join ( & exercise_dir) ) ?;
314-
315323 let exercise_path = course_clone_path. join ( & exercise_dir) ;
316324 let points = task_executor:: get_available_points ( & exercise_path) ?;
317325
@@ -335,12 +343,10 @@ fn calculate_checksum(exercise_dir: &Path) -> Result<String, UtilError> {
335343 . sort_by ( |a, b| a. file_name ( ) . cmp ( b. file_name ( ) ) )
336344 {
337345 let entry = entry?;
338- let relative = entry. path ( ) . strip_prefix ( exercise_dir) . unwrap ( ) ;
346+ let relative = entry. path ( ) . strip_prefix ( exercise_dir) . unwrap ( ) ; // safe
339347 let string = relative. as_os_str ( ) . to_string_lossy ( ) ;
340- log:: debug!( "updating {}" , string) ;
341348 digest. consume ( string. as_ref ( ) ) ;
342349 if entry. path ( ) . is_file ( ) {
343- log:: debug!( "updating with file" ) ;
344350 let file = file_util:: read_file ( entry. path ( ) ) ?;
345351 digest. consume ( file) ;
346352 }
@@ -356,6 +362,12 @@ fn execute_zip(
356362 root_path : & Path ,
357363 zip_dir : & Path ,
358364) -> Result < ( ) , UtilError > {
365+ log:: info!(
366+ "compressing exercises from from {} to {}" ,
367+ root_path. display( ) ,
368+ zip_dir. display( )
369+ ) ;
370+
359371 file_util:: create_dir_all ( zip_dir) ?;
360372 for exercise in course_exercises {
361373 let exercise_root = root_path. join ( & exercise. path ) ;
@@ -373,16 +385,15 @@ fn execute_zip(
373385 let entry = entry?;
374386 if entry. path ( ) . is_file ( ) {
375387 let relative_path = entry. path ( ) . strip_prefix ( & root_path) . unwrap ( ) ; // safe
376- writer
377- . start_file (
378- relative_path. to_string_lossy ( ) ,
379- zip:: write:: FileOptions :: default ( ) ,
380- )
381- . unwrap ( ) ;
388+ writer. start_file (
389+ relative_path. to_string_lossy ( ) ,
390+ zip:: write:: FileOptions :: default ( ) ,
391+ ) ?;
382392 let bytes = file_util:: read_file ( entry. path ( ) ) ?;
383393 writer. write_all ( & bytes) . map_err ( UtilError :: ZipWrite ) ?;
384394 }
385395 }
396+ writer. finish ( ) ?;
386397 }
387398 Ok ( ( ) )
388399}
@@ -398,6 +409,8 @@ fn set_permissions(path: &Path) -> Result<(), UtilError> {
398409 use nix:: sys:: stat;
399410 use std:: os:: unix:: io:: AsRawFd ;
400411
412+ log:: info!( "setting permissions in {}" , path. display( ) ) ;
413+
401414 let chmod: ModeBits = 0o775 ; // octal, read and execute permissions for all users
402415 for entry in WalkDir :: new ( path) {
403416 let entry = entry?;
@@ -555,7 +568,15 @@ courses:
555568 "course/part1/ex1/test/test.py" ,
556569 "@points('1') @points('2')" ,
557570 ) ;
558- let exercise_dirs = find_exercise_directories ( & temp. path ( ) . join ( "course" ) ) . unwrap ( ) ;
571+ let exercise_dirs = find_exercise_directories ( & temp. path ( ) . join ( "course" ) )
572+ . unwrap ( )
573+ . into_iter ( )
574+ . map ( |ed| {
575+ ed. strip_prefix ( & temp. path ( ) . join ( "course" ) )
576+ . unwrap ( )
577+ . to_path_buf ( )
578+ } )
579+ . collect ( ) ;
559580 let exercises = get_exercises (
560581 exercise_dirs,
561582 & temp. path ( ) . join ( "course" ) ,
@@ -567,7 +588,7 @@ courses:
567588 assert_eq ! ( exercises[ 0 ] . points. len( ) , 2 ) ;
568589 assert_eq ! ( exercises[ 0 ] . points[ 0 ] , "1" ) ;
569590 assert_eq ! ( exercises[ 0 ] . points[ 1 ] , "2" ) ;
570- assert_eq ! ( exercises[ 0 ] . checksum, "043fb4832da4e3fbf5babd13ed9fa732 " ) ;
591+ assert_eq ! ( exercises[ 0 ] . checksum, "129e7e898698465c4f24494219f06df9 " ) ;
571592 }
572593
573594 #[ test]
@@ -588,7 +609,15 @@ courses:
588609 file_to ( & temp, "stub/part2/ex2/dir/subdir/file" , "some file" ) ;
589610 file_to ( & temp, "stub/part2/ex2/dir/subdir/.hidden" , "hidden file" ) ;
590611
591- let exercise_dirs = find_exercise_directories ( & temp. path ( ) . join ( "clone" ) ) . unwrap ( ) ;
612+ let exercise_dirs = find_exercise_directories ( & temp. path ( ) . join ( "clone" ) )
613+ . unwrap ( )
614+ . into_iter ( )
615+ . map ( |ed| {
616+ ed. strip_prefix ( & temp. path ( ) . join ( "clone" ) )
617+ . unwrap ( )
618+ . to_path_buf ( )
619+ } )
620+ . collect ( ) ;
592621 let exercises = get_exercises (
593622 exercise_dirs,
594623 & temp. path ( ) . join ( "clone" ) ,
@@ -611,23 +640,26 @@ courses:
611640 for i in fz. file_names ( ) {
612641 log:: debug!( "{}" , i) ;
613642 }
614- assert ! ( fz. by_name( "setup.py" ) . is_ok( ) ) ;
615643 assert ! ( fz
616644 . by_name(
617- & Path :: new( "dir" )
645+ & Path :: new( "part2" )
646+ . join( "ex2" )
647+ . join( "dir" )
618648 . join( "subdir" )
619649 . join( ".hidden" )
620650 . to_string_lossy( )
621651 )
622- . is_err( ) ) ;
652+ . is_err( ) ) ; // hidden files filtered
623653 let mut file = fz
624654 . by_name (
625- & Path :: new ( "dir" )
655+ & Path :: new ( "part2" )
656+ . join ( "ex2" )
657+ . join ( "dir" )
626658 . join ( "subdir" )
627659 . join ( "file" )
628660 . to_string_lossy ( ) ,
629661 )
630- . unwrap ( ) ;
662+ . unwrap ( ) ; // other files have their stub contents
631663 let mut buf = String :: new ( ) ;
632664 file. read_to_string ( & mut buf) . unwrap ( ) ;
633665 assert_eq ! ( buf, "some file" ) ;
0 commit comments