1- use std:: path:: { Path , PathBuf } ;
1+ use std:: path:: Path ;
22use std:: process:: Command ;
33
4- /// Strip ANSI escape sequences from a string.
4+ pub struct Output {
5+ pub code : i32 ,
6+ pub stdout : String ,
7+ pub stderr : String ,
8+ }
9+
10+ impl Output {
11+ pub fn redacted_stderr ( & self , fixture : & Fixture ) -> String {
12+ redact ( & self . stderr , fixture)
13+ }
14+
15+ pub fn redacted_stdout ( & self , fixture : & Fixture ) -> String {
16+ redact ( & self . stdout , fixture)
17+ }
18+ }
19+
520fn strip_ansi ( s : & str ) -> String {
621 let mut out = String :: with_capacity ( s. len ( ) ) ;
722 let mut chars = s. chars ( ) ;
823 while let Some ( ch) = chars. next ( ) {
924 if ch == '\x1b' {
10- // skip until we hit a letter (the terminator of the escape sequence)
1125 for ch in chars. by_ref ( ) {
1226 if ch. is_ascii_alphabetic ( ) {
1327 break ;
@@ -20,38 +34,12 @@ fn strip_ansi(s: &str) -> String {
2034 out
2135}
2236
23- /// Result of running a bough command.
24- pub struct Output {
25- pub code : i32 ,
26- pub stdout : String ,
27- pub stderr : String ,
28- }
29-
30- impl Output {
31- /// Return stderr with the fixture's temp dir path replaced by `<TMP>`
32- /// and ANSI escape codes stripped.
33- pub fn redacted_stderr ( & self , fixture : & Fixture ) -> String {
34- redact ( & self . stderr , fixture)
35- }
36-
37- /// Return stdout with the fixture's temp dir path replaced by `<TMP>`
38- /// and ANSI escape codes stripped.
39- pub fn redacted_stdout ( & self , fixture : & Fixture ) -> String {
40- redact ( & self . stdout , fixture)
41- }
42- }
43-
4437fn redact ( s : & str , fixture : & Fixture ) -> String {
4538 let stripped = strip_ansi ( s) ;
46- let canonical = fixture
47- . path ( )
48- . canonicalize ( )
49- . unwrap_or_else ( |_| fixture. path ( ) . to_path_buf ( ) ) ;
50- let canonical_str = canonical. to_string_lossy ( ) ;
51- let tmp_base = canonical_str
52- . strip_prefix ( "\\ \\ ?\\ " )
53- . unwrap_or ( canonical_str. as_ref ( ) ) ;
54- let tmp = std:: borrow:: Cow :: Borrowed ( tmp_base) ;
39+ let fixture_path = fixture. path ( ) . to_string_lossy ( ) . into_owned ( ) ;
40+ // Generate variants to handle OS path separator differences in output
41+ let tmp_json = fixture_path. replace ( '\\' , "\\ \\ " ) ;
42+ let tmp_fwd = fixture_path. replace ( '\\' , "/" ) ;
5543 let mut result = String :: with_capacity ( stripped. len ( ) ) ;
5644 let mut in_file_block = false ;
5745 for line in stripped. lines ( ) {
@@ -61,20 +49,16 @@ fn redact(s: &str, fixture: &Fixture) -> String {
6149 continue ;
6250 }
6351 if in_file_block {
64- // The file block ends when we hit the next sibling source
65- // (lines starting with ├─ or └─ at the top level, not indented │)
6652 if !line. starts_with ( "│" ) {
6753 in_file_block = false ;
6854 } else {
6955 continue ;
7056 }
7157 }
72- let tmp_json_escaped: String = tmp. replace ( '\\' , "\\ \\ " ) ;
73- let tmp_fwd_slash: String = tmp. replace ( '\\' , "/" ) ;
7458 let redacted = line
75- . replace ( tmp_json_escaped . as_str ( ) , "<TMP>" )
76- . replace ( tmp_fwd_slash . as_str ( ) , "<TMP>" )
77- . replace ( tmp . as_ref ( ) , "<TMP>" ) ;
59+ . replace ( tmp_json . as_str ( ) , "<TMP>" )
60+ . replace ( tmp_fwd . as_str ( ) , "<TMP>" )
61+ . replace ( fixture_path . as_str ( ) , "<TMP>" ) ;
7862 result. push_str ( & redacted) ;
7963 result. push ( '\n' ) ;
8064 }
@@ -86,7 +70,7 @@ fn redact(s: &str, fixture: &Fixture) -> String {
8670
8771/// Pending file to be written when the fixture is built.
8872struct PendingFile {
89- path : PathBuf ,
73+ path : std :: path :: PathBuf ,
9074 content : String ,
9175}
9276
@@ -111,7 +95,7 @@ impl FixtureBuilder {
11195 Self { files : Vec :: new ( ) }
11296 }
11397
114- pub fn with_file ( mut self , path : impl Into < PathBuf > , content : impl Into < String > ) -> Self {
98+ pub fn with_file ( mut self , path : impl Into < std :: path :: PathBuf > , content : impl Into < String > ) -> Self {
11599 self . files . push ( PendingFile {
116100 path : path. into ( ) ,
117101 content : content. into ( ) ,
@@ -138,8 +122,6 @@ impl Fixture {
138122 FixtureBuilder :: new ( )
139123 }
140124
141- /// Run a bough command in this fixture's directory.
142- /// `args` is a string of space-separated arguments (e.g. "show config -f json").
143125 pub fn run ( & self , args : & str ) -> Output {
144126 let bough = env ! ( "BOUGH_BIN" ) ;
145127 let args: Vec < & str > = args. split_whitespace ( ) . collect ( ) ;
@@ -157,7 +139,6 @@ impl Fixture {
157139 }
158140 }
159141
160- /// Return the path to the fixture's temporary directory.
161142 pub fn path ( & self ) -> & Path {
162143 self . dir . path ( )
163144 }
0 commit comments