rustic_rs/config/
hooks.rs1use std::collections::HashMap;
16
17use anyhow::Result;
18use conflate::Merge;
19use serde::{Deserialize, Serialize};
20
21use rustic_core::CommandInput;
22
23#[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)]
24#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
25pub struct Hooks {
26 #[merge(strategy = conflate::vec::append)]
28 pub run_before: Vec<CommandInput>,
29
30 #[merge(strategy = conflate::vec::append)]
32 pub run_after: Vec<CommandInput>,
33
34 #[merge(strategy = conflate::vec::append)]
36 pub run_failed: Vec<CommandInput>,
37
38 #[merge(strategy = conflate::vec::append)]
40 pub run_finally: Vec<CommandInput>,
41
42 #[serde(skip)]
43 #[merge(skip)]
44 pub context: String,
45
46 #[serde(skip)]
47 #[merge(skip)]
48 pub env: HashMap<String, String>,
49}
50
51impl Hooks {
52 pub fn with_context(&self, context: &str) -> Self {
53 let mut hooks = self.clone();
54 hooks.context = context.to_string();
55 hooks
56 }
57
58 pub fn with_env(&self, env: &HashMap<String, String>) -> Self {
59 let mut hooks = self.clone();
60 hooks.env = HashMap::<String, String>::new();
61 for (key, val) in env.iter() {
62 _ = hooks.env.insert(key.clone(), val.clone());
63 }
64 hooks
65 }
66
67 fn run_all(
68 cmds: &[CommandInput],
69 context: &str,
70 what: &str,
71 env: &HashMap<String, String>,
72 ) -> Result<()> {
73 let mut env = env.clone();
74
75 let _ = env.insert("RUSTIC_HOOK_TYPE".to_string(), what.to_string());
76
77 for cmd in cmds {
78 cmd.run(context, what, &env)?;
79 }
80
81 Ok(())
82 }
83
84 pub fn run_before(&self) -> Result<()> {
85 Self::run_all(&self.run_before, &self.context, "run-before", &self.env)
86 }
87
88 pub fn run_after(&self) -> Result<()> {
89 Self::run_all(&self.run_after, &self.context, "run-after", &self.env)
90 }
91
92 pub fn run_failed(&self) -> Result<()> {
93 Self::run_all(&self.run_failed, &self.context, "run-failed", &self.env)
94 }
95
96 pub fn run_finally(&self) -> Result<()> {
97 Self::run_all(&self.run_finally, &self.context, "run-finally", &self.env)
98 }
99
100 pub fn use_with<T>(&self, f: impl FnOnce() -> Result<T>) -> Result<T> {
106 match self.run_before() {
107 Ok(()) => match f() {
108 Ok(result) => match self.run_after() {
109 Ok(()) => {
110 self.run_finally()?;
111 Ok(result)
112 }
113 Err(err_after) => {
114 _ = self.run_finally();
115 Err(err_after)
116 }
117 },
118 Err(err_f) => {
119 _ = self.run_failed();
120 _ = self.run_finally();
121 Err(err_f)
122 }
123 },
124 Err(err_before) => {
125 _ = self.run_failed();
126 _ = self.run_finally();
127 Err(err_before)
128 }
129 }
130 }
131}