Grcov report - use_npm.rs

1

    use std::fs::File;

2

    use std::io::BufReader;

3

    use std::path::Path;

4

5

    use anyhow::Context as _;

6

    use hashbrown::HashMap;

7

    use serde::Deserialize;

8

9

    use crate::defaults::default_node_package_manager;

10

    use crate::file::ToUtf8 as _;

11

12

    use super::Task;

13

14

    #[derive(Debug, Deserialize)]

15

    #[serde(rename_all = "camelCase")]

16

    pub struct NpmPackage {

17

      /// The name of the package

18

      pub name: String,

19

20

      /// The version of the package

21

      pub version: Option<String>,

22

23

      /// The path to the package

24

      pub scripts: Option<HashMap<String, String>>,

25

26

      /// The package manager to use

27

      pub package_manager: Option<String>,

28

    }

29

30

    // TODO: Make use of the work_dir field

31

    #[derive(Debug, Deserialize)]

32

    pub struct UseNpmArgs {

33

      /// The package manager to use

34

      #[serde(default)]

35

      pub package_manager: Option<String>,

36

37

      /// The working directory to run the command in

38

      #[serde(default)]

39

      pub work_dir: Option<String>,

40

    }

41

42

    #[derive(Debug, Deserialize)]

43

    #[serde(untagged)]

44

    pub enum UseNpm {

45

      Bool(bool),

46

      UseNpm(Box<UseNpmArgs>),

47

    }

48

49

    impl UseNpm {

50

      pub fn capture(&self) -> anyhow::Result<HashMap<String, Task>> {

51

        match self {

52

          UseNpm::Bool(true) => self.capture_tasks(),

53

          UseNpm::UseNpm(args) => args.capture_tasks(),

54

          _ => Ok(HashMap::new()),

55

        }

56

      }

57

58

      fn capture_tasks(&self) -> anyhow::Result<HashMap<String, Task>> {

59

        UseNpmArgs {

60

          package_manager: None,

61

          work_dir: None,

62

        }

63

        .capture_tasks()

64

      }

65

    }

66

67

    impl UseNpmArgs {

68

      pub fn capture_tasks(&self) -> anyhow::Result<HashMap<String, Task>> {

69

        let path = Path::new("package.json");

70

        if !path.exists() || !path.is_file() {

71

          return Err(anyhow::anyhow!("package.json does not exist"));

72

        }

73

74

        let file = File::open(path).context(format!("Failed to open file - {}", path.to_utf8()?))?;

75

        let reader = BufReader::new(file);

76

77

        let package: NpmPackage = serde_json::from_reader(reader)?;

78

        let package_manager = self

79

          .package_manager

80

          .clone()

81

          .unwrap_or_else(default_node_package_manager);

82

83

        assert!(!package_manager.is_empty());

84

85

        let tasks: HashMap<String, Task> = package

86

          .scripts

87

          .unwrap_or_default()

88

          .into_iter()

89

          .map(|(k, _)| (k.clone(), Task::String(format!("{package_manager} run {k}"))))

90

          .collect();

91

        Ok(tasks)

92

      }

93

    }

94

95

    #[cfg(test)]

96

    mod tests {

97

      use super::*;

98

99

      #[test]

100
20

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

101
20

        let json = r#"{

102
20

          "name": "test",

103
20

          "version": "1.0.0",

104
20

          "scripts": {

105
20

            "build": "echo 'Building'",

106
20

            "test": "echo 'Testing'"

107
20

          }

108
20

        }"#;

109
20

        let package = serde_json::from_str::<NpmPackage>(json)?;

110
20

        assert_eq!(package.name, "test");

111
20

        assert_eq!(package.version, Some("1.0.0".to_string()));

112
20

        assert_eq!(

113
20

          package.scripts,

114
20

          Some({

115
20

            let mut map = HashMap::new();

116
20

            map.insert("build".to_string(), "echo 'Building'".to_string());

117
20

            map.insert("test".to_string(), "echo 'Testing'".to_string());

118
20

            map

119
20

          })

120
20

        );

121
20

        Ok(())

122
20

      }

123

124

      #[test]

125
20

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

126
20

        let yaml = "true";

127

128
20

        let use_npm = serde_yaml::from_str::<UseNpm>(yaml)?;

129
20

        if let UseNpm::Bool(value) = use_npm {

130
20

          assert!(value);

131

        } else {

132

          panic!("Invalid value");

133

        }

134

135
20

        Ok(())

136
20

      }

137

138

      #[test]

139
20

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

140
20

        let yaml = "false";

141

142
20

        let use_npm = serde_yaml::from_str::<UseNpm>(yaml)?;

143
20

        if let UseNpm::Bool(value) = use_npm {

144
20

          assert!(!value);

145

        } else {

146

          panic!("Invalid value");

147

        }

148

149
20

        Ok(())

150
20

      }

151

152

      #[test]

153
20

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

154
20

        let yaml = "

155
20

          package_manager: npm

156
20

        ";

157

158
20

        let use_npm = serde_yaml::from_str::<UseNpm>(yaml)?;

159
20

        if let UseNpm::UseNpm(args) = use_npm {

160
20

          assert_eq!(args.package_manager, Some("npm".to_string()));

161

        } else {

162

          panic!("Invalid value");

163

        }

164

165
20

        Ok(())

166
20

      }

167

168

      #[test]

169
20

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

170
20

        let yaml = "

171
20

          package_manager: yarn

172
20

          work_dir: /path/to/dir

173
20

        ";

174

175
20

        let use_npm = serde_yaml::from_str::<UseNpm>(yaml)?;

176
20

        if let UseNpm::UseNpm(args) = use_npm {

177
20

          assert_eq!(args.package_manager, Some("yarn".to_string()));

178
20

          assert_eq!(args.work_dir, Some("/path/to/dir".to_string()));

179

        } else {

180

          panic!("Invalid value");

181

        }

182

183
20

        Ok(())

184
20

      }

185

    }