@@ -176,6 +176,7 @@ pub struct Config {
176176 build_config : LazyCell < CargoBuildConfig > ,
177177 target_cfgs : LazyCell < Vec < ( String , TargetCfgConfig ) > > ,
178178 doc_extern_map : LazyCell < RustdocExternMap > ,
179+ progress_config : ProgressConfig ,
179180}
180181
181182impl Config {
@@ -247,6 +248,7 @@ impl Config {
247248 build_config : LazyCell :: new ( ) ,
248249 target_cfgs : LazyCell :: new ( ) ,
249250 doc_extern_map : LazyCell :: new ( ) ,
251+ progress_config : ProgressConfig :: default ( ) ,
250252 }
251253 }
252254
@@ -459,8 +461,8 @@ impl Config {
459461
460462 /// Get a configuration value by key.
461463 ///
462- /// This does NOT look at environment variables, the caller is responsible
463- /// for that.
464+ /// This does NOT look at environment variables. See `get_cv_with_env` for
465+ /// a variant that supports environment variables .
464466 fn get_cv ( & self , key : & ConfigKey ) -> CargoResult < Option < ConfigValue > > {
465467 log:: trace!( "get cv {:?}" , key) ;
466468 let vals = self . values ( ) ?;
@@ -720,13 +722,9 @@ impl Config {
720722 let extra_verbose = verbose >= 2 ;
721723 let verbose = verbose != 0 ;
722724
723- #[ derive( Deserialize , Default ) ]
724- struct TermConfig {
725- verbose : Option < bool > ,
726- color : Option < String > ,
727- }
728-
729- // Ignore errors in the configuration files.
725+ // Ignore errors in the configuration files. We don't want basic
726+ // commands like `cargo version` to error out due to config file
727+ // problems.
730728 let term = self . get :: < TermConfig > ( "term" ) . unwrap_or_default ( ) ;
731729
732730 let color = color. or_else ( || term. color . as_deref ( ) ) ;
@@ -754,6 +752,7 @@ impl Config {
754752
755753 self . shell ( ) . set_verbosity ( verbosity) ;
756754 self . shell ( ) . set_color_choice ( color) ?;
755+ self . progress_config = term. progress . unwrap_or_default ( ) ;
757756 self . extra_verbose = extra_verbose;
758757 self . frozen = frozen;
759758 self . locked = locked;
@@ -1192,6 +1191,20 @@ impl Config {
11921191 . try_borrow_with ( || Ok ( self . get :: < CargoBuildConfig > ( "build" ) ?) )
11931192 }
11941193
1194+ pub fn progress_config ( & self ) -> & ProgressConfig {
1195+ & self . progress_config
1196+ }
1197+
1198+ /// This is used to validate the `term` table has valid syntax.
1199+ ///
1200+ /// This is necessary because loading the term settings happens very
1201+ /// early, and in some situations (like `cargo version`) we don't want to
1202+ /// fail if there are problems with the config file.
1203+ pub fn validate_term_config ( & self ) -> CargoResult < ( ) > {
1204+ drop ( self . get :: < TermConfig > ( "term" ) ?) ;
1205+ Ok ( ( ) )
1206+ }
1207+
11951208 /// Returns a list of [target.'cfg()'] tables.
11961209 ///
11971210 /// The list is sorted by the table name.
@@ -1778,6 +1791,94 @@ pub struct CargoBuildConfig {
17781791 pub out_dir : Option < ConfigRelativePath > ,
17791792}
17801793
1794+ #[ derive( Deserialize , Default ) ]
1795+ struct TermConfig {
1796+ verbose : Option < bool > ,
1797+ color : Option < String > ,
1798+ #[ serde( default ) ]
1799+ #[ serde( deserialize_with = "progress_or_string" ) ]
1800+ progress : Option < ProgressConfig > ,
1801+ }
1802+
1803+ #[ derive( Debug , Default , Deserialize ) ]
1804+ pub struct ProgressConfig {
1805+ pub when : ProgressWhen ,
1806+ pub width : Option < usize > ,
1807+ }
1808+
1809+ #[ derive( Debug , Deserialize ) ]
1810+ #[ serde( rename_all = "lowercase" ) ]
1811+ pub enum ProgressWhen {
1812+ Auto ,
1813+ Never ,
1814+ Always ,
1815+ }
1816+
1817+ impl Default for ProgressWhen {
1818+ fn default ( ) -> ProgressWhen {
1819+ ProgressWhen :: Auto
1820+ }
1821+ }
1822+
1823+ fn progress_or_string < ' de , D > ( deserializer : D ) -> Result < Option < ProgressConfig > , D :: Error >
1824+ where
1825+ D : serde:: de:: Deserializer < ' de > ,
1826+ {
1827+ struct ProgressVisitor ;
1828+
1829+ impl < ' de > serde:: de:: Visitor < ' de > for ProgressVisitor {
1830+ type Value = Option < ProgressConfig > ;
1831+
1832+ fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1833+ formatter. write_str ( "a string (\" auto\" or \" never\" ) or a table" )
1834+ }
1835+
1836+ fn visit_str < E > ( self , s : & str ) -> Result < Self :: Value , E >
1837+ where
1838+ E : serde:: de:: Error ,
1839+ {
1840+ match s {
1841+ "auto" => Ok ( Some ( ProgressConfig {
1842+ when : ProgressWhen :: Auto ,
1843+ width : None ,
1844+ } ) ) ,
1845+ "never" => Ok ( Some ( ProgressConfig {
1846+ when : ProgressWhen :: Never ,
1847+ width : None ,
1848+ } ) ) ,
1849+ "always" => Err ( E :: custom ( "\" always\" progress requires a `width` key" ) ) ,
1850+ _ => Err ( E :: unknown_variant ( s, & [ "auto" , "never" ] ) ) ,
1851+ }
1852+ }
1853+
1854+ fn visit_none < E > ( self ) -> Result < Self :: Value , E >
1855+ where
1856+ E : serde:: de:: Error ,
1857+ {
1858+ Ok ( None )
1859+ }
1860+
1861+ fn visit_some < D > ( self , deserializer : D ) -> Result < Self :: Value , D :: Error >
1862+ where
1863+ D : serde:: de:: Deserializer < ' de > ,
1864+ {
1865+ let pc = ProgressConfig :: deserialize ( deserializer) ?;
1866+ if let ProgressConfig {
1867+ when : ProgressWhen :: Always ,
1868+ width : None ,
1869+ } = pc
1870+ {
1871+ return Err ( serde:: de:: Error :: custom (
1872+ "\" always\" progress requires a `width` key" ,
1873+ ) ) ;
1874+ }
1875+ Ok ( Some ( pc) )
1876+ }
1877+ }
1878+
1879+ deserializer. deserialize_option ( ProgressVisitor )
1880+ }
1881+
17811882/// A type to deserialize a list of strings from a toml file.
17821883///
17831884/// Supports deserializing either a whitespace-separated list of arguments in a
0 commit comments