move_links/
paths.rs

1use path_clean::{self, PathClean};
2use std::path::{Path, PathBuf};
3use std::{env, fs, io};
4
5#[derive(PartialEq, Debug)]
6pub struct Paths {
7    pub links_dir: String,
8    pub src_path: String,
9    pub dest_path: String,
10}
11
12impl Paths {
13    pub fn new(links_dir_str: &str, src_path: &str, dest_path: &str) -> Result<Paths, String> {
14        let pb_links_dir = PathBuf::from(links_dir_str);
15        let pb_src_path = PathBuf::from(src_path);
16        let mut pb_dest_path = PathBuf::from(dest_path);
17
18        let pb_links_dir = match fs::canonicalize(&pb_links_dir) {
19            Ok(x) => x,
20            Err(_) => return Err(format!("links_dir: {:#?} is invalid", pb_links_dir)),
21        };
22
23        let pb_src_path = match fs::canonicalize(&pb_src_path) {
24            Ok(x) => x,
25            Err(_) => return Err(format!("src_path: {:#?} is invalid", pb_src_path)),
26        };
27
28        if pb_dest_path.is_relative() {
29            pb_dest_path = absolute_path(&pb_dest_path).unwrap();
30        }
31        if pb_dest_path.exists() {
32            if pb_dest_path.is_dir() {
33                pb_dest_path.push(pb_src_path.file_name().unwrap());
34            } else {
35                return Err(format!(
36                    "dest_path: {:#?} is invalid: a file with that name already exists",
37                    pb_dest_path
38                ));
39            }
40        } else {
41            let mut pb_tmp = pb_dest_path.clone();
42            pb_tmp.pop();
43            if !pb_tmp.exists() {
44                return Err(format!(
45                    "dest_path: {:#?} is invalid: path does not exist",
46                    pb_dest_path
47                ));
48            }
49        }
50        let links_dir = pb_links_dir.into_os_string().into_string().unwrap();
51        let src_path  = pb_src_path.into_os_string().into_string().unwrap();
52        let dest_path = pb_dest_path.into_os_string().into_string().unwrap();
53
54        Ok(Paths {
55            links_dir,
56            src_path,
57            dest_path,
58        })
59    }
60}
61
62fn absolute_path(path: impl AsRef<Path>) -> io::Result<PathBuf> {
63    let path = path.as_ref();
64    let absolute_path = if path.is_absolute() {
65        path.to_path_buf()
66    } else {
67        env::current_dir()?.join(path)
68    }
69    .clean();
70    Ok(absolute_path)
71}