]> quire.kejadlen.dev Git - quire.git/commitdiff
Inline repo submodules and add Repo::exists
authorAlpha Chen <alpha@kejadlen.dev>
Sat, 25 Apr 2026 14:00:32 +0000 (07:00 -0700)
committerAlpha Chen <alpha@kejadlen.dev>
Sat, 25 Apr 2026 14:05:35 +0000 (07:05 -0700)
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
src/bin/quire/commands/repo.rs [new file with mode: 0644]
src/bin/quire/commands/repo/list.rs [deleted file]
src/bin/quire/commands/repo/mod.rs [deleted file]
src/bin/quire/commands/repo/new.rs [deleted file]
src/bin/quire/commands/repo/rm.rs [deleted file]
src/bin/quire/main.rs
src/repo.rs

index d09da5e9b5de0dabe605bbd8fea4d0becdf30649..8af4a0148229075f8b426c7efaf71b5e570fc02c 100644 (file)
@@ -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<String>) -> 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 (file)
index 0000000..0fde07a
--- /dev/null
@@ -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<String> = 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 (file)
index da56be2..0000000
+++ /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<String> = 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 (file)
index ebd962f..0000000
+++ /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 (file)
index 1ded6d3..0000000
+++ /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 (file)
index 77013dd..0000000
+++ /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(())
-}
index bb19d0bf327279d9c885dd969521d9ebb8964cfd..c49821b509a28bbffa97131e9d4cee1a61efaa16 100644 (file)
@@ -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?,
         },
     }
 
index 451cc37663db9eb393bd6d3f9e5b7ec555b56e3c..b53353d053891a3c5257f71862bc8921aabc45b5 100644 (file)
@@ -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.