@@ -1469,98 +1469,20 @@ impl GlobalContext {
14691469 self . _load_file ( & self . cwd ( ) . join ( & str_path) , & mut seen, true , WhyLoad :: Cli )
14701470 . with_context ( || format ! ( "failed to load config from `{}`" , str_path) ) ?
14711471 } else {
1472- // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys)
1473- // expressions followed by a value that's not an "inline table"
1474- // (https://toml.io/en/v1.0.0#inline-table). Easiest way to check for that is to
1475- // parse the value as a toml_edit::DocumentMut, and check that the (single)
1476- // inner-most table is set via dotted keys.
1477- let doc: toml_edit:: DocumentMut = arg. parse ( ) . with_context ( || {
1478- format ! ( "failed to parse value from --config argument `{arg}` as a dotted key expression" )
1479- } ) ?;
1480- fn non_empty ( d : Option < & toml_edit:: RawString > ) -> bool {
1481- d. map_or ( false , |p| !p. as_str ( ) . unwrap_or_default ( ) . trim ( ) . is_empty ( ) )
1482- }
1483- fn non_empty_decor ( d : & toml_edit:: Decor ) -> bool {
1484- non_empty ( d. prefix ( ) ) || non_empty ( d. suffix ( ) )
1485- }
1486- fn non_empty_key_decor ( k : & toml_edit:: Key ) -> bool {
1487- non_empty_decor ( k. leaf_decor ( ) ) || non_empty_decor ( k. dotted_decor ( ) )
1488- }
1489- let ok = {
1490- let mut got_to_value = false ;
1491- let mut table = doc. as_table ( ) ;
1492- let mut is_root = true ;
1493- while table. is_dotted ( ) || is_root {
1494- is_root = false ;
1495- if table. len ( ) != 1 {
1496- break ;
1497- }
1498- let ( k, n) = table. iter ( ) . next ( ) . expect ( "len() == 1 above" ) ;
1499- match n {
1500- Item :: Table ( nt) => {
1501- if table. key ( k) . map_or ( false , non_empty_key_decor)
1502- || non_empty_decor ( nt. decor ( ) )
1503- {
1504- bail ! (
1505- "--config argument `{arg}` \
1506- includes non-whitespace decoration"
1507- )
1508- }
1509- table = nt;
1510- }
1511- Item :: Value ( v) if v. is_inline_table ( ) => {
1512- bail ! (
1513- "--config argument `{arg}` \
1514- sets a value to an inline table, which is not accepted"
1515- ) ;
1516- }
1517- Item :: Value ( v) => {
1518- if table
1519- . key ( k)
1520- . map_or ( false , |k| non_empty ( k. leaf_decor ( ) . prefix ( ) ) )
1521- || non_empty_decor ( v. decor ( ) )
1522- {
1523- bail ! (
1524- "--config argument `{arg}` \
1525- includes non-whitespace decoration"
1526- )
1527- }
1528- got_to_value = true ;
1529- break ;
1530- }
1531- Item :: ArrayOfTables ( _) => {
1532- bail ! (
1533- "--config argument `{arg}` \
1534- sets a value to an array of tables, which is not accepted"
1535- ) ;
1536- }
1537-
1538- Item :: None => {
1539- bail ! ( "--config argument `{arg}` doesn't provide a value" )
1540- }
1541- }
1542- }
1543- got_to_value
1544- } ;
1545- if !ok {
1546- bail ! (
1547- "--config argument `{arg}` was not a TOML dotted key expression (such as `build.jobs = 2`)"
1548- ) ;
1549- }
1550-
1551- let toml_v: toml:: Value = toml:: Value :: deserialize ( doc. into_deserializer ( ) )
1472+ let doc = toml_dotted_keys ( arg) ?;
1473+ let doc: toml:: Value = toml:: Value :: deserialize ( doc. into_deserializer ( ) )
15521474 . with_context ( || {
15531475 format ! ( "failed to parse value from --config argument `{arg}`" )
15541476 } ) ?;
15551477
1556- if toml_v
1478+ if doc
15571479 . get ( "registry" )
15581480 . and_then ( |v| v. as_table ( ) )
15591481 . and_then ( |t| t. get ( "token" ) )
15601482 . is_some ( )
15611483 {
15621484 bail ! ( "registry.token cannot be set through --config for security reasons" ) ;
1563- } else if let Some ( ( k, _) ) = toml_v
1485+ } else if let Some ( ( k, _) ) = doc
15641486 . get ( "registries" )
15651487 . and_then ( |v| v. as_table ( ) )
15661488 . and_then ( |t| t. iter ( ) . find ( |( _, v) | v. get ( "token" ) . is_some ( ) ) )
@@ -1571,7 +1493,7 @@ impl GlobalContext {
15711493 ) ;
15721494 }
15731495
1574- if toml_v
1496+ if doc
15751497 . get ( "registry" )
15761498 . and_then ( |v| v. as_table ( ) )
15771499 . and_then ( |t| t. get ( "secret-key" ) )
@@ -1580,7 +1502,7 @@ impl GlobalContext {
15801502 bail ! (
15811503 "registry.secret-key cannot be set through --config for security reasons"
15821504 ) ;
1583- } else if let Some ( ( k, _) ) = toml_v
1505+ } else if let Some ( ( k, _) ) = doc
15841506 . get ( "registries" )
15851507 . and_then ( |v| v. as_table ( ) )
15861508 . and_then ( |t| t. iter ( ) . find ( |( _, v) | v. get ( "secret-key" ) . is_some ( ) ) )
@@ -1591,7 +1513,7 @@ impl GlobalContext {
15911513 ) ;
15921514 }
15931515
1594- CV :: from_toml ( Definition :: Cli ( None ) , toml_v )
1516+ CV :: from_toml ( Definition :: Cli ( None ) , doc )
15951517 . with_context ( || format ! ( "failed to convert --config argument `{arg}`" ) ) ?
15961518 } ;
15971519 let tmp_table = self
@@ -3056,6 +2978,88 @@ fn parse_document(toml: &str, _file: &Path, _gctx: &GlobalContext) -> CargoResul
30562978 toml. parse ( ) . map_err ( Into :: into)
30572979}
30582980
2981+ fn toml_dotted_keys ( arg : & str ) -> CargoResult < toml_edit:: DocumentMut > {
2982+ // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys)
2983+ // expressions followed by a value that's not an "inline table"
2984+ // (https://toml.io/en/v1.0.0#inline-table). Easiest way to check for that is to
2985+ // parse the value as a toml_edit::DocumentMut, and check that the (single)
2986+ // inner-most table is set via dotted keys.
2987+ let doc: toml_edit:: DocumentMut = arg. parse ( ) . with_context ( || {
2988+ format ! ( "failed to parse value from --config argument `{arg}` as a dotted key expression" )
2989+ } ) ?;
2990+ fn non_empty ( d : Option < & toml_edit:: RawString > ) -> bool {
2991+ d. map_or ( false , |p| !p. as_str ( ) . unwrap_or_default ( ) . trim ( ) . is_empty ( ) )
2992+ }
2993+ fn non_empty_decor ( d : & toml_edit:: Decor ) -> bool {
2994+ non_empty ( d. prefix ( ) ) || non_empty ( d. suffix ( ) )
2995+ }
2996+ fn non_empty_key_decor ( k : & toml_edit:: Key ) -> bool {
2997+ non_empty_decor ( k. leaf_decor ( ) ) || non_empty_decor ( k. dotted_decor ( ) )
2998+ }
2999+ let ok = {
3000+ let mut got_to_value = false ;
3001+ let mut table = doc. as_table ( ) ;
3002+ let mut is_root = true ;
3003+ while table. is_dotted ( ) || is_root {
3004+ is_root = false ;
3005+ if table. len ( ) != 1 {
3006+ break ;
3007+ }
3008+ let ( k, n) = table. iter ( ) . next ( ) . expect ( "len() == 1 above" ) ;
3009+ match n {
3010+ Item :: Table ( nt) => {
3011+ if table. key ( k) . map_or ( false , non_empty_key_decor)
3012+ || non_empty_decor ( nt. decor ( ) )
3013+ {
3014+ bail ! (
3015+ "--config argument `{arg}` \
3016+ includes non-whitespace decoration"
3017+ )
3018+ }
3019+ table = nt;
3020+ }
3021+ Item :: Value ( v) if v. is_inline_table ( ) => {
3022+ bail ! (
3023+ "--config argument `{arg}` \
3024+ sets a value to an inline table, which is not accepted"
3025+ ) ;
3026+ }
3027+ Item :: Value ( v) => {
3028+ if table
3029+ . key ( k)
3030+ . map_or ( false , |k| non_empty ( k. leaf_decor ( ) . prefix ( ) ) )
3031+ || non_empty_decor ( v. decor ( ) )
3032+ {
3033+ bail ! (
3034+ "--config argument `{arg}` \
3035+ includes non-whitespace decoration"
3036+ )
3037+ }
3038+ got_to_value = true ;
3039+ break ;
3040+ }
3041+ Item :: ArrayOfTables ( _) => {
3042+ bail ! (
3043+ "--config argument `{arg}` \
3044+ sets a value to an array of tables, which is not accepted"
3045+ ) ;
3046+ }
3047+
3048+ Item :: None => {
3049+ bail ! ( "--config argument `{arg}` doesn't provide a value" )
3050+ }
3051+ }
3052+ }
3053+ got_to_value
3054+ } ;
3055+ if !ok {
3056+ bail ! (
3057+ "--config argument `{arg}` was not a TOML dotted key expression (such as `build.jobs = 2`)"
3058+ ) ;
3059+ }
3060+ Ok ( doc)
3061+ }
3062+
30593063/// A type to deserialize a list of strings from a toml file.
30603064///
30613065/// Supports deserializing either a whitespace-separated list of arguments in a
0 commit comments