#![allow(clippy::multiple_crate_versions)]
#[cfg(feature = "cli")]
pub mod cli {
pub mod args;
pub mod orchestrate;
pub mod report;
pub mod worker;
use args::{print_usage, Args};
use orchestrate::sync_all;
use report::{aggregate_results, print_summary};
use std::io;
use std::path::Path;
use syncdoc_migrate::{
discover_rust_files, get_or_create_docs_path, write_extractions, DocsPathMode,
};
pub fn main() -> io::Result<()> {
let mut args: Args = facet_args::from_std_args()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("{e}")))?;
args.strip_docs = args.strip_docs || args.migrate;
args.annotate = args.annotate || args.migrate;
args.touch = args.touch || args.migrate;
if args.help {
print_usage();
std::process::exit(0);
}
if args.restore && (args.migrate || args.strip_docs || args.annotate) {
eprintln!("Error: --restore cannot be used with --migrate, --cut, or --add");
std::process::exit(1);
}
let source_path = Path::new(&args.source);
if !source_path.exists() {
eprintln!("Error: Source path does not exist: {}", args.source);
std::process::exit(1);
}
let (docs_root, docs_mode) = if args.inline_paths || args.docs.is_some() {
let path = args.docs.as_deref().unwrap_or("docs");
let docs_root = path.to_string();
(docs_root, DocsPathMode::InlinePaths)
} else {
match get_or_create_docs_path(source_path, args.dry_run) {
Ok((path, mode)) => (path, mode),
Err(e) => {
eprintln!("Warning: Failed to get docs path from Cargo.toml: {}", e);
eprintln!("Using default 'docs' directory with inline paths");
("docs".to_string(), DocsPathMode::InlinePaths)
}
}
};
if args.verbose {
eprintln!("Source directory: {}", source_path.display());
eprintln!("Docs root: {}", docs_root);
eprintln!("Docs mode: {:?}", docs_mode);
eprintln!("Strip docs: {}", args.strip_docs);
eprintln!("Annotate: {}", args.annotate);
eprintln!("Restore: {}", args.restore);
eprintln!();
}
let rust_files = discover_rust_files(source_path)?;
if rust_files.is_empty() {
if args.verbose {
eprintln!("No Rust files found in source directory, nothing to process.");
}
return Ok(()); }
if args.verbose {
eprintln!("Found {} Rust file(s)", rust_files.len());
}
let num_threads = std::thread::available_parallelism().map_or(1, |n| n.get());
let oversubscribe = 4;
let total_chunks = num_threads * oversubscribe;
let chunk_size = rust_files.len().div_ceil(total_chunks);
if args.verbose {
eprintln!(
"Processing with {} threads ({} chunks of ~{} files)",
num_threads, total_chunks, chunk_size
);
}
let results = sync_all(&rust_files, &args, &docs_root, docs_mode);
let agg = aggregate_results(results);
write_extractions(&agg.all_extractions, args.dry_run)?;
print_summary(&agg, &args, args.dry_run, args.verbose);
Ok(())
}
}
#[cfg(not(feature = "cli"))]
pub mod cli {
pub fn main() {
eprintln!("Please build with the cli feature to run the CLI");
eprintln!("Example: cargo install syncdoc --features cli");
std::process::exit(1);
}
}
pub use cli::main;