@@ -130,6 +130,8 @@ impl SetupIntegrationHarness {
130130 . current_dir ( & self . repo_root )
131131 . env ( "XDG_STATE_HOME" , & self . state_home )
132132 . env ( "HOME" , & self . home_dir )
133+ . env ( "LOCALAPPDATA" , & self . state_home )
134+ . env ( "APPDATA" , & self . state_home )
133135 . env ( "GIT_CONFIG_GLOBAL" , null_device_path ( ) )
134136 . env ( "GIT_CONFIG_NOSYSTEM" , "1" ) ;
135137 command
@@ -289,10 +291,11 @@ fn setup_backup_suffix_collision() -> TestResult<()> {
289291
290292 let expected_backup = canonical_repo_root. join ( ".opencode.backup.2" ) ;
291293 assert ! (
292- second. stdout. contains( & format!(
293- "backup: existing target moved to '{}'" ,
294- expected_backup. display( )
295- ) ) ,
294+ candidate_path_strings( & expected_backup)
295+ . iter( )
296+ . any( |candidate| second
297+ . stdout
298+ . contains( & format!( "backup: existing target moved to '{candidate}'" ) ) ) ,
296299 "output should report backup to .backup.2 due to collision\n stdout:\n {}" ,
297300 second. stdout
298301 ) ;
@@ -361,20 +364,14 @@ fn setup_hooks_repo_relative_path() -> TestResult<()> {
361364 ) ;
362365
363366 assert ! (
364- result. stdout. contains( & format!(
365- "Repository root: '{}'" ,
366- canonical_repo_root. display( )
367- ) ) ,
367+ stdout_contains_path_line( & result. stdout, "Repository root" , & canonical_repo_root) ,
368368 "output should contain canonical repository root '{}'\n stdout:\n {}" ,
369369 canonical_repo_root. display( ) ,
370370 result. stdout
371371 ) ;
372372
373373 assert ! (
374- result. stdout. contains( & format!(
375- "Hooks directory: '{}'" ,
376- expected_hooks_dir. display( )
377- ) ) ,
374+ stdout_contains_path_line( & result. stdout, "Hooks directory" , & expected_hooks_dir) ,
378375 "output should contain hooks directory '{}'\n stdout:\n {}" ,
379376 expected_hooks_dir. display( ) ,
380377 result. stdout
@@ -413,20 +410,14 @@ fn setup_hooks_repo_absolute_path() -> TestResult<()> {
413410 ) ;
414411
415412 assert ! (
416- result. stdout. contains( & format!(
417- "Repository root: '{}'" ,
418- canonical_repo_root. display( )
419- ) ) ,
413+ stdout_contains_path_line( & result. stdout, "Repository root" , & canonical_repo_root) ,
420414 "output should contain canonical repository root '{}'\n stdout:\n {}" ,
421415 canonical_repo_root. display( ) ,
422416 result. stdout
423417 ) ;
424418
425419 assert ! (
426- result. stdout. contains( & format!(
427- "Hooks directory: '{}'" ,
428- expected_hooks_dir. display( )
429- ) ) ,
420+ stdout_contains_path_line( & result. stdout, "Hooks directory" , & expected_hooks_dir) ,
430421 "output should contain hooks directory '{}'\n stdout:\n {}" ,
431422 expected_hooks_dir. display( ) ,
432423 result. stdout
@@ -920,6 +911,7 @@ mod pty_interactive {
920911 Ok ( ( ) )
921912 }
922913
914+ #[ cfg( not( target_os = "windows" ) ) ]
923915 #[ test]
924916 fn setup_interactive_nontty_fail ( ) -> TestResult < ( ) > {
925917 let harness = SetupIntegrationHarness :: new ( "sce-setup-nontty" ) ?;
@@ -1292,10 +1284,12 @@ fn assert_setup_hooks_install_and_rerun(
12921284 first. stderr
12931285 ) ;
12941286 assert ! ( first. stdout. contains( "Hook setup completed successfully." ) ) ;
1295- assert ! ( first. stdout. contains( & format!(
1296- "Hooks directory: '{}'" ,
1297- expected_hooks_directory. display( )
1298- ) ) ) ;
1287+ assert ! (
1288+ stdout_contains_path_line( & first. stdout, "Hooks directory" , expected_hooks_directory) ,
1289+ "first setup run should include hooks directory '{}':\n {}" ,
1290+ expected_hooks_directory. display( ) ,
1291+ first. stdout
1292+ ) ;
12991293
13001294 for hook in REQUIRED_HOOK_NAMES {
13011295 let expected_hook_path = expected_hooks_directory. join ( hook) ;
@@ -1326,10 +1320,12 @@ fn assert_setup_hooks_install_and_rerun(
13261320 second. stderr
13271321 ) ;
13281322 assert ! ( second. stdout. contains( "Hook setup completed successfully." ) ) ;
1329- assert ! ( second. stdout. contains( & format!(
1330- "Hooks directory: '{}'" ,
1331- expected_hooks_directory. display( )
1332- ) ) ) ;
1323+ assert ! (
1324+ stdout_contains_path_line( & second. stdout, "Hooks directory" , expected_hooks_directory) ,
1325+ "second setup run should include hooks directory '{}':\n {}" ,
1326+ expected_hooks_directory. display( ) ,
1327+ second. stdout
1328+ ) ;
13331329
13341330 for hook in REQUIRED_HOOK_NAMES {
13351331 let expected_hook_path = expected_hooks_directory. join ( hook) ;
@@ -1448,9 +1444,7 @@ fn expected_agent_trace_local_db_path(harness: &SetupIntegrationHarness) -> Path
14481444 #[ cfg( target_os = "windows" ) ]
14491445 {
14501446 harness
1451- . home_dir
1452- . join ( "AppData" )
1453- . join ( "Local" )
1447+ . state_home
14541448 . join ( "sce" )
14551449 . join ( "agent-trace" )
14561450 . join ( "local.db" )
@@ -1477,6 +1471,32 @@ fn expected_agent_trace_local_db_path(harness: &SetupIntegrationHarness) -> Path
14771471 }
14781472}
14791473
1474+ fn stdout_contains_path_line ( stdout : & str , label : & str , path : & Path ) -> bool {
1475+ candidate_path_strings ( path) . into_iter ( ) . any ( |candidate| {
1476+ stdout. contains ( & format ! ( "{label}: '{candidate}'" ) )
1477+ || stdout. contains ( & format ! ( "{label}: \" {candidate}\" " ) )
1478+ } )
1479+ }
1480+
1481+ fn candidate_path_strings ( path : & Path ) -> Vec < String > {
1482+ let raw = path. display ( ) . to_string ( ) ;
1483+ let slash = raw. replace ( '\\' , "/" ) ;
1484+ let raw_trimmed = trim_windows_verbatim_prefix ( & raw ) . to_string ( ) ;
1485+ let slash_trimmed = trim_windows_verbatim_prefix ( & slash) . to_string ( ) ;
1486+
1487+ let mut candidates = vec ! [ raw, slash, raw_trimmed, slash_trimmed] ;
1488+ candidates. sort ( ) ;
1489+ candidates. dedup ( ) ;
1490+ candidates
1491+ }
1492+
1493+ fn trim_windows_verbatim_prefix ( value : & str ) -> & str {
1494+ value
1495+ . strip_prefix ( r"\\?\" )
1496+ . or_else ( || value. strip_prefix ( "//?/" ) )
1497+ . unwrap_or ( value)
1498+ }
1499+
14801500fn null_device_path ( ) -> & ' static str {
14811501 #[ cfg( windows) ]
14821502 {
0 commit comments