11///|
22fn usage () -> String {
3- "usage: fwdc <schema.yaml> [output.json]\n fwdc presets\n fwdc validate <schema.yaml>"
3+ "usage: fwdc <schema.yaml> [output.json]\n fwdc presets\n fwdc validate <schema.yaml> [--baseline <baseline.yaml>] [--format json|--json] "
44}
55
66///|
@@ -12,8 +12,7 @@ fn print_presets() -> Unit {
1212
1313///|
1414fn read_input (path : String ) -> String? {
15- let input_result : Result [String , @fs .IOError ] = try ? @fs .read_file_to_string (path )
16- match input_result {
15+ match read_input_result (path ) {
1716 Ok (text ) => Some (text )
1817 Err (err ) => {
1918 println ("read error: " + err .to_string ())
@@ -22,6 +21,11 @@ fn read_input(path : String) -> String? {
2221 }
2322}
2423
24+ ///|
25+ fn read_input_result (path : String ) -> Result [String , @fs .IOError ] {
26+ try ? @fs .read_file_to_string (path )
27+ }
28+
2529///|
2630fn write_output (path : String , output : String ) -> Bool {
2731 let write_result : Result [Unit , @fs .IOError ] =
@@ -35,6 +39,32 @@ fn write_output(path : String, output : String) -> Bool {
3539 }
3640}
3741
42+ ///|
43+ fn format_reason (reason : @core .Reason ) -> String {
44+ @compiler .reason_to_human_line (reason )
45+ }
46+
47+ ///|
48+ fn has_breaking (reasons : Array [@core .Reason ]) -> Bool {
49+ for reason in reasons {
50+ if reason .code () == "BreakingChange" || reason .code () == "MigrationRequired" {
51+ return true
52+ }
53+ }
54+ false
55+ }
56+
57+ ///|
58+ fn reason_from_compile_error (err : @compiler .CompileError ) -> @core .Reason {
59+ match err {
60+ @compiler .CompileError ::ParseFailure (msg ) =>
61+ @core .Reason ::new ("ParseFailure" , msg )
62+ @compiler .CompileError ::ResolveFailure (msg ) =>
63+ @core .Reason ::new ("ResolveFailure" , msg )
64+ @compiler .CompileError ::ValidationFailure (reason ) => reason
65+ }
66+ }
67+
3868///|
3969pub fn run (args : Array [String ]) -> Int {
4070 if args .length () == 0 {
@@ -51,37 +81,162 @@ pub fn run(args : Array[String]) -> Int {
5181 return 1
5282 }
5383 let input_path = args [1 ]
54- let input_opt = read_input (input_path )
55- match input_opt {
56- Some (input ) => {
57- match @compiler .parse_yaml (input ) {
58- Ok (schema ) => {
59- match @compiler .resolve_schema (schema ) {
60- Ok (resolved ) => {
61- match @compiler .validate_schema (resolved ) {
84+ let mut baseline_path : String? = None
85+ let mut json_output = false
86+ for i = 2 ; i < args .length (); {
87+ let arg = args [i ]
88+ if arg == "--baseline" {
89+ if i + 1 >= args .length () {
90+ println (usage ())
91+ return 1
92+ }
93+ baseline_path = Some (args [i + 1 ])
94+ continue i + 2
95+ } else if arg == "--format" {
96+ if i + 1 >= args .length () {
97+ println (usage ())
98+ return 1
99+ }
100+ if args [i + 1 ] == "json" {
101+ json_output = true
102+ continue i + 2
103+ }
104+ println (usage ())
105+ return 1
106+ } else if arg == "--json" {
107+ json_output = true
108+ continue i + 1
109+ } else {
110+ println (usage ())
111+ return 1
112+ }
113+ } else {}
114+ let input_result = read_input_result (input_path )
115+ match input_result {
116+ Ok (input ) => {
117+ match baseline_path {
118+ Some (path ) => {
119+ let baseline_result = read_input_result (path )
120+ match baseline_result {
121+ Ok (baseline ) => {
122+ match @compiler .validate_with_baseline (input , baseline ) {
62123 Ok (_ ) => {
63- println ("ok" )
124+ if json_output {
125+ println (@compiler .validation_json_string (true , []))
126+ } else {
127+ println ("ok" )
128+ }
64129 0
65130 }
66- Err (reason ) => {
67- println ("validation error: " + reason .code () + ": " + reason .message ())
131+ Err (reasons ) => {
132+ if json_output {
133+ println (@compiler .validation_json_string (false , reasons ))
134+ } else {
135+ let header = if has_breaking (reasons ) {
136+ "error: breaking changes detected ("
137+ } else {
138+ "error: validation failed ("
139+ }
140+ println (header + reasons .length ().to_string () + ")" )
141+ for reason in reasons {
142+ println ("- " + format_reason (reason ))
143+ }
144+ }
68145 1
69146 }
70147 }
71148 }
72149 Err (err ) => {
73- println (@compiler .describe_error (err ))
150+ if json_output {
151+ let reasons : Array [@core .Reason ] = []
152+ reasons .push (@core .Reason ::new (
153+ "ReadFailure" ,
154+ "read error: " + err .to_string (),
155+ ))
156+ println (@compiler .validation_json_string (false , reasons ))
157+ } else {
158+ println ("read error: " + err .to_string ())
159+ }
74160 1
75161 }
76162 }
77163 }
78- Err (err ) => {
79- println (@compiler .describe_error (err ))
80- 1
164+ None => {
165+ if json_output {
166+ match @compiler .parse_yaml (input ) {
167+ Ok (schema ) => {
168+ match @compiler .resolve_schema (schema ) {
169+ Ok (resolved ) => {
170+ match @compiler .validate_schema (resolved ) {
171+ Ok (_ ) => {
172+ println (@compiler .validation_json_string (true , []))
173+ 0
174+ }
175+ Err (reason ) => {
176+ println (@compiler .validation_json_string (false , [reason ]))
177+ 1
178+ }
179+ }
180+ }
181+ Err (err ) => {
182+ let reason = reason_from_compile_error (err )
183+ println (@compiler .validation_json_string (false , [reason ]))
184+ 1
185+ }
186+ }
187+ }
188+ Err (err ) => {
189+ let reason = reason_from_compile_error (err )
190+ println (@compiler .validation_json_string (false , [reason ]))
191+ 1
192+ }
193+ }
194+ } else {
195+ match @compiler .parse_yaml (input ) {
196+ Ok (schema ) => {
197+ match @compiler .resolve_schema (schema ) {
198+ Ok (resolved ) => {
199+ match @compiler .validate_schema (resolved ) {
200+ Ok (_ ) => {
201+ println ("ok" )
202+ 0
203+ }
204+ Err (reason ) => {
205+ println (
206+ "validation error: " + reason .code () + ": " + reason .message (),
207+ )
208+ 1
209+ }
210+ }
211+ }
212+ Err (err ) => {
213+ println (@compiler .describe_error (err ))
214+ 1
215+ }
216+ }
217+ }
218+ Err (err ) => {
219+ println (@compiler .describe_error (err ))
220+ 1
221+ }
222+ }
223+ }
81224 }
82225 }
83226 }
84- None => 1
227+ Err (err ) => {
228+ if json_output {
229+ let reasons : Array [@core .Reason ] = []
230+ reasons .push (@core .Reason ::new (
231+ "ReadFailure" ,
232+ "read error: " + err .to_string (),
233+ ))
234+ println (@compiler .validation_json_string (false , reasons ))
235+ } else {
236+ println ("read error: " + err .to_string ())
237+ }
238+ 1
239+ }
85240 }
86241 } else {
87242 let input_path = args [0 ]
0 commit comments