Grcov report - precondition.rs

1

    use anyhow::Context as _;

2

    use serde::Deserialize;

3

    use std::io::{

4

      BufRead as _,

5

      BufReader,

6

    };

7

    use std::process::Command as ProcessCommand;

8

    use std::thread;

9

10

    use super::TaskContext;

11

    use crate::defaults::{

12

      default_shell,

13

      default_verbose,

14

    };

15

    use crate::handle_output;

16

    use crate::schema::get_output_handler;

17

18

    /// This struct represents a precondition that must be met before a task can be

19

    /// executed.

20

    #[derive(Debug, Default, Deserialize)]

21

    pub struct Precondition {

22

      /// The command to run

23

      pub command: String,

24

25

      //// The message to display if the command fails

26

      #[serde(default)]

27

      pub message: Option<String>,

28

29

      /// The shell to use to run the command

30

      #[serde(default = "default_shell")]

31

      pub shell: String,

32

33

      /// The working directory to run the command in

34

      #[serde(default)]

35

      pub work_dir: Option<String>,

36

37

      /// Show verbose output

38

      #[serde(default)]

39

      pub verbose: Option<bool>,

40

    }

41

42

    impl Precondition {

43

      pub fn execute(&self, context: &TaskContext) -> anyhow::Result<()> {

44

        assert!(!self.command.is_empty());

45

        assert!(!self.shell.is_empty());

46

47

        let verbose = self.verbose(context);

48

49

        let stdout = get_output_handler(verbose);

50

        let stderr = get_output_handler(verbose);

51

52

        let shell = &self.shell;

53

        let mut cmd = ProcessCommand::new(shell);

54

        cmd

55

          .arg("-c")

56

          .arg(self.command.clone())

57

          .stdout(stdout)

58

          .stderr(stderr);

59

60

        if self.work_dir.is_some() {

61

          cmd.current_dir(self.work_dir.as_ref().with_context(|| "Failed to get work_dir")?);

62

        }

63

64

        // Inject environment variables

65

        for (key, value) in context.env_vars.iter() {

66

          cmd.env(key, value);

67

        }

68

69

        let mut cmd = cmd.spawn()?;

70

71

        if verbose {

72

          handle_output!(cmd.stdout, context);

73

          handle_output!(cmd.stderr, context);

74

        }

75

76

        let status = cmd.wait()?;

77

        if !status.success() {

78

          if let Some(message) = &self.message {

79

            anyhow::bail!("Precondition failed - {}", message);

80

          } else {

81

            anyhow::bail!("Precondition failed - {}", self.command);

82

          }

83

        }

84

85

        Ok(())

86

      }

87

88

      fn verbose(&self, context: &TaskContext) -> bool {

89

        self.verbose.or(context.verbose).unwrap_or(default_verbose())

90

      }

91

    }

92

93

    #[cfg(test)]

94

    mod test {

95

      use super::*;

96

97

      #[test]

98
20

      fn test_precondition_1() -> anyhow::Result<()> {

99
20

        {

100
20

          let yaml = "

101
20

            command: 'echo \"Hello, World!\"'

102
20

            message: 'This is a message'

103
20

          ";

104
20

          let precondition = serde_yaml::from_str::<Precondition>(yaml)?;

105

106
20

          assert_eq!(precondition.command, "echo \"Hello, World!\"");

107
20

          assert_eq!(precondition.message, Some("This is a message".into()));

108
20

          assert_eq!(precondition.shell, "sh");

109
20

          assert_eq!(precondition.work_dir, None);

110
20

          assert_eq!(precondition.verbose, None);

111

112
20

          Ok(())

113

        }

114
20

      }

115

116

      #[test]

117
20

      fn test_precondition_2() -> anyhow::Result<()> {

118
20

        {

119
20

          let yaml = "

120
20

            command: 'echo \"Hello, World!\"'

121
20

          ";

122
20

          let precondition = serde_yaml::from_str::<Precondition>(yaml)?;

123

124
20

          assert_eq!(precondition.command, "echo \"Hello, World!\"");

125
20

          assert_eq!(precondition.message, None);

126
20

          assert_eq!(precondition.shell, "sh");

127
20

          assert_eq!(precondition.work_dir, None);

128
20

          assert_eq!(precondition.verbose, None);

129

130
20

          Ok(())

131

        }

132
20

      }

133

134

      #[test]

135
20

      fn test_precondition_3() -> anyhow::Result<()> {

136
20

        {

137
20

          let yaml = "

138
20

            command: 'echo \"Hello, World!\"'

139
20

            message: null

140
20

          ";

141
20

          let precondition = serde_yaml::from_str::<Precondition>(yaml)?;

142

143
20

          assert_eq!(precondition.command, "echo \"Hello, World!\"");

144
20

          assert_eq!(precondition.message, None);

145
20

          assert_eq!(precondition.shell, "sh");

146
20

          assert_eq!(precondition.work_dir, None);

147
20

          assert_eq!(precondition.verbose, None);

148

149
20

          Ok(())

150

        }

151
20

      }

152

153

      #[test]

154
20

      fn test_precondition_4() -> anyhow::Result<()> {

155
20

        {

156
20

          let yaml = "

157
20

            command: 'echo \"Hello, World!\"'

158
20

            work_dir: /tmp

159
20

          ";

160
20

          let precondition = serde_yaml::from_str::<Precondition>(yaml)?;

161

162
20

          assert_eq!(precondition.command, "echo \"Hello, World!\"");

163
20

          assert_eq!(precondition.message, None);

164
20

          assert_eq!(precondition.shell, "sh");

165
20

          assert_eq!(precondition.work_dir, Some("/tmp".into()));

166
20

          assert_eq!(precondition.verbose, None);

167

168
20

          Ok(())

169

        }

170
20

      }

171

172

      #[test]

173
20

      fn test_precondition_5() -> anyhow::Result<()> {

174
20

        {

175
20

          let yaml = "

176
20

            command: 'echo \"Hello, World!\"'

177
20

            verbose: true

178
20

          ";

179
20

          let precondition = serde_yaml::from_str::<Precondition>(yaml)?;

180

181
20

          assert_eq!(precondition.command, "echo \"Hello, World!\"");

182
20

          assert_eq!(precondition.message, None);

183
20

          assert_eq!(precondition.shell, "sh");

184
20

          assert_eq!(precondition.work_dir, None);

185
20

          assert_eq!(precondition.verbose, Some(true));

186

187
20

          Ok(())

188

        }

189
20

      }

190

    }