sr_core/publishers/
custom.rs1use super::{PublishCtx, PublishState, Publisher};
8use crate::error::ReleaseError;
9use crate::hooks::run_shell;
10
11pub struct CustomPublisher {
12 pub command: String,
13 pub check: Option<String>,
14 pub cwd: Option<String>,
15}
16
17impl Publisher for CustomPublisher {
18 fn name(&self) -> &'static str {
19 "custom"
20 }
21
22 fn check(&self, ctx: &PublishCtx<'_>) -> Result<PublishState, ReleaseError> {
23 let Some(check_cmd) = &self.check else {
24 return Ok(PublishState::Unknown(
25 "no `check` command configured".into(),
26 ));
27 };
28
29 let cwd = self.cwd.clone().unwrap_or_else(|| ctx.package.path.clone());
30 let wrapped = format!("cd {} && {}", shell_word(&cwd), check_cmd);
31
32 match run_shell(&wrapped, None, ctx.env) {
37 Ok(()) => Ok(PublishState::Completed),
38 Err(_) => Ok(PublishState::Needed),
39 }
40 }
41
42 fn run(&self, ctx: &PublishCtx<'_>) -> Result<(), ReleaseError> {
43 let cwd = self.cwd.clone().unwrap_or_else(|| ctx.package.path.clone());
44 let wrapped = format!("cd {} && {}", shell_word(&cwd), self.command);
45
46 if ctx.dry_run {
47 eprintln!("[dry-run] custom ({cwd}): {}", self.command);
48 return Ok(());
49 }
50
51 eprintln!("custom ({cwd}): {}", self.command);
52 run_shell(&wrapped, None, ctx.env)
53 }
54}
55
56fn shell_word(s: &str) -> String {
57 let mut out = String::from("'");
58 for ch in s.chars() {
59 if ch == '\'' {
60 out.push_str("'\\''");
61 } else {
62 out.push(ch);
63 }
64 }
65 out.push('\'');
66 out
67}