forked from o2sh/onefetch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackage_manager.rs
127 lines (106 loc) · 3.3 KB
/
package_manager.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use anyhow::Result;
use regex::Regex;
use std::collections::HashMap;
use strum::EnumIter;
use toml::Value;
use yaml_rust::YamlLoader;
macro_rules! define_package_managers {
($( { $name:ident, $display:literal, [$(($file:literal, $parser:expr))+] } ),+ ,) => {
#[derive(PartialEq, EnumIter)]
pub enum PackageManager {
$(
$name ,
)+
}
impl std::fmt::Display for PackageManager {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
$( PackageManager::$name => write!(f, $display), )+
}
}
}
pub fn build() -> HashMap<String, (fn(&str) -> Result<usize>, PackageManager)> {
let mut package_managers: HashMap<
String,
(fn(&str) -> Result<usize>, PackageManager)
> = HashMap::new();
$(
$(
package_managers.insert(String::from($file), ($parser, PackageManager::$name));
)+
)+
package_managers
}
}
}
define_package_managers! {
{ Cargo, "cargo", [ ("Cargo.toml", cargo) ] },
{ GoModules, "go modules", [ ("go.mod", go_modules) ] },
{ Npm, "npm", [ ("package.json", npm) ] },
{ Pip, "pip", [ ("requirements.txt", pip_requirement) ("pyproject.toml", pip_pyproject) ("Pipfile", pip_pipfile) ] },
{ Pub, "pub", [ ("pubspec.yaml", pub_packages) ] },
}
fn cargo(contents: &str) -> Result<usize> {
let parsed = contents.parse::<Value>()?;
let count = parsed.get("dependencies");
match count {
Some(val) => Ok(val.as_table().unwrap().len()),
None => Ok(0),
}
}
fn go_modules(contents: &str) -> Result<usize> {
let mut count = 0;
let mut start = false;
for line in contents.lines() {
if line.contains("require") {
start = true;
continue;
}
if start && line.contains(')') {
break;
}
if start {
count += 1;
}
}
Ok(count)
}
fn npm(contents: &str) -> Result<usize> {
let parsed: serde_json::Value = serde_json::from_str(contents)?;
match &parsed["dependencies"].as_object() {
Some(val) => Ok(val.len()),
None => Ok(0),
}
}
fn pip_requirement(contents: &str) -> Result<usize> {
let count = Regex::new(r"(^|\n)[A-z]+")?.find_iter(contents).count();
Ok(count)
}
fn pip_pyproject(contents: &str) -> Result<usize> {
let parsed = contents.parse::<Value>()?;
let count = parsed
.get("tool")
.and_then(|tool| tool.get("poetry"))
.and_then(|poetry| poetry.get("dependencies"));
match count {
Some(val) => Ok(val.as_table().unwrap().len()),
None => Ok(0),
}
}
fn pip_pipfile(contents: &str) -> Result<usize> {
let parsed = contents.parse::<Value>()?;
let count = parsed.get("packages");
match count {
Some(val) => Ok(val.as_table().unwrap().len()),
None => Ok(0),
}
}
fn pub_packages(contents: &str) -> Result<usize> {
match YamlLoader::load_from_str(contents) {
Ok(parsed) => match &parsed[0]["dependencies"].as_hash() {
Some(deps) => Ok(deps.len()),
None => Ok(0),
},
Err(_) => Ok(0),
}
}