Skip to content

Commit 4a10dde

Browse files
committed
fix(robot-repo-automaton): make ContentMatch detection compile
`detect_content_match` read file contents with `std::fs::read` (→ `Vec<u8>`) and passed `&content` to a string `regex::Regex::is_match`, which wants `&str`. The crate therefore never compiled and the whole `DetectionMethod::ContentMatch` detection path was dead code. Switch to `std::fs::read_to_string`. This fixes the type error and also implements the "skip non-UTF8" intent already stated in the comment just above (`read_to_string` returns `Err` on non-UTF8 bytes, which the `if let Ok` then skips), matching the sibling content scan in `hypatia.rs`. Add a regression test for the previously-uncompilable path: a positive regex match, a non-match, and a non-UTF8 file that must be skipped without panicking. `cargo build` is clean and all 101 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RozeeLxpJsd3WWFngaZWz3
1 parent f39d3d5 commit 4a10dde

1 file changed

Lines changed: 58 additions & 1 deletion

File tree

robot-repo-automaton/src/detector.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,9 @@ impl Detector {
297297
}
298298
}
299299

300-
if let Ok(content) = std::fs::read(file_path) {
300+
// read_to_string returns Err on non-UTF8 bytes, so the
301+
// `if let Ok` here also implements the "skip non-UTF8" intent.
302+
if let Ok(content) = std::fs::read_to_string(file_path) {
301303
if re.is_match(&content) {
302304
affected.push(file_path.clone());
303305
}
@@ -377,6 +379,8 @@ impl Detector {
377379
#[cfg(test)]
378380
mod tests {
379381
use super::*;
382+
use crate::catalog::{Detection, Fix, FixAction};
383+
use std::collections::HashMap;
380384
use tempfile::TempDir;
381385

382386
#[test]
@@ -404,4 +408,57 @@ mod tests {
404408
assert!(detector.file_exists(".github/workflows/ci.yml"));
405409
assert!(!detector.file_exists(".github/workflows/nonexistent.yml"));
406410
}
411+
412+
fn content_match_error(condition: &str, files: Vec<String>) -> ErrorType {
413+
ErrorType {
414+
id: "TEST-CONTENT".to_string(),
415+
name: "content-match regression".to_string(),
416+
severity: Severity::Medium,
417+
category: "test".to_string(),
418+
description: "regression coverage for detect_content_match".to_string(),
419+
detection: Detection {
420+
method: DetectionMethod::ContentMatch,
421+
files,
422+
condition: Some(condition.to_string()),
423+
extension_map: HashMap::new(),
424+
},
425+
affected_repos: vec![],
426+
fix: Fix {
427+
action: FixAction::Modify,
428+
target: String::new(),
429+
reason: None,
430+
modification: None,
431+
fallback: None,
432+
},
433+
commit_message: "test".to_string(),
434+
}
435+
}
436+
437+
#[test]
438+
fn test_content_match_detects_and_skips_non_utf8() {
439+
let temp = TempDir::new().unwrap();
440+
std::fs::write(temp.path().join("hit.txt"), "contains believe_me here").unwrap();
441+
std::fs::write(temp.path().join("miss.txt"), "nothing to see").unwrap();
442+
// Invalid UTF-8: detect_content_match must skip this (not panic) — the
443+
// bug fix relies on std::fs::read_to_string returning Err here.
444+
std::fs::write(temp.path().join("blob.bin"), [0xff, 0xfe, 0x62, 0x6d]).unwrap();
445+
446+
let detector = Detector::new(temp.path().to_path_buf()).unwrap();
447+
448+
// Positive: regex hits hit.txt; the non-UTF8 blob is skipped cleanly.
449+
assert!(
450+
detector
451+
.detect(&content_match_error("believe_me", vec!["*".to_string()]))
452+
.is_some(),
453+
"should detect the file whose contents match the regex"
454+
);
455+
456+
// Negative: a token present in no valid-UTF8 file yields no issue.
457+
assert!(
458+
detector
459+
.detect(&content_match_error("no_such_token", vec!["*".to_string()]))
460+
.is_none(),
461+
"should report nothing when no file matches"
462+
);
463+
}
407464
}

0 commit comments

Comments
 (0)