@@ -5,6 +5,23 @@ use crate::error::{Error, Result};
55
66const OPENVIKING_CLI_CONFIG_ENV : & str = "OPENVIKING_CLI_CONFIG_FILE" ;
77
8+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
9+ pub struct UploadConfig {
10+ pub ignore_dirs : Option < String > ,
11+ pub include : Option < String > ,
12+ pub exclude : Option < String > ,
13+ }
14+
15+ impl Default for UploadConfig {
16+ fn default ( ) -> Self {
17+ Self {
18+ ignore_dirs : None ,
19+ include : None ,
20+ exclude : None ,
21+ }
22+ }
23+ }
24+
825#[ derive( Debug , Clone , Serialize , Deserialize ) ]
926pub struct Config {
1027 #[ serde( default = "default_url" ) ]
@@ -19,6 +36,8 @@ pub struct Config {
1936 pub output : String ,
2037 #[ serde( default = "default_echo_command" ) ]
2138 pub echo_command : bool ,
39+ #[ serde( default ) ]
40+ pub upload : UploadConfig ,
2241}
2342
2443fn default_url ( ) -> String {
@@ -48,10 +67,35 @@ impl Default for Config {
4867 timeout : 60.0 ,
4968 output : "table" . to_string ( ) ,
5069 echo_command : true ,
70+ upload : UploadConfig :: default ( ) ,
5171 }
5272 }
5373}
5474
75+ fn normalize_csv_option ( value : Option < String > ) -> Vec < String > {
76+ value
77+ . unwrap_or_default ( )
78+ . split ( ',' )
79+ . map ( str:: trim)
80+ . filter ( |token| !token. is_empty ( ) )
81+ . map ( ToString :: to_string)
82+ . collect ( )
83+ }
84+
85+ pub fn merge_csv_options (
86+ config_value : Option < String > ,
87+ cli_value : Option < String > ,
88+ ) -> Option < String > {
89+ let mut merged = normalize_csv_option ( config_value) ;
90+ merged. extend ( normalize_csv_option ( cli_value) ) ;
91+
92+ if merged. is_empty ( ) {
93+ None
94+ } else {
95+ Some ( merged. join ( "," ) )
96+ }
97+ }
98+
5599impl Config {
56100 /// Load config from default location or create default
57101 pub fn load ( ) -> Result < Self > {
@@ -115,7 +159,7 @@ pub fn get_or_create_machine_id() -> Result<String> {
115159
116160#[ cfg( test) ]
117161mod tests {
118- use super :: Config ;
162+ use super :: { Config , merge_csv_options } ;
119163
120164 #[ test]
121165 fn config_deserializes_account_and_user_fields ( ) {
@@ -133,5 +177,77 @@ mod tests {
133177 assert_eq ! ( config. account. as_deref( ) , Some ( "acme" ) ) ;
134178 assert_eq ! ( config. user. as_deref( ) , Some ( "alice" ) ) ;
135179 assert_eq ! ( config. agent_id. as_deref( ) , Some ( "assistant-1" ) ) ;
180+ assert ! ( config. upload. ignore_dirs. is_none( ) ) ;
181+ assert ! ( config. upload. include. is_none( ) ) ;
182+ assert ! ( config. upload. exclude. is_none( ) ) ;
183+ }
184+
185+ #[ test]
186+ fn config_deserializes_upload_fields ( ) {
187+ let config: Config = serde_json:: from_str (
188+ r#"{
189+ "url": "http://localhost:1933",
190+ "upload": {
191+ "ignore_dirs": "node_modules,dist",
192+ "include": "*.md,*.pdf",
193+ "exclude": "*.tmp,*.log"
194+ }
195+ }"# ,
196+ )
197+ . expect ( "config should deserialize" ) ;
198+
199+ assert_eq ! (
200+ config. upload. ignore_dirs. as_deref( ) ,
201+ Some ( "node_modules,dist" )
202+ ) ;
203+ assert_eq ! ( config. upload. include. as_deref( ) , Some ( "*.md,*.pdf" ) ) ;
204+ assert_eq ! ( config. upload. exclude. as_deref( ) , Some ( "*.tmp,*.log" ) ) ;
205+ }
206+
207+ #[ test]
208+ fn merge_csv_options_config_only ( ) {
209+ assert_eq ! (
210+ merge_csv_options( Some ( "node_modules,dist" . to_string( ) ) , None ) ,
211+ Some ( "node_modules,dist" . to_string( ) )
212+ ) ;
213+ }
214+
215+ #[ test]
216+ fn merge_csv_options_cli_only ( ) {
217+ assert_eq ! (
218+ merge_csv_options( None , Some ( "*.md,*.pdf" . to_string( ) ) ) ,
219+ Some ( "*.md,*.pdf" . to_string( ) )
220+ ) ;
221+ }
222+
223+ #[ test]
224+ fn merge_csv_options_additive_merge ( ) {
225+ assert_eq ! (
226+ merge_csv_options(
227+ Some ( "node_modules,dist" . to_string( ) ) ,
228+ Some ( "build,out" . to_string( ) )
229+ ) ,
230+ Some ( "node_modules,dist,build,out" . to_string( ) )
231+ ) ;
232+ }
233+
234+ #[ test]
235+ fn merge_csv_options_trims_and_drops_empty_tokens ( ) {
236+ assert_eq ! (
237+ merge_csv_options(
238+ Some ( " node_modules , , dist ," . to_string( ) ) ,
239+ Some ( " ,*.tmp, *.log ," . to_string( ) )
240+ ) ,
241+ Some ( "node_modules,dist,*.tmp,*.log" . to_string( ) )
242+ ) ;
243+ }
244+
245+ #[ test]
246+ fn merge_csv_options_returns_none_when_empty ( ) {
247+ assert_eq ! (
248+ merge_csv_options( Some ( " , , " . to_string( ) ) , Some ( "" . to_string( ) ) ) ,
249+ None
250+ ) ;
251+ assert_eq ! ( merge_csv_options( None , None ) , None ) ;
136252 }
137253}
0 commit comments