wapm_cli/dataflow/
removed_lockfile_packages.rs1use crate::dataflow::bin_script::delete_bin_script;
2use crate::dataflow::lockfile_packages::{LockfilePackage, LockfilePackages};
3use crate::dataflow::manifest_packages::ManifestPackages;
4use crate::dataflow::removed_packages::RemovedPackages;
5use crate::dataflow::{bin_script, PackageKey, WapmPackageKey};
6use std::collections::hash_map::HashMap;
7use std::collections::hash_set::HashSet;
8use std::path::Path;
9use thiserror::Error;
10
11#[derive(Clone, Debug, Error)]
12pub enum Error {
13 #[error("Could not cleanup uninstalled command \"{0}\". {1}")]
14 CommandCleanupError(String, bin_script::Error),
15}
16
17#[derive(Clone, Debug)]
18pub struct RemovedLockfilePackages<'a> {
19 pub packages: HashMap<PackageKey<'a>, LockfilePackage>,
20}
21
22impl<'a> RemovedLockfilePackages<'a> {
23 pub fn from_manifest_and_lockfile(
24 manifest_packages: &'a ManifestPackages<'a>,
25 lockfile_packages: &'a LockfilePackages<'a>,
26 ) -> Self {
27 let old_package_keys: HashSet<_> = lockfile_packages.packages.keys().cloned().collect();
29 let packages = old_package_keys
30 .difference(&manifest_packages.packages)
31 .map(|key| {
32 (
33 key.clone(),
34 lockfile_packages.packages.get(key).cloned().unwrap(),
35 )
36 })
37 .collect();
38 Self { packages }
39 }
40
41 pub fn from_removed_packages_and_lockfile(
42 removed_packages: &'a RemovedPackages<'a>,
43 lockfile_packages: &'a LockfilePackages<'a>,
44 ) -> Self {
45 let packages = removed_packages
46 .packages
47 .iter()
48 .cloned()
49 .filter_map(|removed_package_name| {
50 lockfile_packages
51 .packages
52 .iter()
53 .find(|(key, _)| match key {
54 PackageKey::WapmPackage(WapmPackageKey { name, .. }) => {
55 name == &removed_package_name
56 }
57 _ => unreachable!(
58 "Lockfile should only contain exact wapm package versions."
59 ),
60 })
61 .map(|(key, data)| (key.clone(), data.clone()))
62 })
63 .collect();
64 Self { packages }
65 }
66
67 pub fn cleanup_old_packages<P: AsRef<Path>>(self, directory: P) -> Result<(), Error> {
69 let directory = directory.as_ref();
70 for (_key, data) in self.packages {
71 for command in data.commands {
72 delete_bin_script(directory, command.name.clone())
73 .map_err(|e| Error::CommandCleanupError(command.name.clone(), e))?;
74 }
75 }
77 Ok(())
78 }
79}
80
81#[cfg(test)]
82mod test {
83 use crate::dataflow::lockfile_packages::{LockfilePackage, LockfilePackages};
84 use crate::dataflow::manifest_packages::ManifestPackages;
85 use crate::dataflow::removed_lockfile_packages::RemovedLockfilePackages;
86 use crate::dataflow::removed_packages::RemovedPackages;
87 use crate::dataflow::PackageKey;
88 use std::collections::hash_set::HashSet;
89 use std::collections::HashMap;
90
91 #[test]
92 fn get_removed_lockfile_packages_from_manifest_and_lockfile() {
93 let mut manifest_packages = ManifestPackages::default();
94 let mut packages = HashSet::default();
95 packages.insert(PackageKey::new_registry_package(
96 "_/foo",
97 semver::Version::parse("1.0.0").unwrap(),
98 ));
99 packages.insert(PackageKey::new_registry_package(
100 "_/bar",
101 semver::Version::parse("2.0.0").unwrap(),
102 ));
103 manifest_packages.packages = packages;
104
105 let mut lockfile_packages = LockfilePackages::default();
106 let mut packages = HashMap::default();
107 packages.insert(
108 PackageKey::new_registry_package("_/foo", semver::Version::parse("1.0.0").unwrap()),
109 LockfilePackage::default(),
110 );
111 packages.insert(
112 PackageKey::new_registry_package("_/bar", semver::Version::parse("2.0.0").unwrap()),
113 LockfilePackage::default(),
114 );
115 packages.insert(
116 PackageKey::new_registry_package("_/baz", semver::Version::parse("3.0.0").unwrap()),
117 LockfilePackage::default(),
118 );
119 lockfile_packages.packages = packages;
120
121 let removed_lockfile_packages = RemovedLockfilePackages::from_manifest_and_lockfile(
122 &manifest_packages,
123 &lockfile_packages,
124 );
125 assert_eq!(1, removed_lockfile_packages.packages.len());
126 removed_lockfile_packages
127 .packages
128 .get(&PackageKey::new_registry_package(
129 "_/baz",
130 semver::Version::parse("3.0.0").unwrap(),
131 ))
132 .unwrap();
133 }
134
135 #[test]
136 fn get_removed_lockfile_packages_from_removed_packages_and_lockfile() {
137 let mut removed_packages = RemovedPackages::default();
138 let mut packages = HashSet::default();
139 packages.insert("_/foo".into());
140 packages.insert("_/bar".into());
141 removed_packages.packages = packages;
142
143 let mut lockfile_packages = LockfilePackages::default();
144 let mut packages = HashMap::default();
145 packages.insert(
146 PackageKey::new_registry_package("_/foo", semver::Version::parse("1.0.0").unwrap()),
147 LockfilePackage::default(),
148 );
149 packages.insert(
150 PackageKey::new_registry_package("_/bar", semver::Version::parse("2.0.0").unwrap()),
151 LockfilePackage::default(),
152 );
153 packages.insert(
154 PackageKey::new_registry_package("_/baz", semver::Version::parse("3.0.0").unwrap()),
155 LockfilePackage::default(),
156 );
157 lockfile_packages.packages = packages;
158
159 let removed_lockfile_packages = RemovedLockfilePackages::from_removed_packages_and_lockfile(
160 &removed_packages,
161 &lockfile_packages,
162 );
163 assert_eq!(2, removed_lockfile_packages.packages.len());
164 removed_lockfile_packages
165 .packages
166 .get(&PackageKey::new_registry_package(
167 "_/bar",
168 semver::Version::parse("2.0.0").unwrap(),
169 ))
170 .unwrap();
171 removed_lockfile_packages
172 .packages
173 .get(&PackageKey::new_registry_package(
174 "_/foo",
175 semver::Version::parse("1.0.0").unwrap(),
176 ))
177 .unwrap();
178 }
179}