@@ -172,6 +172,7 @@ pub struct Config {
172172 net_config : LazyCell < CargoNetConfig > ,
173173 build_config : LazyCell < CargoBuildConfig > ,
174174 target_cfgs : LazyCell < Vec < ( String , TargetCfgConfig ) > > ,
175+ progress_config : ProgressConfig ,
175176}
176177
177178impl Config {
@@ -241,6 +242,7 @@ impl Config {
241242 net_config : LazyCell :: new ( ) ,
242243 build_config : LazyCell :: new ( ) ,
243244 target_cfgs : LazyCell :: new ( ) ,
245+ progress_config : ProgressConfig :: default ( ) ,
244246 }
245247 }
246248
@@ -442,8 +444,8 @@ impl Config {
442444
443445 /// Get a configuration value by key.
444446 ///
445- /// This does NOT look at environment variables, the caller is responsible
446- /// for that.
447+ /// This does NOT look at environment variables. See `get_cv_with_env` for
448+ /// a variant that supports environment variables .
447449 fn get_cv ( & self , key : & ConfigKey ) -> CargoResult < Option < ConfigValue > > {
448450 log:: trace!( "get cv {:?}" , key) ;
449451 let vals = self . values ( ) ?;
@@ -620,13 +622,9 @@ impl Config {
620622 let extra_verbose = verbose >= 2 ;
621623 let verbose = verbose != 0 ;
622624
623- #[ derive( Deserialize , Default ) ]
624- struct TermConfig {
625- verbose : Option < bool > ,
626- color : Option < String > ,
627- }
628-
629- // Ignore errors in the configuration files.
625+ // Ignore errors in the configuration files. We don't want basic
626+ // commands like `cargo version` to error out due to config file
627+ // problems.
630628 let term = self . get :: < TermConfig > ( "term" ) . unwrap_or_default ( ) ;
631629
632630 let color = color. or_else ( || term. color . as_ref ( ) . map ( |s| s. as_ref ( ) ) ) ;
@@ -654,6 +652,7 @@ impl Config {
654652
655653 self . shell ( ) . set_verbosity ( verbosity) ;
656654 self . shell ( ) . set_color_choice ( color) ?;
655+ self . progress_config = term. progress . unwrap_or_default ( ) ;
657656 self . extra_verbose = extra_verbose;
658657 self . frozen = frozen;
659658 self . locked = locked;
@@ -1054,6 +1053,20 @@ impl Config {
10541053 . try_borrow_with ( || Ok ( self . get :: < CargoBuildConfig > ( "build" ) ?) )
10551054 }
10561055
1056+ pub fn progress_config ( & self ) -> & ProgressConfig {
1057+ & self . progress_config
1058+ }
1059+
1060+ /// This is used to validate the `term` table has valid syntax.
1061+ ///
1062+ /// This is necessary because loading the term settings happens very
1063+ /// early, and in some situations (like `cargo version`) we don't want to
1064+ /// fail if there are problems with the config file.
1065+ pub fn validate_term_config ( & self ) -> CargoResult < ( ) > {
1066+ drop ( self . get :: < TermConfig > ( "term" ) ?) ;
1067+ Ok ( ( ) )
1068+ }
1069+
10571070 /// Returns a list of [target.'cfg()'] tables.
10581071 ///
10591072 /// The list is sorted by the table name.
@@ -1640,6 +1653,101 @@ pub struct CargoBuildConfig {
16401653 pub out_dir : Option < ConfigRelativePath > ,
16411654}
16421655
1656+ #[ derive( Deserialize , Default ) ]
1657+ struct TermConfig {
1658+ verbose : Option < bool > ,
1659+ color : Option < String > ,
1660+ #[ serde( default ) ]
1661+ #[ serde( deserialize_with = "progress_or_string" ) ]
1662+ progress : Option < ProgressConfig > ,
1663+ }
1664+
1665+ #[ derive( Debug , Default , Deserialize ) ]
1666+ pub struct ProgressConfig {
1667+ pub when : ProgressWhen ,
1668+ pub width : Option < usize > ,
1669+ }
1670+
1671+ #[ derive( Debug , Deserialize ) ]
1672+ #[ serde( rename_all = "lowercase" ) ]
1673+ pub enum ProgressWhen {
1674+ Auto ,
1675+ Never ,
1676+ Always ,
1677+ }
1678+
1679+ impl Default for ProgressWhen {
1680+ fn default ( ) -> ProgressWhen {
1681+ ProgressWhen :: Auto
1682+ }
1683+ }
1684+
1685+ fn progress_or_string < ' de , D > ( deserializer : D ) -> Result < Option < ProgressConfig > , D :: Error >
1686+ where
1687+ D : serde:: de:: Deserializer < ' de > ,
1688+ {
1689+ struct ProgressVisitor ;
1690+
1691+ impl < ' de > serde:: de:: Visitor < ' de > for ProgressVisitor {
1692+ type Value = Option < ProgressConfig > ;
1693+
1694+ fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1695+ formatter. write_str ( "a string (\" auto\" or \" never\" ) or a table" )
1696+ }
1697+
1698+ fn visit_none < E > ( self ) -> Result < Self :: Value , E >
1699+ where
1700+ E : serde:: de:: Error ,
1701+ {
1702+ Ok ( None )
1703+ }
1704+
1705+ fn visit_some < D > ( self , deserializer : D ) -> Result < Self :: Value , D :: Error >
1706+ where
1707+ D : serde:: de:: Deserializer < ' de > ,
1708+ {
1709+ ProgressConfig :: deserialize ( deserializer) . map ( Some )
1710+ }
1711+
1712+ fn visit_str < E > ( self , s : & str ) -> Result < Self :: Value , E >
1713+ where
1714+ E : serde:: de:: Error ,
1715+ {
1716+ match s {
1717+ "auto" => Ok ( Some ( ProgressConfig {
1718+ when : ProgressWhen :: Auto ,
1719+ width : None ,
1720+ } ) ) ,
1721+ "never" => Ok ( Some ( ProgressConfig {
1722+ when : ProgressWhen :: Never ,
1723+ width : None ,
1724+ } ) ) ,
1725+ "always" => Err ( E :: custom ( "\" always\" progress requires a `width` key" ) ) ,
1726+ _ => Err ( E :: unknown_variant ( s, & [ "auto" , "never" ] ) ) ,
1727+ }
1728+ }
1729+
1730+ fn visit_map < M > ( self , map : M ) -> Result < Self :: Value , M :: Error >
1731+ where
1732+ M : serde:: de:: MapAccess < ' de > ,
1733+ {
1734+ let pc = Deserialize :: deserialize ( serde:: de:: value:: MapAccessDeserializer :: new ( map) ) ?;
1735+ if let ProgressConfig {
1736+ when : ProgressWhen :: Always ,
1737+ width : None ,
1738+ } = pc
1739+ {
1740+ return Err ( serde:: de:: Error :: custom (
1741+ "\" always\" progress requires a `width` key" ,
1742+ ) ) ;
1743+ }
1744+ Ok ( Some ( pc) )
1745+ }
1746+ }
1747+
1748+ deserializer. deserialize_any ( ProgressVisitor )
1749+ }
1750+
16431751/// A type to deserialize a list of strings from a toml file.
16441752///
16451753/// Supports deserializing either a whitespace-separated list of arguments in a
0 commit comments