Files
pick/src/tool/bash.rs
rm-dr b3d7b5274b
Some checks failed
CI / Typos (pull_request) Successful in 12s
CI / Clippy (pull_request) Successful in 59s
CI / Build and test (pull_request) Successful in 1m17s
CI / Check version (pull_request) Failing after 4s
Clippy
2025-07-13 17:20:09 +00:00

175 lines
4.2 KiB
Rust

use anyhow::{Context, Result};
use serde::Deserialize;
use std::io::Write;
use std::{collections::HashMap, path::Path};
use tracing::{debug, error, trace, warn};
use crate::manifest::types::PickConfig;
use super::{PickTool, TaskContext};
#[derive(Debug, Deserialize, Clone)]
pub struct ToolBash {
#[serde(default)]
pub before: Option<String>,
#[serde(default)]
pub after: Option<String>,
#[serde(default)]
pub env: HashMap<String, String>,
#[serde(default)]
pub script: HashMap<String, String>,
}
impl PickTool for ToolBash {
fn before(&self, manifest_path: &Path, cfg: &PickConfig) -> Result<()> {
let script = match &self.before {
None => {
return Ok(());
}
Some(script) => {
debug!("Running `before` script");
let mut temp_file =
tempfile::NamedTempFile::new().context("while creating temporary script")?;
writeln!(temp_file, "{script}").context("while creating temporary script")?;
temp_file
}
};
let mut cmd = std::process::Command::new("bash");
cmd.arg(script.path());
cmd.current_dir(&cfg.work_dir(manifest_path)?);
for (key, value) in &self.env {
cmd.env(key, value);
}
let output = match cmd.output() {
Ok(output) => output,
Err(error) => {
error!("Failed to execute `before` script: {error}");
return Ok(());
}
};
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!(
"`before` script failed with status {}: {stderr}",
output.status.code().unwrap_or(-1)
);
} else {
let stdout = String::from_utf8_lossy(&output.stdout);
#[expect(clippy::print_stdout)]
if !stdout.is_empty() {
println!("{}", stdout.trim());
}
}
return Ok(());
}
fn after(&self, manifest_path: &Path, cfg: &PickConfig) -> Result<()> {
let script = match &self.after {
None => {
return Ok(());
}
Some(script) => {
debug!("Running `after` script");
let mut temp_file =
tempfile::NamedTempFile::new().context("while creating temporary script")?;
writeln!(temp_file, "{script}").context("while creating temporary script")?;
temp_file
}
};
let mut cmd = std::process::Command::new("bash");
cmd.arg(script.path());
cmd.current_dir(&cfg.work_dir(manifest_path)?);
for (key, value) in &self.env {
cmd.env(key, value);
}
let output = match cmd.output() {
Ok(output) => output,
Err(error) => {
error!("Failed to execute `after` script: {error}");
return Ok(());
}
};
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!(
"`after` script failed with status {}: {stderr}",
output.status.code().unwrap_or(-1)
);
} else {
let stdout = String::from_utf8_lossy(&output.stdout);
#[expect(clippy::print_stdout)]
if !stdout.is_empty() {
println!("{}", stdout.trim());
}
}
return Ok(());
}
fn run(&self, manifest_path: &Path, cfg: &PickConfig, ctx: TaskContext) -> Result<()> {
let script = match self.script.get(&ctx.task) {
None => {
warn!("No script named \"{}\"", ctx.task);
return Ok(());
}
Some(script) => {
trace!("Running script for {}: {}", ctx.path_rel_str, ctx.task);
let mut temp_file =
tempfile::NamedTempFile::new().context("while creating temporary script")?;
writeln!(temp_file, "{script}").context("while creating temporary script")?;
temp_file
}
};
let mut cmd = std::process::Command::new("bash");
cmd.arg(script.path());
cmd.current_dir(&cfg.work_dir(manifest_path)?);
cmd.env("PICK_FILE", &ctx.path_abs_str);
cmd.env("PICK_RELATIVE", &ctx.path_rel_str);
for (key, value) in &self.env {
cmd.env(key, value);
}
let output = match cmd.output() {
Ok(output) => output,
Err(error) => {
error!("Failed to execute script for {}: {error}", ctx.path_rel_str);
return Ok(());
}
};
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!(
"Script for {} failed with status {}: {stderr}",
ctx.path_rel_str,
output.status.code().unwrap_or(-1)
);
} else {
let stdout = String::from_utf8_lossy(&output.stdout);
#[expect(clippy::print_stdout)]
if !stdout.is_empty() {
println!("{}", stdout.trim());
}
}
return Ok(());
}
}