@@ -16,6 +16,7 @@ use std::{cmp, env, fs};
16
16
use build_helper:: ci:: CiEnv ;
17
17
use build_helper:: exit;
18
18
use build_helper:: git:: { GitConfig , get_closest_merge_commit, output_result} ;
19
+ use serde:: de:: Visitor ;
19
20
use serde:: { Deserialize , Deserializer } ;
20
21
use serde_derive:: Deserialize ;
21
22
#[ cfg( feature = "tracing" ) ]
@@ -183,6 +184,62 @@ pub enum GccCiMode {
183
184
DownloadFromCi ,
184
185
}
185
186
187
+ /// This enum is used for deserializing change IDs from TOML, allowing both numeric values and the string `"ignore"`.
188
+ #[ derive( Clone , Debug , PartialEq ) ]
189
+ pub enum ChangeId {
190
+ Ignore ,
191
+ Id ( usize ) ,
192
+ }
193
+
194
+ impl < ' de > Deserialize < ' de > for ChangeId {
195
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
196
+ where
197
+ D : Deserializer < ' de > ,
198
+ {
199
+ struct ChangeIdVisitor ;
200
+
201
+ impl Visitor < ' _ > for ChangeIdVisitor {
202
+ type Value = ChangeId ;
203
+
204
+ fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
205
+ formatter. write_str ( "a usize number or the string \" ignore\" " )
206
+ }
207
+
208
+ fn visit_i64 < E > ( self , value : i64 ) -> Result < Self :: Value , E >
209
+ where
210
+ E : serde:: de:: Error ,
211
+ {
212
+ if value >= 0 {
213
+ Ok ( ChangeId :: Id ( value as usize ) )
214
+ } else {
215
+ Err ( E :: custom ( format ! (
216
+ "invalid negative number `{}`, expected a non-negative usize or \" ignore\" " ,
217
+ value
218
+ ) ) )
219
+ }
220
+ }
221
+
222
+ fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
223
+ where
224
+ E : serde:: de:: Error ,
225
+ {
226
+ let value = value. trim ( ) ;
227
+ if value. eq_ignore_ascii_case ( "ignore" ) {
228
+ Ok ( ChangeId :: Ignore )
229
+ } else if let Ok ( num) = value. parse :: < usize > ( ) {
230
+ Ok ( ChangeId :: Id ( num) )
231
+ } else {
232
+ Err ( E :: custom ( format ! (
233
+ "invalid value `{}`, expected a usize number or \" ignore\" " ,
234
+ value
235
+ ) ) )
236
+ }
237
+ }
238
+ }
239
+ deserializer. deserialize_any ( ChangeIdVisitor )
240
+ }
241
+ }
242
+
186
243
/// Global configuration for the entire build and/or bootstrap.
187
244
///
188
245
/// This structure is parsed from `bootstrap.toml`, and some of the fields are inferred from `git` or build-time parameters.
@@ -193,7 +250,7 @@ pub enum GccCiMode {
193
250
/// `bootstrap.example.toml`.
194
251
#[ derive( Default , Clone ) ]
195
252
pub struct Config {
196
- pub change_id : Option < usize > ,
253
+ pub change_id : Option < ChangeId > ,
197
254
pub bypass_bootstrap_lock : bool ,
198
255
pub ccache : Option < String > ,
199
256
/// Call Build::ninja() instead of this.
@@ -707,7 +764,7 @@ pub(crate) struct TomlConfig {
707
764
#[ derive( Deserialize , Default ) ]
708
765
pub ( crate ) struct ChangeIdWrapper {
709
766
#[ serde( alias = "change-id" ) ]
710
- pub ( crate ) inner : Option < usize > ,
767
+ pub ( crate ) inner : Option < ChangeId > ,
711
768
}
712
769
713
770
/// Describes how to handle conflicts in merging two [`TomlConfig`]
0 commit comments