@@ -314,10 +314,10 @@ fn extract_with_filter<F: Fn(&Path) -> bool>(
314314 let file = file_util:: open_file ( archive) ?;
315315 let mut zip = Archive :: new ( file, compression) ?;
316316 let project_dir_in_archive = if naive {
317- PathBuf :: new ( )
317+ Ok ( PathBuf :: new ( ) )
318318 } else {
319- plugin. find_project_dir_in_archive ( & mut zip) ?
320- } ;
319+ plugin. safe_find_project_dir_in_archive ( & mut zip)
320+ } ? ;
321321
322322 let mut iter = zip. iter ( ) ?;
323323 loop {
@@ -783,4 +783,83 @@ mod test {
783783 . exists( )
784784 ) ;
785785 }
786+
787+ #[ test]
788+ fn includes_files_in_root_dir_from_exercise ( ) {
789+ init ( ) ;
790+
791+ let temp = tempfile:: tempdir ( ) . unwrap ( ) ;
792+ let clone_root = temp. path ( ) . join ( "some_course" ) ;
793+ file_util:: create_dir_all ( & clone_root) . unwrap ( ) ;
794+
795+ // Copy the Maven exercise to our temp directory
796+ let src_clone = Path :: new ( MAVEN_CLONE ) ;
797+ file_util:: copy ( src_clone, & clone_root) . unwrap ( ) ;
798+
799+ let exercise_dir = clone_root. join ( "MavenExercise" ) ;
800+
801+ // Create a file in the root directory of the exercise (simulating repo file)
802+ let repo_file_path = exercise_dir. join ( "foo.txt" ) ;
803+ file_util:: write_to_file ( b"repohello" , & repo_file_path) . unwrap ( ) ;
804+
805+ // Create a submission zip that also has foo.txt but with different content
806+ // We need to create a proper Maven project structure that the plugin can understand
807+ let sub_zip_path = temp. path ( ) . join ( "submission.zip" ) ;
808+ let sub_zip_file = file_util:: create_file ( & sub_zip_path) . unwrap ( ) ;
809+ let mut zw = zip:: ZipWriter :: new ( sub_zip_file) ;
810+ let opts = SimpleFileOptions :: default ( ) ;
811+
812+ // Create the Maven project structure
813+ zw. add_directory ( "MavenExercise" , opts) . unwrap ( ) ;
814+ zw. add_directory ( "MavenExercise/src" , opts) . unwrap ( ) ;
815+ zw. add_directory ( "MavenExercise/src/main" , opts) . unwrap ( ) ;
816+ zw. add_directory ( "MavenExercise/src/main/java" , opts)
817+ . unwrap ( ) ;
818+
819+ // Add the student's modified file
820+ zw. start_file ( "MavenExercise/foo.txt" , opts) . unwrap ( ) ;
821+ std:: io:: Write :: write_all ( & mut zw, b"submissionhello" ) . unwrap ( ) ;
822+
823+ // Add a source file
824+ zw. start_file ( "MavenExercise/src/main/java/SimpleStuff.java" , opts)
825+ . unwrap ( ) ;
826+ std:: io:: Write :: write_all ( & mut zw, b"public class SimpleStuff { }" ) . unwrap ( ) ;
827+
828+ zw. finish ( ) . unwrap ( ) ;
829+
830+ let output_arch = temp. path ( ) . join ( "out.tar" ) ;
831+ prepare_submission (
832+ PrepareSubmission {
833+ archive : & sub_zip_path,
834+ compression : Compression :: Zip ,
835+ extract_naively : false ,
836+ } ,
837+ & output_arch,
838+ false ,
839+ TmcParams :: new ( ) ,
840+ & exercise_dir,
841+ None ,
842+ Compression :: Tar ,
843+ )
844+ . unwrap ( ) ;
845+ assert ! ( output_arch. exists( ) ) ;
846+
847+ // Unpack and verify that foo.txt content is from the repo, not submission
848+ let output_file = file_util:: open_file ( & output_arch) . unwrap ( ) ;
849+ let mut archive = tar:: Archive :: new ( output_file) ;
850+ let output_extracted = temp. path ( ) . join ( "output" ) ;
851+ archive. unpack ( & output_extracted) . unwrap ( ) ;
852+
853+ // Verify foo.txt exists and has content from repo, not submission
854+ let foo_file = output_extracted. join ( "some_course/MavenExercise/foo.txt" ) ;
855+ assert ! (
856+ foo_file. exists( ) ,
857+ "foo.txt should be included in the archive"
858+ ) ;
859+ let content = fs:: read_to_string ( foo_file) . unwrap ( ) ;
860+ assert_eq ! (
861+ content, "repohello" ,
862+ "Should use repo content, not submission content"
863+ ) ;
864+ }
786865}
0 commit comments