Skip to main content

selene_core/config/common/
mutators.rs

1use std::{io, path::PathBuf};
2
3use lunar_lib::{ask, error, info};
4
5use crate::{config::common::CommonConfig, utils::list_dirs_to_string};
6
7impl CommonConfig {
8    /// Sets your library directory to the input path after validation
9    ///
10    /// The directory is invalid if:
11    /// - The library directory starts with a source
12    /// - Any source starts with the library directory
13    /// - The library directory is equal to any source
14    /// - The path is relative
15    ///
16    /// # Errors
17    ///
18    /// Errors when sources or the library fail to canonicalize via `std::path::Path::canonicalize()`
19    /// Paths that do not exist on the file system are not canonicalized
20    pub fn set_library_directory(&mut self, path: impl Into<PathBuf>) -> io::Result<&mut Self> {
21        let path = path.into();
22        let library_dir = self.library_dir.as_ref();
23
24        if Some(&path) == library_dir {
25            info!(
26                "The library directory is already set to '{}'",
27                path.display()
28            );
29            return Ok(self);
30        }
31
32        if !self.valid_library_dir(&path)? {
33            error!(
34                "Could not set the library directory to '{}': Path is not valid",
35                path.display()
36            );
37            return Ok(self);
38        }
39
40        self.library_dir = Some(path);
41
42        Ok(self)
43    }
44
45    /// Sets your sources to the input sources after validation
46    ///
47    /// Sources are invalid if:
48    /// - The library directory starts with the source
49    /// - The source starts with the library directory
50    /// - The library directory and source are equal
51    /// - The source is a relative path
52    ///
53    /// # Errors
54    ///
55    /// Errors when sources or the library fail to canonicalize via `std::path::Path::canonicalize()`
56    /// Paths that do not exist on the file system are not canonicalized
57    pub fn set_library_sources(&mut self, paths: &[PathBuf]) -> io::Result<&mut Self> {
58        if paths.is_empty() {
59            self.source_dirs = Vec::new();
60            return Ok(self);
61        }
62
63        let validity_checked_paths: Vec<(PathBuf, bool)> = paths
64            .iter()
65            .map(|p| {
66                let is_valid = self.valid_source_dir(p)?;
67                Ok((p.clone(), is_valid))
68            })
69            .collect::<Result<Vec<_>, io::Error>>()?;
70
71        let validated: Vec<PathBuf> = validity_checked_paths
72            .iter()
73            .filter_map(|(source, valid)| if *valid { Some(source.clone()) } else { None })
74            .collect();
75
76        let invalidated: Vec<&PathBuf> = validity_checked_paths
77            .iter()
78            .filter_map(|(source, valid)| if *valid { None } else { Some(source) })
79            .collect();
80
81        let validated_string = list_dirs_to_string(&validated);
82        let invalidated_string = list_dirs_to_string(&invalidated);
83
84        if validated.is_empty() {
85            error!(
86                "Could not set source directories: All inputs are invalid:\n{invalidated_string}"
87            );
88        } else {
89            if !invalidated.is_empty() {
90                let confirm = ask!(
91                    true,
92                    "Invalid directories detected:\n{invalidated_string}\n\nWould you still like to set the valid source directories?:\n{validated_string}"
93                );
94
95                if !confirm.unwrap_or(false) {
96                    return Ok(self);
97                }
98            }
99
100            info!("Sucessfully set the source directories to:\n{validated_string}");
101            self.source_dirs = validated;
102        }
103
104        Ok(self)
105    }
106}