Skip to content

Commit 156102a

Browse files
committed
feat: Added verify_file_layout() to CargoPathExt
1 parent b2c0aea commit 156102a

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

crates/cargo-test-support/src/compare.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ fn add_regex_redactions(subs: &mut snapbox::Redactions) {
229229
.unwrap();
230230
subs.insert("[HASH]", regex!(r"/[a-z0-9\-_]+-(?<redacted>[0-9a-f]{16})"))
231231
.unwrap();
232+
// Match multi-part hashes like 06/b451d0d6f88b1d used in directory paths
233+
subs.insert("[HASH]", regex!(r"/(?<redacted>[a-f0-9]{2}\/[0-9a-f]{14})"))
234+
.unwrap();
235+
subs.insert("[HASH]", regex!(r"[a-z0-9]+-(?<redacted>[a-f0-9]{16})"))
236+
.unwrap();
232237
subs.insert(
233238
"[AVG_ELAPSED]",
234239
regex!(r"(?<redacted>[0-9]+(\.[0-9]+)?) ns/iter"),

crates/cargo-test-support/src/paths.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::sync::Mutex;
1212
use std::sync::OnceLock;
1313
use std::sync::atomic::{AtomicUsize, Ordering};
1414

15+
use crate::compare;
16+
1517
static CARGO_INTEGRATION_TEST_DIR: &str = "cit";
1618

1719
static GLOBAL_ROOT: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();
@@ -152,6 +154,8 @@ pub trait CargoPathExt {
152154
fn move_in_time<F>(&self, travel_amount: F)
153155
where
154156
F: Fn(i64, u32) -> (i64, u32);
157+
158+
fn verify_file_layout(&self, expected: impl snapbox::IntoData);
155159
}
156160

157161
impl CargoPathExt for Path {
@@ -236,6 +240,18 @@ impl CargoPathExt for Path {
236240
});
237241
}
238242
}
243+
244+
#[track_caller]
245+
fn verify_file_layout(&self, expected: impl snapbox::IntoData) {
246+
let layout = generate_tree(&self);
247+
248+
let name = format!("verify_file_layout {}", self.display());
249+
if let Err(err) =
250+
compare::assert_ui().try_eq(Some(&name), layout.into(), expected.into_data())
251+
{
252+
panic!("{err}");
253+
}
254+
}
239255
}
240256

241257
impl CargoPathExt for PathBuf {
@@ -260,6 +276,11 @@ impl CargoPathExt for PathBuf {
260276
{
261277
self.as_path().move_in_time(travel_amount)
262278
}
279+
280+
#[track_caller]
281+
fn verify_file_layout(&self, expected: impl snapbox::IntoData) {
282+
self.as_path().verify_file_layout(expected);
283+
}
263284
}
264285

265286
fn do_op<F>(path: &Path, desc: &str, mut f: F)
@@ -414,3 +435,46 @@ pub fn windows_reserved_names_are_allowed() -> bool {
414435
true
415436
}
416437
}
438+
439+
pub fn generate_tree(path: &Path) -> String {
440+
let mut output = format!("{}\n", path.display());
441+
generate_tree_inner(path, &[], true, &mut output);
442+
return output;
443+
}
444+
445+
pub fn generate_tree_inner(path: &Path, prefix_state: &[bool], last: bool, output: &mut String) {
446+
let file_name = path
447+
.file_name()
448+
.map(|s| s.to_string_lossy())
449+
.unwrap_or_else(|| path.to_string_lossy());
450+
451+
if !prefix_state.is_empty() {
452+
// Build indentation based on ancestor "lastness"
453+
let mut indent = String::new();
454+
for &has_more_siblings in &prefix_state[..prefix_state.len() - 1] {
455+
indent.push_str(if has_more_siblings { "│ " } else { " " });
456+
}
457+
let connector = if last { "└── " } else { "├── " };
458+
output.push_str(&format!("{indent}{connector}{file_name}\n"));
459+
}
460+
461+
if path.is_dir() {
462+
let mut entries: Vec<_> = walkdir::WalkDir::new(path)
463+
.max_depth(1)
464+
.into_iter()
465+
.filter_map(Result::ok)
466+
.filter(|e| e.path() != path) // skip the dir itself
467+
.collect();
468+
469+
entries.sort_by_key(|e| e.file_name().to_os_string());
470+
471+
let count = entries.len();
472+
for (i, entry) in entries.into_iter().enumerate() {
473+
let is_last = i == count - 1;
474+
// push info about *this* level for children
475+
let mut new_prefix_state = prefix_state.to_vec();
476+
new_prefix_state.push(!is_last);
477+
generate_tree_inner(entry.path(), &new_prefix_state, is_last, output);
478+
}
479+
}
480+
}

0 commit comments

Comments
 (0)