1
1
//! Utility functions for updating plist files.
2
2
//
3
3
// NB: Most of this code originated from: https://github.com/gibfahn/up-rs, MIT & Apache 2.0 licensed.
4
- //
4
+
5
+ use std:: collections:: HashMap ;
6
+ use std:: fs:: { self , File } ;
7
+ use std:: io:: Read ;
8
+ use std:: mem;
9
+
5
10
use camino:: { Utf8Path , Utf8PathBuf } ;
6
11
use color_eyre:: eyre:: { eyre, Result } ;
7
12
use duct:: cmd;
8
13
use log:: { debug, info, trace, warn} ;
9
14
use plist:: { Dictionary , Value } ;
10
15
use serde:: { Deserialize , Serialize } ;
11
- use std:: collections:: HashMap ;
12
- use std:: fs:: { self , File } ;
13
- use std:: io:: Read ;
14
- use std:: mem;
15
16
16
17
use super :: errors:: DefaultsError as E ;
17
18
@@ -356,12 +357,14 @@ fn merge_value(new_value: &mut Value, old_value: Option<&Value>) {
356
357
/// But any duplicates between old and new values are removed, with the first value taking
357
358
/// precedence.
358
359
fn replace_ellipsis_array ( new_value : & mut Value , old_value : Option < & Value > ) {
360
+ //
359
361
let Value :: Array ( new_array) = new_value else {
360
362
trace ! ( "Value isn't an array, skipping ellipsis replacement..." ) ;
361
363
return ;
362
364
} ;
363
365
364
366
let ellipsis = plist:: Value :: from ( ELLIPSIS ) ;
367
+
365
368
let Some ( position) = new_array. iter ( ) . position ( |x| x == & ellipsis) else {
366
369
trace ! ( "New value doesn't contain ellipsis, skipping ellipsis replacement..." ) ;
367
370
return ;
@@ -376,6 +379,7 @@ fn replace_ellipsis_array(new_value: &mut Value, old_value: Option<&Value>) {
376
379
let array_copy: Vec < _ > = std:: mem:: take ( new_array) ;
377
380
378
381
trace ! ( "Performing array ellipsis replacement..." ) ;
382
+
379
383
for element in array_copy {
380
384
if element == ellipsis {
381
385
for old_element in old_array {
@@ -390,30 +394,33 @@ fn replace_ellipsis_array(new_value: &mut Value, old_value: Option<&Value>) {
390
394
}
391
395
}
392
396
393
- /// Recursively merge dictionaries, unless the new value is empty `{}`.
394
- /// If a dictionary
395
- /// * is empty `{}`
396
- /// * contains a key `{}`
397
- /// Then the merge step will be skipped for it and its children.
397
+ // Recursively merge dictionaries, unless the new value is empty `{}`.
398
+ // If a dictionary
399
+ // * is empty `{}`
400
+ // * contains a key `{}`
401
+ // Then the merge step will be skipped for it and its children.
398
402
fn deep_merge_dictionaries ( new_value : & mut Value , old_value : Option < & Value > ) {
403
+ //
399
404
let Value :: Dictionary ( new_dict) = new_value else {
400
405
trace ! ( "New value is not a dictionary, Skipping merge..." ) ;
401
406
return ;
402
407
} ;
408
+
403
409
if new_dict. is_empty ( ) {
404
410
trace ! ( "New value is an empty dictionary. Skipping merge..." ) ;
405
411
return ;
406
412
}
413
+
407
414
// the "..." key is no longer used, and its merging behavior is performed by default. ignore it, for compatibility with older YAML.
408
415
new_dict. remove ( ELLIPSIS ) ;
409
416
410
417
let Some ( old_dict) = old_value. and_then ( plist:: Value :: as_dictionary) else {
411
418
trace ! ( "Old value wasn't a dict. Skipping merge..." ) ;
412
419
return ;
413
420
} ;
414
-
421
+
415
422
// for each value, recursively invoke this to merge any child dictionaries.
416
- // also perform array ellipsis replacment .
423
+ // also perform array ellipsis replacement .
417
424
// this occurs even if "!" is present.
418
425
for ( key, new_child_value) in & mut * new_dict {
419
426
let old_child_value = old_dict. get ( key) ;
@@ -425,7 +432,9 @@ fn deep_merge_dictionaries(new_value: &mut Value, old_value: Option<&Value>) {
425
432
new_dict. remove ( BANG ) ;
426
433
return ;
427
434
}
435
+
428
436
trace ! ( "Performing deep merge..." ) ;
437
+
429
438
for ( key, old_value) in old_dict {
430
439
if !new_dict. contains_key ( key) {
431
440
new_dict. insert ( key. clone ( ) , old_value. clone ( ) ) ;
@@ -497,10 +506,8 @@ mod tests {
497
506
use crate :: defaults:: deep_merge_dictionaries;
498
507
499
508
use super :: { replace_ellipsis_array, NS_GLOBAL_DOMAIN } ;
500
- // use serial_test::serial;
501
509
502
510
#[ test]
503
- // #[serial(home_dir)] // Test relies on or changes the $HOME env var.
504
511
fn plist_path_tests ( ) -> TestResult {
505
512
let home_dir = dirs:: home_dir ( ) . expect ( "Expected to be able to calculate the user's home directory." ) ;
506
513
@@ -585,7 +592,7 @@ mod tests {
585
592
}
586
593
587
594
#[ test]
588
- fn test_deep_merge_dictionaries ( ) -> TestResult {
595
+ fn test_deep_merge_dictionaries ( ) {
589
596
use plist:: { Dictionary , Value } ;
590
597
591
598
let old_value = Dictionary :: from_iter ( [
@@ -612,12 +619,10 @@ mod tests {
612
619
. into ( ) ;
613
620
614
621
assert_eq ! ( new_value, expected) ;
615
-
616
- Ok ( ( ) )
617
622
}
618
623
619
624
#[ test]
620
- fn test_replace_ellipsis_dict_nested ( ) -> TestResult {
625
+ fn test_replace_ellipsis_dict_nested ( ) {
621
626
use plist:: { Dictionary , Value } ;
622
627
623
628
let old_value = Dictionary :: from_iter ( [ (
@@ -660,12 +665,10 @@ mod tests {
660
665
. into ( ) ;
661
666
662
667
assert_eq ! ( new_value, expected) ;
663
-
664
- Ok ( ( ) )
665
668
}
666
669
667
670
#[ test]
668
- fn test_replace_ellipsis_dict_nested_bang ( ) -> TestResult {
671
+ fn test_replace_ellipsis_dict_nested_bang ( ) {
669
672
use plist:: { Dictionary , Value } ;
670
673
671
674
let old_value = Dictionary :: from_iter ( [ (
@@ -702,12 +705,10 @@ mod tests {
702
705
. into ( ) ;
703
706
704
707
assert_eq ! ( new_value, expected) ;
705
-
706
- Ok ( ( ) )
707
708
}
708
709
709
710
#[ test]
710
- fn test_replace_ellipsis_array ( ) -> TestResult {
711
+ fn test_replace_ellipsis_array ( ) {
711
712
let old_value = vec ! [
712
713
10 . into( ) , // !
713
714
20 . into( ) , // !
@@ -736,7 +737,7 @@ mod tests {
736
737
50 . into( ) ,
737
738
]
738
739
. into ( ) ;
740
+
739
741
assert_eq ! ( new_value, expected) ;
740
- Ok ( ( ) )
741
742
}
742
743
}
0 commit comments