@@ -27,14 +27,18 @@ pub fn new() -> Compiler {
27
27
}
28
28
29
29
/// Creates a new boon::compiler with format assertions enabled and validation
30
- /// for the custom `path` and `license` formats.
30
+ /// for the custom `path`, `glob`, and `license` formats.
31
31
pub fn spec_compiler ( ) -> Compiler {
32
32
let mut compiler = Compiler :: new ( ) ;
33
33
compiler. enable_format_assertions ( ) ;
34
34
compiler. register_format ( boon:: Format {
35
35
name : "path" ,
36
36
func : is_path,
37
37
} ) ;
38
+ compiler. register_format ( boon:: Format {
39
+ name : "glob" ,
40
+ func : is_glob,
41
+ } ) ;
38
42
compiler. register_format ( boon:: Format {
39
43
name : "license" ,
40
44
func : is_license,
@@ -46,11 +50,26 @@ pub fn spec_compiler() -> Compiler {
46
50
fn is_path ( v : & Value ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
47
51
let Value :: String ( s) = v else { return Ok ( ( ) ) } ;
48
52
49
- let path = RelativePath :: new ( s) ;
53
+ let path = RelativePath :: new ( s. strip_prefix ( "./" ) . unwrap_or ( s ) ) ;
50
54
for c in path. components ( ) {
51
- if c == Component :: ParentDir {
52
- Err ( "references parent dir" ) ?
53
- } ;
55
+ match c {
56
+ Component :: ParentDir => Err ( "references parent directory" ) ?,
57
+ Component :: CurDir => Err ( "references current directory" ) ?,
58
+ _ => ( ) ,
59
+ }
60
+ }
61
+
62
+ Ok ( ( ) )
63
+ }
64
+
65
+ /// Returns an error if v is not a valid glob.
66
+ fn is_glob ( v : & Value ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
67
+ let Value :: String ( s) = v else { return Ok ( ( ) ) } ;
68
+
69
+ // XXX Use https://docs.rs/glob/latest/glob/struct.Pattern.html instead?
70
+ let path = wax:: Glob :: new ( s. strip_prefix ( "./" ) . unwrap_or ( s) ) ?;
71
+ if path. has_semantic_literals ( ) {
72
+ Err ( "references parent or current directory" ) ?
54
73
}
55
74
56
75
Ok ( ( ) )
@@ -77,6 +96,7 @@ mod tests {
77
96
json ! ( "\\ foo.md" ) ,
78
97
json ! ( "this\\ and\\ that.txt" ) ,
79
98
json ! ( "/absolute/path" ) ,
99
+ json ! ( "./relative/path" ) ,
80
100
json ! ( "" ) ,
81
101
json ! ( "C:\\ foo" ) ,
82
102
json ! ( "README.txt" ) ,
@@ -92,11 +112,20 @@ mod tests {
92
112
93
113
// Test invalid paths.
94
114
for ( name, invalid, err) in [
95
- ( "parent" , json ! ( "../outside/path" ) , "references parent dir" ) ,
115
+ (
116
+ "parent" ,
117
+ json ! ( "../outside/path" ) ,
118
+ "references parent directory" ,
119
+ ) ,
120
+ (
121
+ "current" ,
122
+ json ! ( "/./outside/path" ) ,
123
+ "references current directory" ,
124
+ ) ,
96
125
(
97
126
"sub parent" ,
98
127
json ! ( "thing/../other" ) ,
99
- "references parent dir " ,
128
+ "references parent directory " ,
100
129
) ,
101
130
] {
102
131
match is_path ( & invalid) {
@@ -106,6 +135,42 @@ mod tests {
106
135
}
107
136
}
108
137
138
+ #[ test]
139
+ fn test_glob ( ) {
140
+ // Test valid globs.
141
+ for valid in [
142
+ json ! ( ".gitignore" ) ,
143
+ json ! ( ".git*" ) ,
144
+ json ! ( "/git*" ) ,
145
+ json ! ( "./git*" ) ,
146
+ json ! ( "" ) ,
147
+ json ! ( "README.*" ) ,
148
+ json ! ( "**/*.(?i){jpg,jpeg}" ) ,
149
+ json ! ( "**/{*.{go,rs}}" ) ,
150
+ json ! ( "src/**/*.rs" ) ,
151
+ ] {
152
+ if let Err ( e) = is_glob ( & valid) {
153
+ panic ! ( "{} failed: {e}" , valid) ;
154
+ }
155
+ }
156
+
157
+ // Test invalid paths.
158
+ for ( name, invalid) in [
159
+ ( "parent" , json ! ( "../*.c" ) ) ,
160
+ ( "current" , json ! ( "/./*.c" ) ) ,
161
+ ( "sub parent" , json ! ( "/**/../passwd" ) ) ,
162
+ ] {
163
+ match is_glob ( & invalid) {
164
+ Ok ( _) => panic ! ( "{name} unexpectedly passed!" ) ,
165
+ Err ( e) => assert_eq ! (
166
+ "references parent or current directory" ,
167
+ e. to_string( ) ,
168
+ "{name}"
169
+ ) ,
170
+ }
171
+ }
172
+ }
173
+
109
174
#[ test]
110
175
fn test_license ( ) {
111
176
// Test valid relative licenses.
@@ -163,7 +228,7 @@ mod tests {
163
228
fn test_spec_compiler ( ) -> Result < ( ) , Error > {
164
229
let mut c = spec_compiler ( ) ;
165
230
let id = "format" ;
166
- // Compile simple schema to validate license and path .
231
+ // Compile simple schema to validate license, path, and glob .
167
232
c. add_resource (
168
233
id,
169
234
json ! ( {
@@ -173,6 +238,10 @@ mod tests {
173
238
"type" : "string" ,
174
239
"format" : "path" ,
175
240
} ,
241
+ "glob" : {
242
+ "type" : "string" ,
243
+ "format" : "glob" ,
244
+ } ,
176
245
"license" : {
177
246
"type" : "string" ,
178
247
"format" : "license" ,
@@ -198,7 +267,12 @@ mod tests {
198
267
(
199
268
"parent path" ,
200
269
json ! ( { "path" : "../foo" } ) ,
201
- "'../foo' is not valid path: references parent dir" ,
270
+ "'../foo' is not valid path: references parent directory" ,
271
+ ) ,
272
+ (
273
+ "parent glob" ,
274
+ json ! ( { "glob" : "../*.c" } ) ,
275
+ "'../*.c' is not valid glob: references parent or current directory" ,
202
276
) ,
203
277
] {
204
278
match schemas. validate ( & json, idx) {
0 commit comments