@@ -127,7 +127,7 @@ pub fn prepare_submission(
127127 }
128128 let test_path = tests_dir. join ( "src/test" ) ;
129129 if test_path. exists ( ) {
130- file_util:: copy ( test_path, dest. join ( "src " ) ) ?;
130+ file_util:: copy ( test_path, dest. join ( "test " ) ) ?;
131131 }
132132
133133 // copy files from config
@@ -180,7 +180,7 @@ pub fn prepare_submission(
180180 }
181181 let test_path = clone_path. join ( "test" ) ;
182182 if test_path. exists ( ) {
183- file_util:: copy ( test_path, & dest) ?;
183+ file_util:: copy ( test_path, & dest. join ( "test" ) ) ?;
184184 }
185185
186186 // copy files directly in tests to dest
@@ -191,14 +191,23 @@ pub fn prepare_submission(
191191 }
192192 }
193193 }
194- _ => {
194+ Plugin :: Python3 ( _ ) => {
195195 // copy libs
196196 log:: debug!( "copying lib" ) ;
197197 let lib_dir = clone_path. join ( "lib" ) ;
198198 if lib_dir. exists ( ) {
199199 file_util:: copy ( lib_dir, & dest) ?;
200200 }
201201
202+ // copy files directly in clone_path to dest
203+ log:: debug!( "copying files in clone path" ) ;
204+ for entry in WalkDir :: new ( clone_path) . min_depth ( 1 ) . max_depth ( 1 ) {
205+ let entry = entry?;
206+ if entry. path ( ) . is_file ( ) {
207+ file_util:: copy ( entry. path ( ) , & dest) ?;
208+ }
209+ }
210+
202211 // copy files from config
203212 log:: debug!( "copying files according to packaging config" ) ;
204213 let config = TmcProjectYml :: load_or_default ( clone_path) ?;
@@ -217,6 +226,32 @@ pub fn prepare_submission(
217226 }
218227 }
219228
229+ // copy all ipynb files
230+ log:: debug!( "copying all ipynb files" ) ;
231+ for entry in WalkDir :: new ( & project_root) {
232+ let entry = entry?;
233+ if entry
234+ . path ( )
235+ . extension ( )
236+ . map ( |ext| ext == "ipynb" )
237+ . unwrap_or_default ( )
238+ {
239+ let relative = entry
240+ . path ( )
241+ . strip_prefix ( & project_root)
242+ . expect ( "always inside project root" ) ;
243+ file_util:: copy ( entry. path ( ) , dest. join ( relative) ) ?;
244+ }
245+ }
246+ }
247+ _ => {
248+ // copy libs
249+ log:: debug!( "copying lib" ) ;
250+ let lib_dir = clone_path. join ( "lib" ) ;
251+ if lib_dir. exists ( ) {
252+ file_util:: copy ( lib_dir, & dest) ?;
253+ }
254+
220255 // copy files directly in clone_path to dest
221256 log:: debug!( "copying files in clone path" ) ;
222257 for entry in WalkDir :: new ( clone_path) . min_depth ( 1 ) . max_depth ( 1 ) {
@@ -225,6 +260,24 @@ pub fn prepare_submission(
225260 file_util:: copy ( entry. path ( ) , & dest) ?;
226261 }
227262 }
263+
264+ // copy files from config
265+ log:: debug!( "copying files according to packaging config" ) ;
266+ let config = TmcProjectYml :: load_or_default ( clone_path) ?;
267+ let config = plugin. get_exercise_packaging_configuration ( config) ?;
268+ for path in config. student_file_paths {
269+ let student_file = project_root. join ( & path) ;
270+ if student_file. exists ( ) {
271+ file_util:: copy ( student_file, & dest) ?;
272+ }
273+ }
274+ for path in config. exercise_file_paths {
275+ let exercise_file = tests_dir. join ( & path) ;
276+ if exercise_file. exists ( ) {
277+ // todo --no-target-directory?
278+ file_util:: copy ( exercise_file, & dest) ?;
279+ }
280+ }
228281 }
229282 }
230283
@@ -317,12 +370,34 @@ pub fn prepare_submission(
317370
318371// TODO: make more robust instead of just looking for src...
319372fn find_project_root < P : AsRef < Path > > ( path : P ) -> Result < Option < PathBuf > , FileError > {
373+ let mut shallowest_ipynb_dir = None :: < PathBuf > ;
320374 for entry in WalkDir :: new ( & path) {
321375 let entry = entry?;
322376 if entry. path ( ) . is_dir ( ) && entry. file_name ( ) == OsStr :: new ( "src" ) {
323377 return Ok ( entry. path ( ) . parent ( ) . map ( Path :: to_path_buf) ) ;
324378 }
379+
380+ if entry
381+ . path ( )
382+ . extension ( )
383+ . map ( |ext| ext == "ipynb" )
384+ . unwrap_or_default ( )
385+ {
386+ let ipynb_dir = entry. path ( ) . parent ( ) . unwrap_or_else ( || Path :: new ( "" ) ) ;
387+ if let Some ( shallowest_ipynb_dir) = shallowest_ipynb_dir. as_mut ( ) {
388+ if shallowest_ipynb_dir. components ( ) . count ( ) > ipynb_dir. components ( ) . count ( ) {
389+ * shallowest_ipynb_dir = ipynb_dir. to_path_buf ( ) ;
390+ }
391+ } else {
392+ shallowest_ipynb_dir = Some ( ipynb_dir. to_path_buf ( ) ) ;
393+ }
394+ }
325395 }
396+
397+ if shallowest_ipynb_dir. is_some ( ) {
398+ return Ok ( shallowest_ipynb_dir) ;
399+ }
400+
326401 log:: warn!(
327402 "No src director found, defaulting the project root to the input path {}" ,
328403 path. as_ref( ) . display( )
0 commit comments