feat: add utils subcommand for renaming genome labels
Introduces a `utils` CLI subcommand to enable in-place genome label renaming without full reindexing. Adds strict label validation to reject empty strings, filesystem separators, and control characters, ensuring safe CSV serialization. Updates index metadata, renames corresponding spectrum JSON files, and registers the command in the main dispatch logic. CLI reference documentation is also updated.
This commit is contained in:
@@ -12,5 +12,5 @@ pub use error::{OKIError, OKIResult};
|
||||
pub use distance::{DistanceMetric, DistanceOutput};
|
||||
pub use index::KmerIndex;
|
||||
pub use merge::MergeMode;
|
||||
pub use meta::{GenomeInfo, IndexConfig, IndexMeta, META_FILENAME};
|
||||
pub use meta::{validate_label, GenomeInfo, IndexConfig, IndexMeta, META_FILENAME};
|
||||
pub use state::{IndexState, SENTINEL_COUNTED, SENTINEL_INDEXED, SENTINEL_SCATTERED};
|
||||
|
||||
@@ -70,3 +70,26 @@ impl IndexMeta {
|
||||
self.genomes.iter().map(|g| g.label.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate a user-supplied genome label.
|
||||
///
|
||||
/// Forbidden: `/` (filesystem separator), `=` (--new-label parser separator),
|
||||
/// `\0` (null byte), `\n`, `\r`, `\t` (break CSV output).
|
||||
/// Empty labels are also rejected.
|
||||
pub fn validate_label(label: &str) -> Result<(), String> {
|
||||
if label.is_empty() {
|
||||
return Err("genome label must not be empty".into());
|
||||
}
|
||||
const FORBIDDEN: &[char] = &['/', '=', '\0', '\n', '\r', '\t'];
|
||||
if let Some(c) = label.chars().find(|c| FORBIDDEN.contains(c)) {
|
||||
let display = match c {
|
||||
'\0' => "\\0 (null)".to_string(),
|
||||
'\n' => "\\n (newline)".to_string(),
|
||||
'\r' => "\\r (carriage return)".to_string(),
|
||||
'\t' => "\\t (tab)".to_string(),
|
||||
c => format!("'{c}'"),
|
||||
};
|
||||
return Err(format!("genome label contains forbidden character {display}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user