refactor: put the dry-run and quiet checks on Ctx

This commit is contained in:
2026-09-09 12:32:55 +00:00
parent d9439253fd
commit b40dfe6124
10 changed files with 253 additions and 217 deletions

View File

@@ -4,7 +4,7 @@ use anyhow::{Result, anyhow};
use crate::cmd::{Bash, Cmd, Manage, Words};
use crate::ctx::Ctx;
use crate::fsops::{create_dir, touch, write_new};
use crate::output::note;
use crate::project::Project;
@@ -40,8 +40,8 @@ pub fn make_command(ctx: &Ctx, app: &Path, name: &str) -> Result<()> {
let management_dir = app_dir.join("management");
if !management_dir.exists() {
create_dir(ctx, &management_dir)?;
touch(ctx, &management_dir.join("__init__.py"))?;
ctx.fs().create_dir(&management_dir)?;
ctx.fs().touch(&management_dir.join("__init__.py"))?;
note!(ctx, "created module {app_name}.management")
};
@@ -49,14 +49,13 @@ pub fn make_command(ctx: &Ctx, app: &Path, name: &str) -> Result<()> {
let commands_dir = management_dir.join("commands");
if !commands_dir.exists() {
create_dir(ctx, &commands_dir)?;
touch(ctx, &commands_dir.join("__init__.py"))?;
ctx.fs().create_dir(&commands_dir)?;
ctx.fs().touch(&commands_dir.join("__init__.py"))?;
note!(ctx, "created module {app_name}.management.commands")
};
write_new(
ctx,
ctx.fs().write_new(
&commands_dir.join(format!("{name}.py")),
DEBUG_TEMPLATE.as_bytes(),
)?;
@@ -72,22 +71,18 @@ fn is_module_name(name: &str) -> bool {
}
pub fn bash(ctx: &Ctx) -> Result<()> {
Bash.in_service(&service(ctx)?)
.quiet(ctx.quiet)
.replace(ctx)
Bash.in_service(ctx, &service(ctx)?).replace(ctx)
}
pub fn run(ctx: &Ctx, rest: &[String]) -> Result<()> {
Words::new(rest)
.in_service(&service(ctx)?)
.quiet(ctx.quiet)
.in_service(ctx, &service(ctx)?)
.replace(ctx)
}
pub fn manage(ctx: &Ctx, rest: &[String]) -> Result<()> {
Manage::new(rest)
.in_service(&service(ctx)?)
.quiet(ctx.quiet)
.in_service(ctx, &service(ctx)?)
.replace(ctx)
}

View File

@@ -11,9 +11,7 @@ use anyhow::{Context, Result, anyhow, bail};
use self::store::{Leads, Repo, ignored, leads, resolve, symlink_metadata_opt, tracked};
use crate::ctx::Ctx;
use crate::fsops::{
ensure_private_parent, move_path, place_link, prune_empty, remove_file, rename, suffixed,
};
use crate::fsops::suffixed;
use crate::output::{line, note, warning};
const BACKUP_SUFFIX: &str = ".ahab-bak";
@@ -137,10 +135,10 @@ fn restore_one(ctx: &Ctx, repo: &Repo, path: &Path, report: &Report) -> Result<(
bail!("{} is in the way; move it aside", aside.display());
}
rename(ctx, &src, &aside)?;
ctx.fs().rename(&src, &aside)?;
if let Err(e) = move_path(ctx, &stored, &src) {
rename(ctx, &aside, &src).with_context(|| {
if let Err(e) = ctx.fs().move_path(&stored, &src) {
ctx.fs().rename(&aside, &src).with_context(|| {
format!(
"could not put the link at {} back after failing to restore it",
src.display()
@@ -150,8 +148,8 @@ fn restore_one(ctx: &Ctx, repo: &Repo, path: &Path, report: &Report) -> Result<(
return Err(e);
}
remove_file(ctx, &aside)?;
prune_empty(ctx, stored.parent(), &repo.base);
ctx.fs().remove_file(&aside)?;
ctx.fs().prune_empty(stored.parent(), &repo.base);
report.line("restored", &rel);
Ok(())
@@ -295,7 +293,7 @@ fn link_one(ctx: &Ctx, repo: &Repo, path: &Path, force: bool, report: &Report) -
stays_in_store(repo, &rel)?;
// before anything is moved in, so the tree it lands in is never briefly
// readable by anyone else
ensure_private_parent(ctx, &repo.base, &target)?;
ctx.fs().ensure_private_parent(&repo.base, &target)?;
if tracked(ctx, repo, &rel)? {
return Err(anyhow!(
@@ -363,7 +361,7 @@ fn link_one(ctx: &Ctx, repo: &Repo, path: &Path, force: bool, report: &Report) -
return Err(needs_force(&target));
}
place_link(ctx, &src, &target)?;
ctx.fs().place_link(&src, &target)?;
report.line("repointed", &rel);
Ok(())
}
@@ -381,10 +379,10 @@ fn link_one(ctx: &Ctx, repo: &Repo, path: &Path, force: bool, report: &Report) -
));
}
rename(ctx, &src, &backup)?;
ctx.fs().rename(&src, &backup)?;
report.line("saved", &suffixed(&rel, BACKUP_SUFFIX));
place_link(ctx, &src, &target)?;
ctx.fs().place_link(&src, &target)?;
report.line("linked", &rel);
Ok(())
}
@@ -399,7 +397,7 @@ fn link_one(ctx: &Ctx, repo: &Repo, path: &Path, force: bool, report: &Report) -
if !force {
return Err(needs_force(&target));
}
place_link(ctx, &src, &target)?;
ctx.fs().place_link(&src, &target)?;
report.line("linked", &rel);
Ok(())
}
@@ -416,10 +414,10 @@ fn link_one(ctx: &Ctx, repo: &Repo, path: &Path, force: bool, report: &Report) -
// but no link placed, the store holds a path nothing points at and the working
// tree has lost it altogether, which is the one outcome worse than failing
fn move_and_link(ctx: &Ctx, src: &Path, target: &Path) -> Result<()> {
move_path(ctx, src, target)?;
ctx.fs().move_path(src, target)?;
if let Err(e) = place_link(ctx, src, target) {
move_path(ctx, target, src).with_context(|| {
if let Err(e) = ctx.fs().place_link(src, target) {
ctx.fs().move_path(target, src).with_context(|| {
format!(
"could not put {} back after failing to link it to {}",
src.display(),

View File

@@ -11,11 +11,10 @@ use self::server::{Database, wait_until_ready, when_ready};
use self::shape::{Dump, HEADER_LEN, Kind};
use crate::cli::Format;
use crate::cmd::{
Cmd, Cp, CreateDb, DropDb, Gunzip, Gzip, Head, PgDump, PgDumpAll, PgRestore, Psql, Rm, Start,
Stop, Up,
Cmd, Cp, CreateDb, DropDb, Gunzip, Gzip, Head, PgDump, PgDumpAll, PgRestore, Psql, Rm,
};
use crate::ctx::Ctx;
use crate::fsops::{create_private_new, remove_file, rename, suffixed};
use crate::fsops::{create_private_new, suffixed};
use crate::output::{note, warning};
// unique per run: docker cp will not copy a directory over an existing path, and
@@ -136,7 +135,7 @@ pub fn import(ctx: &Ctx, file: &Path) -> Result<()> {
}
note!(ctx, "stopping all containers");
Stop { quiet: ctx.quiet }.run(ctx)?;
ctx.compose().stop().run(ctx)?;
// everything from here runs with the project down, so an error leaves it
// that way and the user has no reason to guess as much
@@ -159,11 +158,7 @@ fn local_path_for_docker(file: &Path) -> Result<()> {
fn imported(ctx: &Ctx, db: &Database, dump: &Dump, file: &Path) -> Result<()> {
note!(ctx, "starting db container");
Start {
service: &db.service,
quiet: ctx.quiet,
}
.run(ctx)?;
ctx.compose().start(&db.service).run(ctx)?;
let remote = remote_dump();
@@ -229,8 +224,8 @@ fn imported(ctx: &Ctx, db: &Database, dump: &Dump, file: &Path) -> Result<()> {
restored?;
note!(ctx, "restarting containers");
Stop { quiet: ctx.quiet }.run(ctx)?;
Up { quiet: ctx.quiet }.run(ctx)?;
ctx.compose().stop().run(ctx)?;
ctx.compose().up().run(ctx)?;
Ok(())
}
@@ -337,11 +332,11 @@ pub fn dump(ctx: &Ctx, file: &Path, format: Format, gzip: bool) -> Result<()> {
};
if let Err(e) = dumped {
let _ = remove_file(ctx, &partial);
let _ = ctx.fs().remove_file(&partial);
return Err(e);
}
rename(ctx, &partial, file)?;
ctx.fs().rename(&partial, file)?;
Ok(())
}

View File

@@ -4,7 +4,7 @@ use std::time::{Duration, Instant};
use anyhow::{Result, bail};
use super::shape::Kind;
use crate::cmd::{Cmd, PgIsReady, PgRestore, Ps, Psql};
use crate::cmd::{Cmd, PgIsReady, PgRestore, Psql};
use crate::ctx::Ctx;
use crate::project::Project;
@@ -26,7 +26,7 @@ impl Database {
let service = compose.postgres()?;
let (user, name) = compose.postgres_credentials(&service)?;
let listed = Ps::id_of(&service).capture(ctx)?;
let listed = ctx.compose().ps(&service).capture(ctx)?;
let mut ids = listed.lines().map(str::trim).filter(|id| !id.is_empty());
let container = match (ids.next(), ids.next()) {

View File

@@ -2,7 +2,7 @@ use std::path::Path;
use anyhow::Result;
use crate::cmd::{Cmd, Ps};
use crate::cmd::Cmd;
use crate::commands::link;
use crate::ctx::Ctx;
use crate::output::line;
@@ -62,7 +62,7 @@ fn role(ctx: &Ctx, role: &str, detected: Result<String>, project: &Project) {
line!("{role}: {service} ({image})");
match Ps::id_of(&service).capture(ctx) {
match ctx.compose().ps(&service).capture(ctx) {
Ok(id) if id.trim().is_empty() => line!("\tcontainer: not running"),
Ok(id) => line!("\tcontainer: {}", short(id.trim())),
Err(e) => line!("\tcontainer: {e:#}"),