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
use std::collections::HashMap;
use anyhow::{ensure, Result};
use crate::opts;
use crate::configuration_file::ConfigurationFile;
use crate::monorepo_manifest::MonorepoManifest;
pub fn handle_subcommand(opts: opts::Lint) -> Result<()> {
match opts.subcommand {
opts::ClapLintSubCommand::DependencyVersion(args) => lint_dependency_version(&args),
}
}
fn most_common_dependency_version(
package_manifests_by_dependency_version: &HashMap<String, Vec<String>>,
) -> Option<String> {
package_manifests_by_dependency_version
.iter()
.map(|(dependency_version, package_manifests)| {
(dependency_version, package_manifests.len())
})
.max_by(|a, b| a.1.cmp(&b.1))
.map(|(k, _v)| k.to_owned())
}
fn lint_dependency_version(opts: &opts::DependencyVersion) -> Result<()> {
let opts::DependencyVersion { root, dependencies } = opts;
let lerna_manifest = MonorepoManifest::from_directory(root)?;
let package_manifest_by_package_name = lerna_manifest.package_manifests_by_package_name()?;
let mut is_exit_success = true;
for dependency in dependencies {
let package_manifests_by_dependency_version: HashMap<String, Vec<String>> =
package_manifest_by_package_name
.values()
.filter_map(|package_manifest| {
package_manifest
.get_dependency_version(dependency)
.map(|dependency_version| (package_manifest, dependency_version))
})
.fold(
HashMap::new(),
|mut accumulator, (package_manifest, dependency_version)| {
let packages_using_this_dependency_version =
accumulator.entry(dependency_version).or_default();
packages_using_this_dependency_version.push(
package_manifest
.path()
.into_os_string()
.into_string()
.expect("Path not UTF-8 encoded"),
);
accumulator
},
);
if package_manifests_by_dependency_version.keys().len() <= 1 {
return Ok(());
}
let expected_version_number =
most_common_dependency_version(&package_manifests_by_dependency_version)
.expect("Expected dependency to be used in at least one package");
println!("Linting versions of dependency \"{}\"", &dependency);
package_manifests_by_dependency_version
.into_iter()
.filter(|(dependency_version, _package_manifests)| {
!dependency_version.eq(&expected_version_number)
})
.for_each(|(dependency_version, package_manifests)| {
package_manifests.into_iter().for_each(|package_manifest| {
println!(
"\tIn {}, expected version {} but found version {}",
&package_manifest, &expected_version_number, dependency_version
);
});
});
is_exit_success = false;
}
ensure!(is_exit_success, "Found unexpected dependency versions");
Ok(())
}