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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub mod dirs;
pub mod errors;
pub mod profile;

use std::{fs::create_dir_all, path::PathBuf};
use dirs::{path_dir_storage, path_file_credentials};
pub use errors::{Error, ErrorStorage, Success};
pub use profile::Profile;


pub fn ensure_storage() -> Result<PathBuf, ErrorStorage> {
    let path_dir = path_dir_storage().ok_or(ErrorStorage::NoPath)?;

    if path_dir.exists() {
        if path_dir.is_dir() {
            Ok(path_dir)
        } else {
            Err(ErrorStorage::NotDir)
        }
    } else {
        match create_dir_all(&path_dir) {
            Ok(()) => Ok(path_dir),
            Err(e) => Err(ErrorStorage::CannotCreate(e)),
        }
    }
}


pub fn profile_clear() -> Result<Success, Error> {
    match path_file_credentials() {
        Some(path_cred) => match std::fs::remove_file(path_cred) {
            Ok(()) => Ok(Success::Cleared),
            Err(e) => Err(Error::CredentialsCannotRemove(e)),
        }
        None => Err(Error::CredentialsNoPath),
    }
}


pub fn profile_list() -> Result<Success, Error> {
    let dir_profile = ensure_storage()?;
    let mut profiles = Vec::new();

    if let Ok(dir) = dir_profile.read_dir() {
        for entry in dir {
            if let Ok(sub) = entry {
                if let Some(profile) = Profile::from_path(sub.path()) {
                    profiles.push(profile);
                }
            }
        }
    }

    Ok(Success::List(profiles))
}


pub fn profile_save(name: String, clobber: bool) -> Result<Success, Error> {
    let mut path_dst = ensure_storage()?;
    let profile = Profile::new(name);
    path_dst.push(profile.filename());

    if !clobber && path_dst.exists() {
        Err(Error::ProfileExists(profile))
    } else {
        match path_file_credentials() {
            Some(path) if !path.is_file() => Err(Error::CredentialsNotFound),

            Some(path_src) => match std::fs::copy(path_src, &path_dst) {
                Ok(..) => Ok(Success::Saved(profile)),
                Err(e) => Err(Error::CannotSave(profile, e)),
            }

            None => Err(Error::CredentialsNoPath),
        }
    }
}


pub fn profile_load(name: String) -> Result<Success, Error> {
    let mut path_src = ensure_storage()?;
    let profile = Profile::new(name);
    path_src.push(profile.filename());

    match path_file_credentials() {
        Some(path_dst) => match std::fs::copy(path_src, &path_dst) {
            Ok(..) => Ok(Success::Loaded(profile)),
            Err(e) => Err(Error::CannotLoad(profile, e)),
        }
        None => Err(Error::CredentialsNoPath),
    }
}


pub fn profile_remove(names: Vec<String>) -> Result<Success, Error> {
    let dir_profile = ensure_storage()?;
    let mut vec_del = Vec::with_capacity(names.len());
    let mut vec_err = Vec::with_capacity(names.len());

    for name in names {
        let profile = Profile::new(name);

        let mut path = dir_profile.clone();
        path.push(profile.filename());

        if path.is_file() {
            match std::fs::remove_file(&path) {
                Ok(()) => vec_del.push(profile),
                Err(e) => vec_err.push(Error::ProfileCannotRemove(profile, e)),
            }
        } else {
            vec_err.push(Error::ProfileNotFound(profile));
        }
    }

    Ok(Success::Removed { removed: vec_del, errors: vec_err })
}