1
1
use log:: LevelFilter ;
2
2
use serde:: { Deserialize , Serialize } ;
3
+ use serde_json:: Value ;
3
4
use std:: error:: Error ;
4
5
use std:: str:: FromStr ;
5
6
@@ -19,6 +20,81 @@ impl UserConfig {
19
20
Ok ( root)
20
21
}
21
22
}
23
+
24
+ pub fn save ( root : Root ) -> Result < ( ) , Box < dyn Error > > {
25
+ let config = AppConfig :: load ( ) ;
26
+ save_json ( & root, & config. config_file_path ( ) ) ?;
27
+ Ok ( ( ) )
28
+ }
29
+
30
+ pub fn write_config_value ( path : & str , value : & str ) -> Result < ( ) , Box < dyn Error > > {
31
+ let mut root: Value = serde_json:: to_value ( Self :: load ( ) ?) ?;
32
+ let ( current, last_part) = Self :: traverse_path ( & mut root, path) ?;
33
+
34
+ let parsed_value =
35
+ if value. eq_ignore_ascii_case ( "true" ) || value. eq_ignore_ascii_case ( "false" ) {
36
+ Value :: Bool ( value. parse :: < bool > ( ) ?)
37
+ } else if let Ok ( int_value) = value. parse :: < i64 > ( ) {
38
+ Value :: Number ( int_value. into ( ) )
39
+ } else {
40
+ Value :: String ( value. to_string ( ) )
41
+ } ;
42
+
43
+ match current {
44
+ Value :: Object ( map) => {
45
+ if map. contains_key ( & last_part) {
46
+ map. insert ( last_part, parsed_value) ;
47
+ } else {
48
+ return Err ( format ! ( "Invalid configuration key: {}" , path) . into ( ) ) ;
49
+ }
50
+ }
51
+ _ => return Err ( "Invalid configuration path" . into ( ) ) ,
52
+ }
53
+
54
+ let updated_root: Root = serde_json:: from_value ( root) ?;
55
+ Self :: save ( updated_root) ?;
56
+
57
+ Ok ( ( ) )
58
+ }
59
+
60
+ pub fn read_config_value ( path : & str ) -> Result < ( ) , Box < dyn Error > > {
61
+ let mut root: Value = serde_json:: to_value ( Self :: load ( ) ?) ?;
62
+ let ( current, last_part) = Self :: traverse_path ( & mut root, path) ?;
63
+
64
+ match current. get ( & last_part) {
65
+ Some ( value) => {
66
+ if value. is_object ( ) {
67
+ println ! ( "{}" , serde_json:: to_string_pretty( & value) ?) ;
68
+ } else {
69
+ println ! ( "{}" , value) ;
70
+ }
71
+ }
72
+ None => return Err ( format ! ( "Invalid configuration key: {}" , path) . into ( ) ) ,
73
+ }
74
+
75
+ Ok ( ( ) )
76
+ }
77
+
78
+ fn traverse_path < ' a > (
79
+ root : & ' a mut Value ,
80
+ path : & str ,
81
+ ) -> Result < ( & ' a mut Value , String ) , Box < dyn Error > > {
82
+ let parts: Vec < & str > = path. split ( '.' ) . collect ( ) ;
83
+ if parts. is_empty ( ) {
84
+ return Err ( "Invalid configuration path" . into ( ) ) ;
85
+ }
86
+
87
+ let mut current = root;
88
+ for part in parts. iter ( ) . take ( parts. len ( ) - 1 ) {
89
+ current = current. get_mut ( * part) . ok_or ( "Invalid configuration path" ) ?;
90
+ }
91
+
92
+ let last_part = parts
93
+ . last ( )
94
+ . ok_or ( "Invalid configuration path" ) ?
95
+ . to_string ( ) ;
96
+ Ok ( ( current, last_part) )
97
+ }
22
98
}
23
99
24
100
#[ derive( Serialize , Deserialize , Debug , Default ) ]
@@ -50,6 +126,18 @@ impl Engine {
50
126
}
51
127
}
52
128
129
+ impl FromStr for Engine {
130
+ type Err = ( ) ;
131
+
132
+ fn from_str ( input : & str ) -> Result < Engine , Self :: Err > {
133
+ match input. to_lowercase ( ) . as_str ( ) {
134
+ "docker" => Ok ( Engine :: Docker ) ,
135
+ "podman" => Ok ( Engine :: Podman ) ,
136
+ _ => Err ( ( ) ) ,
137
+ }
138
+ }
139
+ }
140
+
53
141
#[ derive( Serialize , Deserialize , Debug ) ]
54
142
pub struct Logs {
55
143
#[ serde( default ) ]
0 commit comments