entrust_core/
resolve.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use anyhow::anyhow;
use std::path;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub struct Locations {
    pub files: Vec<String>,
    pub dirs: Vec<String>,
}

pub fn get_existing_locations(base: &Path) -> anyhow::Result<Locations> {
    let walk_dir = WalkDir::new(base);
    let mut locations = Locations {
        files: Vec::with_capacity(16),
        dirs: Vec::with_capacity(16),
    };
    for entry in walk_dir {
        let entry = entry?;
        let mut path = pathdiff::diff_paths(entry.path(), base)
            .ok_or(anyhow!("Error resolving relative path"))?
            .into_os_string()
            .into_string()
            .map_err(|_| anyhow!("Encountered invalid UTF-8"))?;
        if path.starts_with('.') {
            continue;
        }
        if cfg!(windows) {
            path = path.replace(path::MAIN_SEPARATOR, "/")
        }
        if entry.path().is_dir() {
            if !path.is_empty() {
                let dir_path = format!("{path}/");
                if !locations.dirs.contains(&dir_path) {
                    locations.dirs.push(dir_path)
                }
            }
        } else {
            locations.files.push(path)
        }
    }
    Ok(locations)
}

pub fn resolve_existing_location(
    base: &Path,
    key: &str,
    can_be_dir: bool,
) -> anyhow::Result<PathBuf> {
    let concat = base.join(key);
    if can_be_dir {
        return if concat.exists() {
            Ok(concat)
        } else {
            Err(anyhow!("Key {key} does not exist"))
        };
    }
    if concat.is_file() {
        return Ok(concat);
    }
    if concat.is_dir() {
        let pass = concat.join("pass");
        return if pass.is_file() {
            Ok(pass)
        } else {
            Err(anyhow!("{key} is a directory"))
        };
    }
    let existing = get_existing_locations(base)?;
    let candidates: Vec<_> = existing
        .files
        .iter()
        .filter(|&s| s.starts_with(key))
        .collect();
    if candidates.len() == 1 {
        return Ok(base.join(candidates[0]));
    }
    Err(anyhow!("Key {key} does not exist"))
}

pub fn resolve_new_location(base: &Path, key: &str) -> anyhow::Result<PathBuf> {
    let file = base.join(key);
    if file.exists() {
        Err(anyhow!("Key {key} already exists"))
    } else {
        Ok(file)
    }
}