@@ -176,6 +176,7 @@ pub struct Config {
176
176
build_config : LazyCell < CargoBuildConfig > ,
177
177
target_cfgs : LazyCell < Vec < ( String , TargetCfgConfig ) > > ,
178
178
doc_extern_map : LazyCell < RustdocExternMap > ,
179
+ progress_config : ProgressConfig ,
179
180
}
180
181
181
182
impl Config {
@@ -247,6 +248,7 @@ impl Config {
247
248
build_config : LazyCell :: new ( ) ,
248
249
target_cfgs : LazyCell :: new ( ) ,
249
250
doc_extern_map : LazyCell :: new ( ) ,
251
+ progress_config : ProgressConfig :: default ( ) ,
250
252
}
251
253
}
252
254
@@ -459,8 +461,8 @@ impl Config {
459
461
460
462
/// Get a configuration value by key.
461
463
///
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 .
464
466
fn get_cv ( & self , key : & ConfigKey ) -> CargoResult < Option < ConfigValue > > {
465
467
log:: trace!( "get cv {:?}" , key) ;
466
468
let vals = self . values ( ) ?;
@@ -720,13 +722,9 @@ impl Config {
720
722
let extra_verbose = verbose >= 2 ;
721
723
let verbose = verbose != 0 ;
722
724
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.
730
728
let term = self . get :: < TermConfig > ( "term" ) . unwrap_or_default ( ) ;
731
729
732
730
let color = color. or_else ( || term. color . as_deref ( ) ) ;
@@ -754,6 +752,7 @@ impl Config {
754
752
755
753
self . shell ( ) . set_verbosity ( verbosity) ;
756
754
self . shell ( ) . set_color_choice ( color) ?;
755
+ self . progress_config = term. progress . unwrap_or_default ( ) ;
757
756
self . extra_verbose = extra_verbose;
758
757
self . frozen = frozen;
759
758
self . locked = locked;
@@ -1192,6 +1191,20 @@ impl Config {
1192
1191
. try_borrow_with ( || Ok ( self . get :: < CargoBuildConfig > ( "build" ) ?) )
1193
1192
}
1194
1193
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
+
1195
1208
/// Returns a list of [target.'cfg()'] tables.
1196
1209
///
1197
1210
/// The list is sorted by the table name.
@@ -1778,6 +1791,94 @@ pub struct CargoBuildConfig {
1778
1791
pub out_dir : Option < ConfigRelativePath > ,
1779
1792
}
1780
1793
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
+
1781
1882
/// A type to deserialize a list of strings from a toml file.
1782
1883
///
1783
1884
/// Supports deserializing either a whitespace-separated list of arguments in a
0 commit comments