dotfiles_actions/exec/
action.rs1use std::marker::PhantomData;
25use std::path::Path;
26
27use dotfiles_core::error::execution_error;
28use dotfiles_core::error::DotfilesError;
29use dotfiles_core_macros::ConditionalAction;
30use subprocess::Exec;
31use subprocess::ExitStatus;
32
33use dotfiles_core::Action;
34
35#[derive(Eq, PartialEq, Debug, ConditionalAction)]
37pub struct ExecAction<'a> {
38 skip_in_ci: bool,
40 command: String,
42 description: Option<String>,
44 echo: bool,
46 phantom_data: PhantomData<&'a String>,
47}
48
49impl<'a> ExecAction<'a> {
50 pub fn new(
52 skip_in_ci: bool,
53 command: String,
54 description: Option<String>,
55 echo: bool,
56 current_dir: &Path,
57 ) -> Result<Self, DotfilesError> {
58 let action = ExecAction {
59 skip_in_ci,
60 command: format!(
61 "cd \"{}\" && {}",
62 current_dir.as_os_str().to_str().unwrap(),
63 command
64 ),
65 description,
66 echo,
67 phantom_data: PhantomData,
68 };
69 log::trace!("Creating new {:?}", action);
70 Ok(action)
71 }
72 pub fn command(&self) -> &str {
74 self.command.as_str()
75 }
76
77 pub fn echo(&self) -> bool {
79 self.echo
80 }
81
82 pub fn description(&self) -> Option<&String> {
84 self.description.as_ref()
85 }
86}
87
88impl<'a> Action<'a> for ExecAction<'a> {
89 fn execute(&self) -> Result<(), DotfilesError> {
90 if let Some(description) = self.description.as_ref() {
91 log::info!("{}", description);
92 }
93 if self.echo {
94 log::info!("Running command: {0}", self.command);
95 }
96 Exec::shell(self.command()).join().map_or_else(
97 |err| {
98 Err(DotfilesError::from(
99 format!(
100 "Couldn't run command `{0}`, failed with error {1}",
101 self.command(),
102 err
103 ),
104 execution_error(Some(err), None),
105 ))
106 },
107 |status| match status {
108 ExitStatus::Exited(0) => Ok(()),
109 ExitStatus::Exited(code) => Err(DotfilesError::from(
110 format!(
111 "Command `{0}` failed with error code {1}",
112 self.command(),
113 code
114 ),
115 execution_error(None, Some(status)),
116 )),
117 _ => Err(DotfilesError::from(
118 format!(
119 "Unexpected error while running command `{0}`",
120 self.command()
121 ),
122 execution_error(None, Some(status)),
123 )),
124 },
125 )
126 }
127}