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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
use std::{
collections::VecDeque,
path::{Component, Path, PathBuf},
};
use crate::{
dotup::{self, Dotup},
Flags,
};
pub const DEFAULT_DEPOT_FILE_NAME: &str = ".depot";
/// Returns a list of canonical paths to all the files in `dir`. This includes files in
/// subdirectories.
/// Fails if dir isnt a directory or if there is some other io error.
pub fn collect_files_in_dir_recursive(dir: impl Into<PathBuf>) -> anyhow::Result<Vec<PathBuf>> {
let mut paths = Vec::new();
let mut dirs = VecDeque::new();
dirs.push_back(dir.into());
while let Some(dir) = dirs.pop_front() {
for entry in std::fs::read_dir(dir)? {
let entry = entry?;
let filetype = entry.file_type()?;
if filetype.is_dir() {
dirs.push_back(entry.path());
} else {
paths.push(entry.path());
}
}
}
Ok(paths)
}
pub fn collect_paths_in_dir(dir: impl AsRef<Path>) -> anyhow::Result<Vec<PathBuf>> {
Ok(std::fs::read_dir(dir)?
.filter_map(|e| e.ok())
.map(|e| e.path())
.collect())
}
pub fn read_dotup(flags: &Flags) -> anyhow::Result<Dotup> {
let depot_path = depot_path_from_flags(flags)?;
let install_base = install_base_from_flags(flags);
dotup::read(depot_path, install_base)
}
pub fn write_dotup(dotup: &Dotup) -> anyhow::Result<()> {
dotup::write(dotup)
}
pub fn depot_path_from_flags(flags: &Flags) -> anyhow::Result<PathBuf> {
match flags.depot {
Some(ref path) => Ok(path.clone()),
None => find_depot_path().ok_or_else(|| anyhow::anyhow!("Failed to find depot path")),
}
}
pub fn default_depot_path() -> PathBuf {
current_working_directory().join(DEFAULT_DEPOT_FILE_NAME)
}
pub fn find_depot_path() -> Option<PathBuf> {
let mut cwd = current_working_directory();
loop {
let path = cwd.join(DEFAULT_DEPOT_FILE_NAME);
if path.exists() {
break Some(path);
}
if !cwd.pop() {
break None;
}
}
}
pub fn install_base_from_flags(flags: &Flags) -> PathBuf {
match flags.install_base {
Some(ref path) => path.clone(),
None => default_install_base(),
}
}
pub fn default_install_base() -> PathBuf {
PathBuf::from(std::env::var("HOME").expect("Failed to obtain HOME environment variable"))
}
pub fn weakly_canonical(path: impl AsRef<Path>) -> PathBuf {
let cwd = current_working_directory();
weakly_canonical_cwd(path, cwd)
}
fn weakly_canonical_cwd(path: impl AsRef<Path>, cwd: PathBuf) -> PathBuf {
// Adapated from
// https://github.com/rust-lang/cargo/blob/fede83ccf973457de319ba6fa0e36ead454d2e20/src/cargo/util/paths.rs#L61
let path = path.as_ref();
let mut components = path.components().peekable();
let mut canonical = cwd;
let prefix = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
PathBuf::from(c.as_os_str())
} else {
PathBuf::new()
};
for component in components {
match component {
Component::Prefix(_) => unreachable!(),
Component::RootDir => {
canonical = prefix.clone();
canonical.push(component.as_os_str())
}
Component::CurDir => {}
Component::ParentDir => {
canonical.pop();
}
Component::Normal(p) => canonical.push(p),
};
}
canonical
}
pub fn current_working_directory() -> PathBuf {
std::env::current_dir().expect("Failed to obtain current working directory")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn weak_canonical_test() {
let cwd = PathBuf::from("/home/user");
assert_eq!(
PathBuf::from("/home/dest"),
weakly_canonical_cwd("../dest", cwd.clone())
);
assert_eq!(
PathBuf::from("/home/dest/configs/init.vim"),
weakly_canonical_cwd("../dest/configs/init.vim", cwd.clone())
);
assert_eq!(
PathBuf::from("/dest/configs/init.vim"),
weakly_canonical_cwd("/dest/configs/init.vim", cwd.clone())
);
assert_eq!(
PathBuf::from("/home/user/configs/nvim/lua/setup.lua"),
weakly_canonical_cwd("./configs/nvim/lua/setup.lua", cwd.clone())
);
assert_eq!(
PathBuf::from("/home/user/configs/nvim/lua/setup.lua"),
weakly_canonical_cwd("configs/nvim/lua/setup.lua", cwd)
);
}
}
|