use super::*;
use crate::graph::MagellanIntegration;
pub fn apply_with_rollback<F>(
file_path: &Path,
modify: F,
transaction: &mut RenameTransaction,
) -> Result<()>
where
F: FnOnce() -> Result<Vec<u8>>,
{
let new_content = modify()?;
fs::write(file_path, new_content).map_err(|e| SpliceError::Io {
path: file_path.to_path_buf(),
source: e,
})?;
transaction.track_modified(file_path.to_path_buf());
Ok(())
}
pub fn replace_at_span(content: &[u8], span: &ReferenceFact, new_name: &[u8]) -> Result<Vec<u8>> {
if span.byte_start >= content.len() || span.byte_end > content.len() {
return Err(SpliceError::InvalidSpan {
file: span.file_path.clone(),
start: span.byte_start,
end: span.byte_end,
file_size: content.len(),
});
}
MagellanIntegration::validate_utf8_span(
content,
span.byte_start,
span.byte_end,
&span.file_path,
)?;
let mut result = Vec::with_capacity(content.len() + new_name.len());
result.extend_from_slice(&content[..span.byte_start]);
result.extend_from_slice(new_name);
result.extend_from_slice(&content[span.byte_end..]);
Ok(result)
}
pub fn apply_replacements_in_file(
file_path: &Path,
_old_name: &str,
new_name: &str,
references: &[ReferenceFact],
) -> Result<usize> {
let content = fs::read(file_path).map_err(|e| SpliceError::Io {
path: file_path.to_path_buf(),
source: e,
})?;
let new_name_bytes = new_name.as_bytes();
let mut current_content = content;
let mut replacements = 0;
for reference in references {
match replace_at_span(¤t_content, reference, new_name_bytes) {
Ok(new_content) => {
current_content = new_content;
replacements += 1;
}
Err(e) => {
return Err(SpliceError::Other(format!(
"Failed to replace in {} at {}..{}: {}",
file_path.display(),
reference.byte_start,
reference.byte_end,
e
)));
}
}
}
fs::write(file_path, current_content).map_err(|e| SpliceError::Io {
path: file_path.to_path_buf(),
source: e,
})?;
Ok(replacements)
}
pub fn group_references_by_file(
references: &[ReferenceFact],
) -> HashMap<PathBuf, Vec<ReferenceFact>> {
let mut grouped: HashMap<PathBuf, Vec<ReferenceFact>> = HashMap::new();
for reference in references {
grouped
.entry(reference.file_path.clone())
.or_default()
.push(reference.clone());
}
for refs in grouped.values_mut() {
refs.sort_by_key(|b| std::cmp::Reverse(b.byte_start));
}
grouped
}
pub fn simulate_replacements(references: &[ReferenceFact]) -> HashMap<PathBuf, usize> {
let mut simulation: HashMap<PathBuf, usize> = HashMap::new();
for reference in references {
*simulation.entry(reference.file_path.clone()).or_insert(0) += 1;
}
simulation
}