@@ -16,6 +16,7 @@ use std::{cmp, env, fs};
1616use build_helper:: ci:: CiEnv ;
1717use build_helper:: exit;
1818use build_helper:: git:: { GitConfig , get_closest_merge_commit, output_result} ;
19+ use serde:: de:: Visitor ;
1920use serde:: { Deserialize , Deserializer } ;
2021use serde_derive:: Deserialize ;
2122#[ cfg( feature = "tracing" ) ]
@@ -183,6 +184,62 @@ pub enum GccCiMode {
183184 DownloadFromCi ,
184185}
185186
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+
186243/// Global configuration for the entire build and/or bootstrap.
187244///
188245/// 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 {
193250/// `bootstrap.example.toml`.
194251#[ derive( Default , Clone ) ]
195252pub struct Config {
196- pub change_id : Option < usize > ,
253+ pub change_id : Option < ChangeId > ,
197254 pub bypass_bootstrap_lock : bool ,
198255 pub ccache : Option < String > ,
199256 /// Call Build::ninja() instead of this.
@@ -707,7 +764,7 @@ pub(crate) struct TomlConfig {
707764#[ derive( Deserialize , Default ) ]
708765pub ( crate ) struct ChangeIdWrapper {
709766 #[ serde( alias = "change-id" ) ]
710- pub ( crate ) inner : Option < usize > ,
767+ pub ( crate ) inner : Option < ChangeId > ,
711768}
712769
713770/// Describes how to handle conflicts in merging two [`TomlConfig`]
0 commit comments