wapm_cli/dataflow/
removed_lockfile_packages.rs

1use 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        // collect all removed packages
28        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    /// This will do the required cleanup of old artifacts like bin scripts and wapm packages
68    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            // TODO cleanup wapm_packages
76        }
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}