1- //! Implementation of LanguagePlugin for C#
1+ //! An implementation of LanguagePlugin for C#.
22
33use crate :: policy:: CSharpStudentFilePolicy ;
44
5- use crate :: { CSTestResult , CSharpError } ;
5+ use crate :: { cs_test_result :: CSTestResult , CSharpError } ;
66use std:: collections:: HashMap ;
77use std:: env;
88use std:: ffi:: { OsStr , OsString } ;
@@ -33,7 +33,7 @@ impl CSharpPlugin {
3333 }
3434
3535 /// Extracts the bundled tmc-csharp-runner to the given path.
36- fn extract_runner ( target : & Path ) -> Result < ( ) , CSharpError > {
36+ fn extract_runner_to_dir ( target : & Path ) -> Result < ( ) , CSharpError > {
3737 log:: debug!( "extracting C# runner to {}" , target. display( ) ) ;
3838 const TMC_CSHARP_RUNNER : & [ u8 ] = include_bytes ! ( "../tmc-csharp-runner-1.0.1.zip" ) ;
3939
@@ -58,12 +58,14 @@ impl CSharpPlugin {
5858 }
5959
6060 /// Returns the directory of the TMC C# runner, writing it to the cache dir if it doesn't exist there yet.
61- fn get_runner_dir ( ) -> Result < PathBuf , CSharpError > {
61+ ///
62+ /// NOTE: May cause issues if called concurrently.
63+ fn get_or_init_runner_dir ( ) -> Result < PathBuf , CSharpError > {
6264 match dirs:: cache_dir ( ) {
6365 Some ( cache_dir) => {
6466 let runner_dir = cache_dir. join ( "tmc" ) . join ( "tmc-csharp-runner" ) ;
6567 if !runner_dir. exists ( ) {
66- Self :: extract_runner ( & runner_dir) ?;
68+ Self :: extract_runner_to_dir ( & runner_dir) ?;
6769 }
6870 Ok ( runner_dir)
6971 }
@@ -77,7 +79,7 @@ impl CSharpPlugin {
7779 log:: debug!( "using bootstrap path TMC_CSHARP_BOOTSTRAP_PATH={}" , var) ;
7880 Ok ( PathBuf :: from ( var) )
7981 } else {
80- let runner_path = Self :: get_runner_dir ( ) ?;
82+ let runner_path = Self :: get_or_init_runner_dir ( ) ?;
8183 let bootstrap_path = runner_path. join ( "TestMyCode.CSharp.Bootstrap.dll" ) ;
8284 if bootstrap_path. exists ( ) {
8385 log:: debug!( "found boostrap dll at {}" , bootstrap_path. display( ) ) ;
@@ -139,9 +141,12 @@ impl LanguagePlugin for CSharpPlugin {
139141 let file_path = Path :: new ( file. name ( ) ) ;
140142
141143 if file_path. extension ( ) == Some ( OsStr :: new ( "csproj" ) ) {
144+ // check parent of parent of csproj file for src
142145 if let Some ( csproj_parent) = file_path. parent ( ) . and_then ( Path :: parent) {
143146 if csproj_parent. file_name ( ) == Some ( OsStr :: new ( "src" ) ) {
147+ // get parent of src
144148 if let Some ( src_parent) = csproj_parent. parent ( ) {
149+ // skip if any part of the path is __MACOSX
145150 if src_parent. components ( ) . any ( |p| p. as_os_str ( ) == "__MACOSX" ) {
146151 continue ;
147152 }
@@ -276,8 +281,9 @@ impl LanguagePlugin for CSharpPlugin {
276281 }
277282 for entry in WalkDir :: new ( path) . into_iter ( ) . filter_map ( |e| e. ok ( ) ) {
278283 let file_name = entry. path ( ) . file_name ( ) ;
279- if file_name == Some ( & OsString :: from ( "bin" ) )
280- || file_name == Some ( & OsString :: from ( "obj" ) )
284+ if entry. path ( ) . is_dir ( )
285+ && ( file_name == Some ( & OsString :: from ( "bin" ) )
286+ || file_name == Some ( & OsString :: from ( "obj" ) ) )
281287 {
282288 file_util:: remove_dir_all ( entry. path ( ) ) ?;
283289 }
@@ -331,7 +337,7 @@ mod test {
331337 fn init ( ) {
332338 let _ = env_logger:: builder ( ) . is_test ( true ) . try_init ( ) ;
333339 INIT_RUNNER . call_once ( || {
334- let _ = CSharpPlugin :: get_runner_dir ( ) . unwrap ( ) ;
340+ let _ = CSharpPlugin :: get_or_init_runner_dir ( ) . unwrap ( ) ;
335341 } ) ;
336342 }
337343
0 commit comments