pub fn references_path(source: &str, changed_path: &str) -> Option<String> {
let trimmed = changed_path.trim_start_matches("./");
if trimmed.is_empty() {
return None;
}
if source.contains(trimmed) {
return Some(trimmed.to_string());
}
if let Some(base) = basename(trimmed) {
if base.len() >= 5 && source.contains(base) {
return Some(base.to_string());
}
}
None
}
fn basename(p: &str) -> Option<&str> {
p.rsplit('/').next().filter(|s| !s.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detects_include_directive_reference() {
let source = r#"
name: x
steps:
- include: ./shared/auth.tarn.yaml
"#;
assert_eq!(
references_path(source, "shared/auth.tarn.yaml"),
Some("shared/auth.tarn.yaml".into())
);
}
#[test]
fn detects_upload_path_reference() {
let source = r#"
name: upload
steps:
- name: put
request:
method: POST
url: http://localhost/upload
multipart:
files:
- name: photo
path: ./fixtures/avatar.jpeg
"#;
assert_eq!(
references_path(source, "fixtures/avatar.jpeg"),
Some("fixtures/avatar.jpeg".into())
);
}
#[test]
fn no_reference_returns_none() {
let source = "name: none\nsteps: []\n";
assert_eq!(references_path(source, "shared/auth.tarn.yaml"), None);
}
#[test]
fn short_basename_alone_does_not_match() {
let source = "name: a\nsteps: []\n";
assert_eq!(references_path(source, "src/a.ts"), None);
}
#[test]
fn long_basename_alone_can_match() {
let source = "# references avatar.jpeg inline\nname: x\nsteps: []\n";
assert_eq!(
references_path(source, "fixtures/avatar.jpeg"),
Some("avatar.jpeg".into())
);
}
}