From 897c0308743265458cd0ac95adea2680b8e815ac Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sat, 25 Apr 2026 07:00:32 -0700 Subject: [PATCH] Inline repo submodules and add Repo::exists Collapsed commands/repo/{new,list,rm}.rs into a single repo.rs. Added Repo::exists() so callers don't need to construct paths just to check. Assisted-by: GLM-5.1 via pi --- src/bin/quire/commands/exec.rs | 23 +++--- src/bin/quire/commands/repo.rs | 105 ++++++++++++++++++++++++++++ src/bin/quire/commands/repo/list.rs | 49 ------------- src/bin/quire/commands/repo/mod.rs | 3 - src/bin/quire/commands/repo/new.rs | 35 ---------- src/bin/quire/commands/repo/rm.rs | 25 ------- src/bin/quire/main.rs | 6 +- src/repo.rs | 4 ++ 8 files changed, 121 insertions(+), 129 deletions(-) create mode 100644 src/bin/quire/commands/repo.rs delete mode 100644 src/bin/quire/commands/repo/list.rs delete mode 100644 src/bin/quire/commands/repo/mod.rs delete mode 100644 src/bin/quire/commands/repo/new.rs delete mode 100644 src/bin/quire/commands/repo/rm.rs diff --git a/src/bin/quire/commands/exec.rs b/src/bin/quire/commands/exec.rs index d09da5e..8af4a01 100644 --- a/src/bin/quire/commands/exec.rs +++ b/src/bin/quire/commands/exec.rs @@ -3,15 +3,10 @@ use std::process::Command; use miette::{Context, IntoDiagnostic, Result, bail, ensure}; -use quire::repo::Repo; use quire::Config; +use quire::repo::Repo; -const GIT_COMMANDS: &[&str] = &[ - "git-receive-pack", - "git-upload-pack", - "git-upload-archive", -]; - +const GIT_COMMANDS: &[&str] = &["git-receive-pack", "git-upload-pack", "git-upload-archive"]; pub async fn run(config: &Config, command: Vec) -> Result<()> { let input = if command.len() == 1 { @@ -51,14 +46,16 @@ fn dispatch_git(config: &Config, git_cmd: &str, args: &[String]) -> Result<()> { ensure!(!path.is_empty(), "empty repository path"); let repo = Repo::from_name(path)?; + ensure!( + repo.exists(&config.repos_dir), + "repository not found: {}", + repo.name() + ); + let repo_dir = repo.path(&config.repos_dir); - ensure!(repo_dir.is_dir(), "repository not found: {}", repo.name()); tracing::info!(%git_cmd, name = %repo.name(), "dispatching git command"); - let err = Command::new(git_cmd) - .arg(".") - .current_dir(&repo_dir) - .exec(); + let err = Command::new(git_cmd).arg(".").current_dir(&repo_dir).exec(); bail!("exec failed: {err}") } @@ -72,5 +69,3 @@ fn dispatch_quire(_config: &Config, args: &[String]) -> Result<()> { let err = Command::new("quire").arg("repo").args(&args[1..]).exec(); bail!("exec failed: {err}") } - - diff --git a/src/bin/quire/commands/repo.rs b/src/bin/quire/commands/repo.rs new file mode 100644 index 0000000..0fde07a --- /dev/null +++ b/src/bin/quire/commands/repo.rs @@ -0,0 +1,105 @@ +use std::process::Command; + +use miette::{IntoDiagnostic, Result, ensure}; + +use quire::Config; +use quire::repo::Repo; + +pub async fn new(config: &Config, name: &str) -> Result<()> { + let repo = Repo::from_name(name)?; + ensure!( + !repo.exists(&config.repos_dir), + "repository already exists: {}", + repo.name() + ); + + let repo_dir = repo.path(&config.repos_dir); + + // Create parent directory for grouped repos (e.g. work/foo.git). + if let Some(parent) = repo_dir.parent() { + fs_err::create_dir_all(parent).into_diagnostic()?; + } + + let status = Command::new("git") + .args(["init", "--bare", repo.name()]) + .current_dir(&config.repos_dir) + .status() + .into_diagnostic()?; + + ensure!(status.success(), "git init failed"); + + tracing::info!(name = %repo.name(), "created repository"); + println!("{}", repo.name()); + + Ok(()) +} + +pub async fn list(config: &Config) -> Result<()> { + let entries = fs_err::read_dir(&config.repos_dir).into_diagnostic()?; + + let mut repos: Vec = Vec::new(); + for entry in entries { + let entry = entry.into_diagnostic()?; + let path = entry.path(); + + if !path.is_dir() { + continue; + } + + let Ok(relative) = path.strip_prefix(&config.repos_dir) else { + continue; + }; + let name = relative.to_string_lossy(); + + // Top-level .git directory. + if name.ends_with(".git") { + repos.push(name.to_string()); + continue; + } + + // Group directory — collect .git children. + let Ok(children) = fs_err::read_dir(&path) else { + continue; + }; + for child in children { + let child = child.into_diagnostic()?; + let child_name = child.file_name(); + let child_name = child_name.to_string_lossy(); + if child_name.ends_with(".git") && child.path().is_dir() { + let full = format!("{}/{}", name, child_name); + repos.push(full); + } + } + } + + repos.sort(); + for repo in &repos { + println!("{repo}"); + } + + Ok(()) +} + +pub async fn rm(config: &Config, name: &str) -> Result<()> { + let repo = Repo::from_name(name)?; + ensure!( + repo.exists(&config.repos_dir), + "repository not found: {}", + repo.name() + ); + + let repo_dir = repo.path(&config.repos_dir); + + fs_err::remove_dir_all(&repo_dir).into_diagnostic()?; + + // Clean up empty parent directory for grouped repos. + if let Some(parent) = repo_dir.parent() + && parent != config.repos_dir + { + let _ = fs_err::remove_dir(parent); + } + + tracing::info!(name = %repo.name(), "removed repository"); + + Ok(()) +} diff --git a/src/bin/quire/commands/repo/list.rs b/src/bin/quire/commands/repo/list.rs deleted file mode 100644 index da56be2..0000000 --- a/src/bin/quire/commands/repo/list.rs +++ /dev/null @@ -1,49 +0,0 @@ -use miette::{IntoDiagnostic, Result}; - -use quire::Config; - -pub async fn run(config: &Config) -> Result<()> { - let entries = fs_err::read_dir(&config.repos_dir).into_diagnostic()?; - - let mut repos: Vec = Vec::new(); - for entry in entries { - let entry = entry.into_diagnostic()?; - let path = entry.path(); - - if !path.is_dir() { - continue; - } - - let Ok(relative) = path.strip_prefix(&config.repos_dir) else { - continue; - }; - let name = relative.to_string_lossy(); - - // Top-level .git directory. - if name.ends_with(".git") { - repos.push(name.to_string()); - continue; - } - - // Group directory — collect .git children. - let Ok(children) = fs_err::read_dir(&path) else { - continue; - }; - for child in children { - let child = child.into_diagnostic()?; - let child_name = child.file_name(); - let child_name = child_name.to_string_lossy(); - if child_name.ends_with(".git") && child.path().is_dir() { - let full = format!("{}/{}", name, child_name); - repos.push(full); - } - } - } - - repos.sort(); - for repo in &repos { - println!("{repo}"); - } - - Ok(()) -} diff --git a/src/bin/quire/commands/repo/mod.rs b/src/bin/quire/commands/repo/mod.rs deleted file mode 100644 index ebd962f..0000000 --- a/src/bin/quire/commands/repo/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod list; -pub mod new; -pub mod rm; diff --git a/src/bin/quire/commands/repo/new.rs b/src/bin/quire/commands/repo/new.rs deleted file mode 100644 index 1ded6d3..0000000 --- a/src/bin/quire/commands/repo/new.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::process::Command; - -use miette::{IntoDiagnostic, Result, ensure}; - -use quire::Config; -use quire::repo::Repo; - -pub async fn run(config: &Config, name: &str) -> Result<()> { - let repo = Repo::from_name(name)?; - let repo_dir = repo.path(&config.repos_dir); - - ensure!( - !repo_dir.exists(), - "repository already exists: {}", - repo.name() - ); - - // Create parent directory for grouped repos (e.g. work/foo.git). - if let Some(parent) = repo_dir.parent() { - fs_err::create_dir_all(parent).into_diagnostic()?; - } - - let status = Command::new("git") - .args(["init", "--bare", repo.name()]) - .current_dir(&config.repos_dir) - .status() - .into_diagnostic()?; - - ensure!(status.success(), "git init failed"); - - tracing::info!(name = %repo.name(), "created repository"); - println!("{}", repo.name()); - - Ok(()) -} diff --git a/src/bin/quire/commands/repo/rm.rs b/src/bin/quire/commands/repo/rm.rs deleted file mode 100644 index 77013dd..0000000 --- a/src/bin/quire/commands/repo/rm.rs +++ /dev/null @@ -1,25 +0,0 @@ -use miette::{IntoDiagnostic, Result, ensure}; - -use quire::Config; -use quire::repo::Repo; - -pub async fn run(config: &Config, name: &str) -> Result<()> { - let repo = Repo::from_name(name)?; - let repo_dir = repo.path(&config.repos_dir); - - ensure!(repo_dir.exists(), "repository not found: {}", repo.name()); - ensure!(repo_dir.is_dir(), "not a directory: {}", repo.name()); - - fs_err::remove_dir_all(&repo_dir).into_diagnostic()?; - - // Clean up empty parent directory for grouped repos. - if let Some(parent) = repo_dir.parent() - && parent != config.repos_dir - { - let _ = fs_err::remove_dir(parent); - } - - tracing::info!(name = %repo.name(), "removed repository"); - - Ok(()) -} diff --git a/src/bin/quire/main.rs b/src/bin/quire/main.rs index bb19d0b..c49821b 100644 --- a/src/bin/quire/main.rs +++ b/src/bin/quire/main.rs @@ -95,9 +95,9 @@ async fn main() -> Result<()> { Commands::Exec { command } => commands::exec::run(&config, command).await?, Commands::Hook { hook_name } => commands::hook::run(hook_name).await?, Commands::Repo { command } => match command { - RepoCommands::New { name } => commands::repo::new::run(&config, &name).await?, - RepoCommands::List => commands::repo::list::run(&config).await?, - RepoCommands::Rm { name } => commands::repo::rm::run(&config, &name).await?, + RepoCommands::New { name } => commands::repo::new(&config, &name).await?, + RepoCommands::List => commands::repo::list(&config).await?, + RepoCommands::Rm { name } => commands::repo::rm(&config, &name).await?, }, } diff --git a/src/repo.rs b/src/repo.rs index 451cc37..b53353d 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -27,6 +27,10 @@ impl Repo { pub fn path(&self, repos_dir: &Path) -> PathBuf { repos_dir.join(&self.name) } + + pub fn exists(&self, repos_dir: &Path) -> bool { + self.path(repos_dir).is_dir() + } } /// Validate segments of a repository name. -- 2.54.0