diff --git a/Cargo.toml b/Cargo.toml index 1f7941d..addd833 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" [dependencies] anyhow = "1.0.95" clap = { version = "4.5.26", features = ["derive"] } +mktemp = "0.5.1" rand = "0.9.1" serde = { version = "1.0.217", features = ["derive"] } -tempfile = "3.20.0" thiserror = "2.0.11" toml = "0.8.19" diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 86dfa95..53ecf9d 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -4,12 +4,8 @@ use clap::Parser; #[command(version, about, long_about = None)] struct Args { /// Directory containing issues. - #[arg(short = 'd', long)] - issues_dir: Option, - - /// Branch containing issues. - #[arg(short = 'b', long)] - issues_branch: Option, + #[arg(short, long)] + issues_dir: String, /// Type of behavior/output. #[command(subcommand)] @@ -28,11 +24,14 @@ enum Commands { }, } -fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<()> { - match &args.command { +fn main() -> anyhow::Result<()> { + let args: Args = Args::parse(); + // println!("{:?}", args); + + match args.command { Commands::List => { let issues = - entomologist::issues::Issues::new_from_dir(std::path::Path::new(issues_dir))?; + entomologist::issues::Issues::new_from_dir(std::path::Path::new(&args.issues_dir))?; for (uuid, issue) in issues.issues.iter() { println!("{} {} ({:?})", uuid, issue.title, issue.state); } @@ -47,31 +46,3 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( Ok(()) } - -fn main() -> anyhow::Result<()> { - let args: Args = Args::parse(); - // println!("{:?}", args); - - if let (Some(_), Some(_)) = (&args.issues_dir, &args.issues_branch) { - return Err(anyhow::anyhow!( - "don't specify both `--issues-dir` and `--issues-branch`" - )); - } - - if let Some(dir) = &args.issues_dir { - let dir = std::path::Path::new(dir); - handle_command(&args, dir)?; - } else { - let branch = match &args.issues_branch { - Some(branch) => branch, - None => "entomologist-data", - }; - if !entomologist::git::git_branch_exists(branch)? { - entomologist::git::create_orphan_branch(branch)?; - } - let worktree = entomologist::git::Worktree::new(branch)?; - handle_command(&args, worktree.path())?; - } - - Ok(()) -} diff --git a/src/git.rs b/src/git.rs index 2b03b5a..8d1ce46 100644 --- a/src/git.rs +++ b/src/git.rs @@ -8,41 +8,6 @@ pub enum GitError { Oops, } -#[derive(Debug)] -/// `Worktree` is a struct that manages a temporary directory containing -/// a checkout of a specific branch. The worktree is removed and pruned -/// when the `Worktree` struct is dropped. -pub struct Worktree { - path: tempfile::TempDir, -} - -impl Drop for Worktree { - fn drop(&mut self) { - let _result = std::process::Command::new("git") - .args(["worktree", "remove", &self.path.path().to_string_lossy()]) - .output(); - } -} - -impl Worktree { - pub fn new(branch: &str) -> Result { - let path = tempfile::tempdir()?; - let result = std::process::Command::new("git") - .args(["worktree", "add", &path.path().to_string_lossy(), branch]) - .output()?; - if !result.status.success() { - println!("stdout: {}", std::str::from_utf8(&result.stdout).unwrap()); - println!("stderr: {}", std::str::from_utf8(&result.stderr).unwrap()); - return Err(GitError::Oops); - } - Ok(Self { path }) - } - - pub fn path(&self) -> &std::path::Path { - self.path.as_ref() - } -} - pub fn checkout_branch_in_worktree( branch: &str, worktree_dir: &std::path::Path, @@ -82,17 +47,10 @@ pub fn git_remove_branch(branch: &str) -> Result<(), GitError> { Ok(()) } -pub fn git_branch_exists(branch: &str) -> Result { - let result = std::process::Command::new("git") - .args(["show-ref", "--quiet", branch]) - .output()?; - return Ok(result.status.success()); -} - pub fn create_orphan_branch(branch: &str) -> Result<(), GitError> { { - let tmp_worktree = tempfile::tempdir().unwrap(); - create_orphan_branch_at_path(branch, tmp_worktree.path())?; + let tmp_worktree = mktemp::Temp::new_path(); + create_orphan_branch_at_path(branch, &tmp_worktree.to_path_buf())?; } // The temp dir is now removed / cleaned up. @@ -107,14 +65,16 @@ pub fn create_orphan_branch(branch: &str) -> Result<(), GitError> { Ok(()) } - -fn create_orphan_branch_at_path( +pub fn create_orphan_branch_at_path( branch: &str, - worktree_path: &std::path::Path, + worktree_path: &std::path::PathBuf, ) -> Result<(), GitError> { - let worktree_dir = worktree_path.to_string_lossy(); + let Some(worktree_dir) = worktree_path.to_str() else { + return Err(GitError::Oops); + }; + let result = std::process::Command::new("git") - .args(["worktree", "add", "--orphan", "-b", branch, &worktree_dir]) + .args(["worktree", "add", "--orphan", "-b", branch, worktree_dir]) .output()?; if !result.status.success() { println!("stdout: {}", std::str::from_utf8(&result.stdout).unwrap()); @@ -122,7 +82,7 @@ fn create_orphan_branch_at_path( return Err(GitError::Oops); } - let mut readme_filename = std::path::PathBuf::from(worktree_path); + let mut readme_filename = worktree_path.clone(); readme_filename.push("README.md"); let mut readme = std::fs::File::create(readme_filename)?; write!( @@ -132,7 +92,7 @@ fn create_orphan_branch_at_path( let result = std::process::Command::new("git") .args(["add", "README.md"]) - .current_dir(worktree_path) + .current_dir(worktree_dir) .output()?; if !result.status.success() { println!("stdout: {}", std::str::from_utf8(&result.stdout).unwrap()); @@ -159,19 +119,12 @@ mod tests { #[test] fn test_worktree() { - let mut p = std::path::PathBuf::new(); { - let worktree = Worktree::new("origin/main").unwrap(); - - p.push(worktree.path()); - assert!(p.exists()); - - let mut p2 = p.clone(); - p2.push("README.md"); - assert!(p2.exists()); + let temp_worktree = mktemp::Temp::new_path(); + checkout_branch_in_worktree("origin/main", temp_worktree.as_path()).unwrap(); + // The temporary worktree directory is removed when the Temp variable is dropped. } - // The temporary worktree directory is removed when the Temp variable is dropped. - assert!(!p.exists()); + git_worktree_prune().unwrap(); } #[test] @@ -182,19 +135,4 @@ mod tests { create_orphan_branch(&branch).unwrap(); git_remove_branch(&branch).unwrap(); } - - #[test] - fn test_branch_exists_0() { - let r = git_branch_exists("main").unwrap(); - assert_eq!(r, true); - } - - #[test] - fn test_branch_exists_1() { - let rnd: u128 = rand::random(); - let mut branch = std::string::String::from("entomologist-missing-branch-"); - branch.push_str(&format!("{:0x}", rnd)); - let r = git_branch_exists(&branch).unwrap(); - assert_eq!(r, false); - } }