1
1
use anyhow:: { Context , Error , Result } ;
2
2
use std:: {
3
- fs:: { create_dir , OpenOptions } ,
4
- io:: { self , Write } ,
3
+ fs:: { self , create_dir } ,
4
+ io,
5
5
} ;
6
6
7
7
use crate :: info_file:: ExerciseInfo ;
8
8
9
9
/// Contains all embedded files.
10
10
pub static EMBEDDED_FILES : EmbeddedFiles = rustlings_macros:: include_files!( ) ;
11
11
12
- #[ derive( Clone , Copy ) ]
13
- pub enum WriteStrategy {
14
- IfNotExists ,
15
- Overwrite ,
16
- }
17
-
18
- impl WriteStrategy {
19
- fn write ( self , path : & str , content : & [ u8 ] ) -> Result < ( ) > {
20
- let file = match self {
21
- Self :: IfNotExists => OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . open ( path) ,
22
- Self :: Overwrite => OpenOptions :: new ( )
23
- . create ( true )
24
- . write ( true )
25
- . truncate ( true )
26
- . open ( path) ,
27
- } ;
28
-
29
- file. with_context ( || format ! ( "Failed to open the file `{path}` in write mode" ) ) ?
30
- . write_all ( content)
31
- . with_context ( || format ! ( "Failed to write the file {path}" ) )
32
- }
33
- }
34
-
35
12
// Files related to one exercise.
36
13
struct ExerciseFiles {
37
14
// The content of the exercise file.
@@ -42,6 +19,16 @@ struct ExerciseFiles {
42
19
dir_ind : usize ,
43
20
}
44
21
22
+ fn create_dir_if_not_exists ( path : & str ) -> Result < ( ) > {
23
+ if let Err ( e) = create_dir ( path) {
24
+ if e. kind ( ) != io:: ErrorKind :: AlreadyExists {
25
+ return Err ( Error :: from ( e) . context ( format ! ( "Failed to create the directory {path}" ) ) ) ;
26
+ }
27
+ }
28
+
29
+ Ok ( ( ) )
30
+ }
31
+
45
32
// A directory in the `exercises/` directory.
46
33
pub struct ExerciseDir {
47
34
pub name : & ' static str ,
@@ -55,21 +42,13 @@ impl ExerciseDir {
55
42
let mut dir_path = String :: with_capacity ( 20 + self . name . len ( ) ) ;
56
43
dir_path. push_str ( "exercises/" ) ;
57
44
dir_path. push_str ( self . name ) ;
58
-
59
- if let Err ( e) = create_dir ( & dir_path) {
60
- if e. kind ( ) == io:: ErrorKind :: AlreadyExists {
61
- return Ok ( ( ) ) ;
62
- }
63
-
64
- return Err (
65
- Error :: from ( e) . context ( format ! ( "Failed to create the directory {dir_path}" ) )
66
- ) ;
67
- }
45
+ create_dir_if_not_exists ( & dir_path) ?;
68
46
69
47
let mut readme_path = dir_path;
70
48
readme_path. push_str ( "/README.md" ) ;
71
49
72
- WriteStrategy :: Overwrite . write ( & readme_path, self . readme )
50
+ fs:: write ( & readme_path, self . readme )
51
+ . with_context ( || format ! ( "Failed to write the file {readme_path}" ) )
73
52
}
74
53
}
75
54
@@ -86,17 +65,31 @@ impl EmbeddedFiles {
86
65
pub fn init_exercises_dir ( & self , exercise_infos : & [ ExerciseInfo ] ) -> Result < ( ) > {
87
66
create_dir ( "exercises" ) . context ( "Failed to create the directory `exercises`" ) ?;
88
67
89
- WriteStrategy :: IfNotExists . write (
68
+ fs :: write (
90
69
"exercises/README.md" ,
91
70
include_bytes ! ( "../exercises/README.md" ) ,
92
- ) ?;
71
+ )
72
+ . context ( "Failed to write the file exercises/README.md" ) ?;
93
73
94
74
for dir in self . exercise_dirs {
95
75
dir. init_on_disk ( ) ?;
96
76
}
97
77
78
+ let mut exercise_path = String :: with_capacity ( 64 ) ;
79
+ let prefix = "exercises/" ;
80
+ exercise_path. push_str ( prefix) ;
81
+
98
82
for ( exercise_info, exercise_files) in exercise_infos. iter ( ) . zip ( self . exercise_files ) {
99
- WriteStrategy :: IfNotExists . write ( & exercise_info. path ( ) , exercise_files. exercise ) ?;
83
+ let dir = & self . exercise_dirs [ exercise_files. dir_ind ] ;
84
+
85
+ exercise_path. truncate ( prefix. len ( ) ) ;
86
+ exercise_path. push_str ( dir. name ) ;
87
+ exercise_path. push ( '/' ) ;
88
+ exercise_path. push_str ( & exercise_info. name ) ;
89
+ exercise_path. push_str ( ".rs" ) ;
90
+
91
+ fs:: write ( & exercise_path, exercise_files. exercise )
92
+ . with_context ( || format ! ( "Failed to write the exercise file {exercise_path}" ) ) ?;
100
93
}
101
94
102
95
Ok ( ( ) )
@@ -107,7 +100,8 @@ impl EmbeddedFiles {
107
100
let dir = & self . exercise_dirs [ exercise_files. dir_ind ] ;
108
101
109
102
dir. init_on_disk ( ) ?;
110
- WriteStrategy :: Overwrite . write ( path, exercise_files. exercise )
103
+ fs:: write ( path, exercise_files. exercise )
104
+ . with_context ( || format ! ( "Failed to write the exercise file {path}" ) )
111
105
}
112
106
113
107
/// Write the solution file to disk and return its path.
@@ -116,19 +110,25 @@ impl EmbeddedFiles {
116
110
exercise_ind : usize ,
117
111
exercise_name : & str ,
118
112
) -> Result < String > {
113
+ create_dir_if_not_exists ( "solutions" ) ?;
114
+
119
115
let exercise_files = & self . exercise_files [ exercise_ind] ;
120
116
let dir = & self . exercise_dirs [ exercise_files. dir_ind ] ;
121
117
122
118
// 14 = 10 + 1 + 3
123
119
// solutions/ + / + .rs
124
- let mut solution_path = String :: with_capacity ( 14 + dir. name . len ( ) + exercise_name. len ( ) ) ;
125
- solution_path. push_str ( "solutions/" ) ;
126
- solution_path. push_str ( dir. name ) ;
120
+ let mut dir_path = String :: with_capacity ( 14 + dir. name . len ( ) + exercise_name. len ( ) ) ;
121
+ dir_path. push_str ( "solutions/" ) ;
122
+ dir_path. push_str ( dir. name ) ;
123
+ create_dir_if_not_exists ( & dir_path) ?;
124
+
125
+ let mut solution_path = dir_path;
127
126
solution_path. push ( '/' ) ;
128
127
solution_path. push_str ( exercise_name) ;
129
128
solution_path. push_str ( ".rs" ) ;
130
129
131
- WriteStrategy :: Overwrite . write ( & solution_path, exercise_files. solution ) ?;
130
+ fs:: write ( & solution_path, exercise_files. solution )
131
+ . with_context ( || format ! ( "Failed to write the solution file {solution_path}" ) ) ?;
132
132
133
133
Ok ( solution_path)
134
134
}
0 commit comments