refactor: hand clap's own structs to the commands

This commit is contained in:
2026-09-09 12:37:19 +00:00
parent b40dfe6124
commit 5dbe99a304
8 changed files with 156 additions and 128 deletions

View File

@@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
use anyhow::{Context, Result, anyhow, bail};
use self::store::{Leads, Repo, ignored, leads, resolve, symlink_metadata_opt, tracked};
use crate::cli::link as cli;
use crate::ctx::Ctx;
use crate::fsops::suffixed;
use crate::output::{line, note, warning};
@@ -19,8 +20,9 @@ const BACKUP_SUFFIX: &str = ".ahab-bak";
const RESTORING_SUFFIX: &str = ".ahab-restoring";
// move untracked paths out of the repo and symlink them back
pub fn add(ctx: &Ctx, paths: &[PathBuf], force: bool, store: Option<&Path>) -> Result<()> {
let repo = Repo::discover(ctx, store)?;
pub fn add(ctx: &Ctx, args: &cli::Add) -> Result<()> {
let (paths, force) = (args.paths.as_slice(), args.force);
let repo = Repo::discover(ctx, args.store.root())?;
let report = Report::new(&repo);
if let [path] = paths {
@@ -42,8 +44,9 @@ pub fn add(ctx: &Ctx, paths: &[PathBuf], force: bool, store: Option<&Path>) -> R
}
// move paths in the store back into the repo, the inverse of add
pub fn restore(ctx: &Ctx, paths: &[PathBuf], all: bool, store: Option<&Path>) -> Result<()> {
let repo = Repo::discover(ctx, store)?;
pub fn restore(ctx: &Ctx, args: &cli::Restore) -> Result<()> {
let (paths, all) = (args.paths.as_slice(), args.all);
let repo = Repo::discover(ctx, args.store.root())?;
let report = Report::new(&repo);
// clap requires one or the other and refuses both, so only the two real
@@ -225,8 +228,8 @@ pub fn stored_summary(ctx: &Ctx, store: Option<&Path>) -> Result<(PathBuf, usize
}
// list what the store holds for this repository, the inverse of check
pub fn list(ctx: &Ctx, store: Option<&Path>) -> Result<()> {
let repo = Repo::discover(ctx, store)?;
pub fn list(ctx: &Ctx, args: &cli::List) -> Result<()> {
let repo = Repo::discover(ctx, args.store.root())?;
let stored = stored_paths(&repo, &repo.store)?;
line!("store: {}", repo.store.display());

View File

@@ -6,20 +6,15 @@ use std::path::{Path, PathBuf};
use anyhow::{Result, anyhow};
use super::store::{Leads, Repo, leads, resolve, symlink_metadata_opt};
use crate::cli::link as cli;
use crate::cmd::{Cmd, LsFiles};
use crate::ctx::Ctx;
use crate::output::{line, text, write_bytes};
// whether anything is outside the store, which main turns into an exit code
pub fn check(
ctx: &Ctx,
paths: &[PathBuf],
porcelain: bool,
null: bool,
store: Option<&Path>,
) -> Result<bool> {
let repo = Repo::discover(ctx, store)?;
let pathspecs = relative_pathspecs(&repo, paths)?;
pub fn check(ctx: &Ctx, args: &cli::Check) -> Result<bool> {
let repo = Repo::discover(ctx, args.store.root())?;
let pathspecs = relative_pathspecs(&repo, &args.paths)?;
let mut exposed = Vec::new();
// git lists untracked and ignored separately
@@ -40,8 +35,8 @@ pub fn check(
exposed.sort_by(|a, b| a.name.cmp(&b.name));
if porcelain || null {
print_porcelain(&exposed, null);
if args.porcelain || args.null {
print_porcelain(&exposed, args.null);
} else {
print_listing(&repo, &exposed);
}

View File

@@ -10,6 +10,7 @@ use anyhow::{Context, Result, bail};
use self::server::{Database, wait_until_ready, when_ready};
use self::shape::{Dump, HEADER_LEN, Kind};
use crate::cli::Format;
use crate::cli::postgres as cli;
use crate::cmd::{
Cmd, Cp, CreateDb, DropDb, Gunzip, Gzip, Head, PgDump, PgDumpAll, PgRestore, Psql, Rm,
};
@@ -297,10 +298,13 @@ pub fn psql(ctx: &Ctx, rest: &[String]) -> Result<()> {
.replace(ctx)
}
pub fn dump(ctx: &Ctx, file: &Path, format: Format, gzip: bool) -> Result<()> {
pub fn dump(ctx: &Ctx, args: &cli::Dump) -> Result<()> {
let (file, format, gzip) = (args.path.as_path(), args.format, args.gzip);
let db = Database::resolve(ctx)?;
if format == Format::Directory {
// main says this as an argument error before getting here; kept as the
// last word in case anything else ever calls dump
if gzip {
bail!("a directory dump is a directory of already compressed files, not a stream");
}
@@ -343,8 +347,8 @@ pub fn dump(ctx: &Ctx, file: &Path, format: Format, gzip: bool) -> Result<()> {
// pg_dump for one database, pg_dumpall for a cluster, which has no format letter
fn dump_command(db: &Database, format: Format) -> Box<dyn Cmd + '_> {
match format.flag() {
Some(flag) => Box::new(PgDump::new(&db.user, &db.name, flag)),
match PgDump::of(&db.user, &db.name, format) {
Some(dump) => Box::new(dump),
None => Box::new(PgDumpAll { username: &db.user }),
}
}
@@ -364,7 +368,8 @@ fn dump_directory(ctx: &Ctx, db: &Database, target: &Path) -> Result<()> {
note!(ctx, "dumping to local directory {}", target.display());
let remote = remote_dump();
PgDump::new(&db.user, &db.name, "d")
PgDump::of(&db.user, &db.name, Format::Directory)
.expect("a directory dump has a pg_dump letter")
.to(&remote)
.in_container(&db.container)
.run(ctx)?;