Skip to content

Commit b1bae03

Browse files
committed
fix: Resolve file list paths relative to lists
1 parent 160b31f commit b1bae03

2 files changed

Lines changed: 56 additions & 5 deletions

File tree

src/io.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ use crate::format::{ENTRY_SIZE, Entry};
77

88
pub fn expand_input_paths(input_paths: &[PathBuf]) -> Result<Vec<PathBuf>> {
99
let mut expanded_paths = Vec::new();
10+
let mut rejected_paths = Vec::new();
1011

1112
for path in input_paths {
1213
if path.is_dir() {
14+
let before = expanded_paths.len();
1315
for entry in std::fs::read_dir(path)? {
1416
let entry = entry?;
1517
let file_path = entry.path();
@@ -18,25 +20,52 @@ pub fn expand_input_paths(input_paths: &[PathBuf]) -> Result<Vec<PathBuf>> {
1820
expanded_paths.push(file_path);
1921
}
2022
}
23+
if expanded_paths.len() == before {
24+
rejected_paths.push(format!(
25+
"{} (directory contains no sequence files)",
26+
path.display()
27+
));
28+
}
2129
} else if path.is_file() {
2230
if is_sequence_file(path) {
2331
expanded_paths.push(path.clone());
2432
} else {
2533
let content = std::fs::read_to_string(path)?;
34+
let base_dir = path.parent().unwrap_or_else(|| Path::new("."));
2635
for line in content.lines() {
27-
let file_path = PathBuf::from(line.trim());
36+
let line = line.trim();
37+
if line.is_empty() || line.starts_with('#') {
38+
continue;
39+
}
40+
let listed_path = PathBuf::from(line);
41+
let file_path = if listed_path.is_relative() {
42+
base_dir.join(listed_path)
43+
} else {
44+
listed_path
45+
};
2846
if file_path.exists() && is_sequence_file(&file_path) {
29-
expanded_paths.push(file_path);
47+
expanded_paths.push(file_path.canonicalize().unwrap_or(file_path));
48+
} else {
49+
rejected_paths.push(format!(
50+
"{} (listed in {}, missing or unsupported extension)",
51+
file_path.display(),
52+
path.display()
53+
));
3054
}
3155
}
3256
}
57+
} else {
58+
rejected_paths.push(format!("{} (does not exist)", path.display()));
3359
}
3460
}
3561

3662
if expanded_paths.is_empty() {
37-
return Err(anyhow::anyhow!(
38-
"No valid sequence files found in input paths"
39-
));
63+
let mut message = "No valid sequence files found in input paths".to_string();
64+
if !rejected_paths.is_empty() {
65+
message.push_str(": ");
66+
message.push_str(&rejected_paths.join(", "));
67+
}
68+
return Err(anyhow::anyhow!(message));
4069
}
4170

4271
expanded_paths.sort();

tests/coverage_tests.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,28 @@ fn test_expand_input_paths_file_list_with_comments() -> Result<()> {
191191
Ok(())
192192
}
193193

194+
#[test]
195+
fn test_expand_input_paths_file_list_relative_to_list_file() -> Result<()> {
196+
let env = CoverageTestEnvironment::new()?;
197+
198+
let list_dir = env.temp_path().join("lists");
199+
let data_dir = env.temp_path().join("data");
200+
fs::create_dir_all(&list_dir)?;
201+
fs::create_dir_all(&data_dir)?;
202+
203+
let valid_file = data_dir.join("valid.fa");
204+
fs::write(&valid_file, ">seq\nACGT\n")?;
205+
206+
let file_list = list_dir.join("inputs.txt");
207+
fs::write(&file_list, "../data/valid.fa\n")?;
208+
209+
let result = expand_input_paths(&[file_list])?;
210+
211+
assert_eq!(result, vec![valid_file]);
212+
213+
Ok(())
214+
}
215+
194216
#[test]
195217
fn test_expand_input_paths_duplicate_files() -> Result<()> {
196218
let env = CoverageTestEnvironment::new()?;

0 commit comments

Comments
 (0)