snm_core/
linker.rs

1use crate::{
2    types::{AliasDir, ReleaseDir},
3    version::{DistVersion, ParseVersion},
4};
5use std::{
6    collections::HashMap,
7    fs::{read_dir, read_link},
8};
9
10use super::SnmRes;
11
12pub struct Linker;
13
14impl Linker {
15    pub fn remove_link(path: &AliasDir) -> SnmRes<()> {
16        if path.as_ref().exists() {
17            #[cfg(unix)]
18            std::fs::remove_file(path.as_ref())?;
19
20            #[cfg(windows)]
21            std::fs::remove_dir(path.as_ref())?;
22        }
23
24        Ok(())
25    }
26
27    pub fn create_link(original: &ReleaseDir, link: &AliasDir) -> SnmRes<()> {
28        Self::remove_link(link)?;
29
30        #[cfg(unix)]
31        std::os::unix::fs::symlink(original.as_ref(), link.as_ref())?;
32
33        #[cfg(windows)]
34        std::os::windows::fs::symlink_dir(original.as_ref(), link.as_ref())?;
35
36        Ok(())
37    }
38
39    pub fn read_convert_to_dist(a_dir: &AliasDir, r_dir: &ReleaseDir) -> SnmRes<DistVersion> {
40        let linked = read_link(a_dir.as_ref())?;
41        let link_ver = linked
42            .strip_prefix(r_dir.as_ref())?
43            .to_str()
44            .ok_or_else(|| anyhow::anyhow!("Unable to read and convert alias"))?;
45
46        DistVersion::parse(link_ver)
47    }
48
49    pub fn list_aliases(
50        a_dir: &AliasDir,
51        r_dir: &ReleaseDir,
52    ) -> SnmRes<HashMap<DistVersion, Vec<String>>> {
53        let mut aliases: HashMap<DistVersion, Vec<String>> = HashMap::new();
54        let entries = read_dir(&a_dir.as_ref())?;
55
56        for entry in entries {
57            let entry = entry?.path();
58            let link = read_link(&entry)?;
59
60            let link_ver = link.strip_prefix(r_dir.as_ref())?;
61            let alias = entry.strip_prefix(a_dir.as_ref())?;
62
63            if let (Some(v), Some(a)) = (link_ver.to_str(), alias.to_str()) {
64                let dist_ver = DistVersion::parse(v)?;
65
66                aliases
67                    .entry(dist_ver)
68                    .and_modify(|curr| curr.push(a.to_string()))
69                    .or_insert_with(|| vec![a.to_string()]);
70            }
71        }
72
73        Ok(aliases)
74    }
75
76    pub fn list_for_version(
77        version: &DistVersion,
78        a_dir: &AliasDir,
79        r_dir: &ReleaseDir,
80    ) -> SnmRes<Vec<String>> {
81        let mut aliases: Vec<String> = vec![];
82        let entries = read_dir(&a_dir.as_ref())?;
83
84        for entry in entries {
85            let entry = entry?.path();
86            let link = read_link(&entry)?;
87
88            let link_ver = link.strip_prefix(r_dir.as_ref())?;
89            let alias = entry.strip_prefix(a_dir.as_ref())?;
90
91            if let (Some(v), Some(a)) = (link_ver.to_str(), alias.to_str()) {
92                if DistVersion::parse(v)?.eq(version) {
93                    aliases.push(a.to_string());
94                }
95            }
96        }
97
98        Ok(aliases)
99    }
100}