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}