use inquire::{self, set_global_render_config};
use std::error::Error;
use std::fs;
use std::io::Write as _;
use std::path::PathBuf;
use std::process::Command;
use thag_styling::{
auto_help, file_navigator, help_system::check_help_and_exit, styling::Styleable,
themed_inquire_config,
};
file_navigator! {}
struct TempCleanupGuard(PathBuf);
impl Drop for TempCleanupGuard {
fn drop(&mut self) {
if self.0.exists() {
let _ = fs::remove_dir_all(&self.0);
}
}
}
fn main() -> Result<(), Box<dyn Error>> {
let help = auto_help!();
check_help_and_exit(&help);
set_global_render_config(themed_inquire_config());
let mut navigator = FileNavigator::new();
let (dest_dir, demo_dest) = loop {
println!("Select where you want to save the new `demo` directory");
let Ok(dest_dir) = select_directory(&mut navigator, false) else {
println!("\nNo directory selected. Exiting.\n");
return Ok(());
};
let demo_dest = dest_dir.join("demo");
if demo_dest.exists() {
println!(
"\n{}\n",
format!("Destination already has subdirectory {}", "demo").emphasis()
);
continue;
}
break (dest_dir, demo_dest);
};
let temp_clone = dest_dir.join("temp_thag_rs_clone");
let _cleanup_guard = TempCleanupGuard(temp_clone.clone());
let status = Command::new("git")
.args([
"clone",
"--depth",
"1",
"--branch",
"main",
"--filter=blob:none",
"--sparse",
"https://github.com/durbanlegend/thag_rs.git",
temp_clone.to_str().unwrap(),
])
.status()?;
if !status.success() {
return Err("git clone failed".into());
}
let status = Command::new("git")
.current_dir(&temp_clone)
.args(["sparse-checkout", "set", "--no-cone", "demo"])
.status()?;
if !status.success() {
return Err("git sparse-checkout failed".into());
}
let sparse_file = temp_clone.join(".git/info/sparse-checkout");
let mut file = fs::OpenOptions::new().append(true).open(&sparse_file)?;
file.write_all(b"!demo/proc_macros/target/\n")?;
let status = Command::new("git")
.current_dir(&temp_clone)
.args(["read-tree", "-mu", "HEAD"])
.status()?;
if !status.success() {
return Err("git read-tree failed".into());
}
let status = Command::new("rm")
.args(["-rf", ".git"])
.current_dir(&temp_clone)
.status()?;
if !status.success() {
return Err("failed to remove .git".into());
}
let demo_src = temp_clone.join("demo");
fs::rename(&demo_src, &demo_dest)?;
fs::remove_dir_all(&temp_clone)?;
println!("✅ demo/ downloaded to: {}", demo_dest.display());
Ok(())
}