mod container;
pub(crate) use crate::detectors::manifests::build::{
analyze_makefile, makefile_capabilities, makefile_relations,
};
pub(crate) use crate::detectors::manifests::javascript::{
analyze_npmrc, analyze_package_json, npmrc_capabilities, npmrc_relations,
package_json_capabilities, package_json_expected_lockfiles, package_json_relations,
};
pub(crate) use crate::detectors::manifests::python::{
analyze_pip_conf, analyze_pyproject_toml, analyze_requirements_txt, pip_conf_capabilities,
pip_conf_relations, pyproject_expected_lockfiles, pyproject_toml_capabilities,
requirements_txt_capabilities,
};
pub(crate) use crate::detectors::manifests::rust_cargo::{
analyze_cargo_toml, cargo_toml_capabilities,
};
pub(crate) use container::{
analyze_docker_compose, analyze_dockerfile, docker_compose_capabilities,
docker_compose_relations, dockerfile_capabilities, dockerfile_relations,
};
use std::path::PathBuf;
pub(crate) fn sibling_has_file(sibling_files: &[PathBuf], name: &str) -> bool {
sibling_files.iter().any(|f| {
f.file_name()
.and_then(|n| n.to_str())
.is_some_and(|n| n.eq_ignore_ascii_case(name))
})
}
pub(crate) fn strip_inline_hash_comment(line: &str) -> &str {
line.split_once('#').map(|(code, _)| code).unwrap_or(line)
}
pub(crate) fn strip_inline_ini_comment(line: &str) -> &str {
let hash_idx = line.find('#');
let semi_idx = line.find(';');
match (hash_idx, semi_idx) {
(Some(h), Some(s)) => &line[..h.min(s)],
(Some(h), None) => &line[..h],
(None, Some(s)) => &line[..s],
(None, None) => line,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strip_inline_hash_comment_preserves_lines_without_hash() {
assert_eq!(
strip_inline_hash_comment("curl https://x"),
"curl https://x"
);
assert_eq!(strip_inline_hash_comment(""), "");
}
#[test]
fn strip_inline_hash_comment_drops_inline_trailing_comment() {
assert_eq!(
strip_inline_hash_comment("\t@echo done # was: curl https://old"),
"\t@echo done ",
);
assert_eq!(
strip_inline_hash_comment("RUN echo ok # curl example.com"),
"RUN echo ok ",
);
}
#[test]
fn strip_inline_hash_comment_collapses_pure_comment_to_empty() {
assert_eq!(strip_inline_hash_comment("# curl evil.example"), "");
assert_eq!(strip_inline_hash_comment("#bash install.sh"), "");
}
#[test]
fn strip_inline_ini_comment_preserves_lines_without_marker() {
assert_eq!(
strip_inline_ini_comment("registry=https://registry.npmjs.org"),
"registry=https://registry.npmjs.org"
);
}
#[test]
fn strip_inline_ini_comment_treats_semicolon_as_comment_marker() {
assert_eq!(strip_inline_ini_comment("; _authtoken=PLACEHOLDER"), "");
assert_eq!(
strip_inline_ini_comment("_authtoken=secret ; rotate me"),
"_authtoken=secret "
);
}
#[test]
fn strip_inline_ini_comment_uses_earliest_marker() {
assert_eq!(
strip_inline_ini_comment("foo=bar ; note # rotate"),
"foo=bar "
);
assert_eq!(
strip_inline_ini_comment("foo=bar # note ; rotate"),
"foo=bar "
);
}
}