@@ -1469,98 +1469,20 @@ impl GlobalContext {
1469
1469
self . _load_file ( & self . cwd ( ) . join ( & str_path) , & mut seen, true , WhyLoad :: Cli )
1470
1470
. with_context ( || format ! ( "failed to load config from `{}`" , str_path) ) ?
1471
1471
} 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 ( ) )
1552
1474
. with_context ( || {
1553
1475
format ! ( "failed to parse value from --config argument `{arg}`" )
1554
1476
} ) ?;
1555
1477
1556
- if toml_v
1478
+ if doc
1557
1479
. get ( "registry" )
1558
1480
. and_then ( |v| v. as_table ( ) )
1559
1481
. and_then ( |t| t. get ( "token" ) )
1560
1482
. is_some ( )
1561
1483
{
1562
1484
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
1564
1486
. get ( "registries" )
1565
1487
. and_then ( |v| v. as_table ( ) )
1566
1488
. and_then ( |t| t. iter ( ) . find ( |( _, v) | v. get ( "token" ) . is_some ( ) ) )
@@ -1571,7 +1493,7 @@ impl GlobalContext {
1571
1493
) ;
1572
1494
}
1573
1495
1574
- if toml_v
1496
+ if doc
1575
1497
. get ( "registry" )
1576
1498
. and_then ( |v| v. as_table ( ) )
1577
1499
. and_then ( |t| t. get ( "secret-key" ) )
@@ -1580,7 +1502,7 @@ impl GlobalContext {
1580
1502
bail ! (
1581
1503
"registry.secret-key cannot be set through --config for security reasons"
1582
1504
) ;
1583
- } else if let Some ( ( k, _) ) = toml_v
1505
+ } else if let Some ( ( k, _) ) = doc
1584
1506
. get ( "registries" )
1585
1507
. and_then ( |v| v. as_table ( ) )
1586
1508
. and_then ( |t| t. iter ( ) . find ( |( _, v) | v. get ( "secret-key" ) . is_some ( ) ) )
@@ -1591,7 +1513,7 @@ impl GlobalContext {
1591
1513
) ;
1592
1514
}
1593
1515
1594
- CV :: from_toml ( Definition :: Cli ( None ) , toml_v )
1516
+ CV :: from_toml ( Definition :: Cli ( None ) , doc )
1595
1517
. with_context ( || format ! ( "failed to convert --config argument `{arg}`" ) ) ?
1596
1518
} ;
1597
1519
let tmp_table = self
@@ -3056,6 +2978,88 @@ fn parse_document(toml: &str, _file: &Path, _gctx: &GlobalContext) -> CargoResul
3056
2978
toml. parse ( ) . map_err ( Into :: into)
3057
2979
}
3058
2980
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
+
3059
3063
/// A type to deserialize a list of strings from a toml file.
3060
3064
///
3061
3065
/// Supports deserializing either a whitespace-separated list of arguments in a
0 commit comments