use std::fs;
use std::path::Path;
use syncdoc_migrate::{
extract_all_docs, find_expected_doc_paths, parse_file, restore_file, rewrite_file, DocsPathMode,
};
#[derive(Debug)]
pub enum ProcessResult {
Migrated {
extractions: Vec<syncdoc_migrate::DocExtraction>,
rewritten: bool,
touched: usize,
},
Restored {
dry_run: bool,
},
NoChange,
Error(String),
}
pub fn sync(
file_path: &Path,
args: &crate::cli::Args,
docs_root: &str,
docs_mode: DocsPathMode,
) -> ProcessResult {
if args.verbose {
eprintln!("Processing: {}", file_path.display());
}
let parsed = match parse_file(file_path) {
Ok(p) => p,
Err(e) => {
let error_msg = format!("Failed to parse {}: {}", file_path.display(), e);
if args.verbose {
eprintln!(" Warning: {}", error_msg);
}
return ProcessResult::Error(error_msg);
}
};
if args.restore {
if let Some(restored) = restore_file(&parsed, docs_root) {
if args.dry_run {
if args.verbose {
eprintln!(" Would restore: {}", file_path.display());
}
return ProcessResult::Restored { dry_run: true };
} else {
match fs::write(file_path, restored) {
Ok(_) => {
if args.verbose {
eprintln!(" Restored: {}", file_path.display());
}
return ProcessResult::Restored { dry_run: false };
}
Err(e) => {
return ProcessResult::Error(format!(
"Failed to write {}: {}",
file_path.display(),
e
));
}
}
}
} else {
return ProcessResult::NoChange;
}
}
let extractions = extract_all_docs(&parsed, docs_root);
if args.verbose && !extractions.is_empty() {
eprintln!(" Found {} doc extraction(s)", extractions.len());
}
let mut all_extractions = extractions;
if args.touch && args.annotate {
let expected_paths = find_expected_doc_paths(&parsed, docs_root);
if args.verbose {
eprintln!(" Found {} expected doc path(s)", expected_paths.len());
}
let existing_paths: std::collections::HashSet<_> =
all_extractions.iter().map(|e| &e.markdown_path).collect();
let missing_paths: Vec<_> = expected_paths
.into_iter()
.filter(|extraction| {
!existing_paths.contains(&extraction.markdown_path)
&& !extraction.markdown_path.exists()
})
.collect();
if !missing_paths.is_empty() && args.verbose {
eprintln!(" Will touch {} missing file(s)", missing_paths.len());
}
let touched_count = missing_paths.len();
all_extractions.extend(missing_paths);
let rewritten = if args.strip_docs || args.annotate {
if let Some(rewritten) = rewrite_file(
&parsed,
docs_root,
docs_mode,
args.strip_docs,
args.annotate,
) {
if args.dry_run {
if args.verbose {
eprintln!(" Would rewrite: {}", file_path.display());
}
true
} else {
match fs::write(file_path, rewritten) {
Ok(_) => {
if args.verbose {
eprintln!(" Rewrote: {}", file_path.display());
}
true
}
Err(e) => {
return ProcessResult::Error(format!(
"Failed to write {}: {}",
file_path.display(),
e
));
}
}
}
} else {
false
}
} else {
false
};
return ProcessResult::Migrated {
extractions: all_extractions,
rewritten,
touched: touched_count,
};
}
ProcessResult::Migrated {
extractions: all_extractions,
rewritten: false,
touched: 0,
}
}