blob: 32c8b1e721c02bbf53241dae8549265e750f0bab (
plain)
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
|
use crate::prelude::*;
use remove_dir_all::remove_dir_all;
use std::ffi::OsStr;
use std::fs::{self, create_dir_all, File};
use std::io;
use thiserror::Error;
pub trait ToStringExt {
fn to_string(&self) -> String;
}
impl ToStringExt for Path {
fn to_string(&self) -> String {
self.to_string_lossy().to_string()
}
}
impl ToStringExt for OsStr {
fn to_string(&self) -> String {
self.to_string_lossy().to_string()
}
}
#[derive(Error, Debug)]
#[error("Invalid path `{0}`")]
pub struct InvalidPath(pub PathBuf);
#[derive(Error, Debug)]
#[error("Unable to read directory `{dir}`")]
pub struct UnreadableDir {
dir: PathBuf,
#[source]
source: anyhow::Error,
}
pub fn open(filename: &Path) -> Result<File> {
File::open(filename).with_context(|| {
let x = filename.to_string();
format!("Failed to open file {}", &x)
})
}
pub fn read_lines(filename: &Path) -> Result<impl Iterator<Item = Result<String>>> {
let file = open(filename)?;
Ok(io::BufReader::new(file)
.lines()
.map(|line| line.map_err(Error::from)))
}
pub fn pathbuf_to_string(pathbuf: &Path) -> Result<String> {
Ok(pathbuf
.as_os_str()
.to_str()
.ok_or_else(|| InvalidPath(pathbuf.to_path_buf()))
.map(str::to_string)?)
}
fn follow_symlink(pathbuf: PathBuf) -> Result<PathBuf> {
fs::read_link(pathbuf.clone())
.map(|o| {
let o_str = o
.as_os_str()
.to_str()
.ok_or_else(|| InvalidPath(o.to_path_buf()))?;
if o_str.starts_with('.') {
let p = pathbuf
.parent()
.ok_or_else(|| anyhow!("`{}` has no parent", pathbuf.display()))?;
let mut p = PathBuf::from(p);
p.push(o_str);
follow_symlink(p)
} else {
follow_symlink(o)
}
})
.unwrap_or(Ok(pathbuf))
}
fn exe_pathbuf() -> Result<PathBuf> {
let pathbuf = std::env::current_exe().context("Unable to acquire executable's path")?;
follow_symlink(pathbuf)
}
fn exe_abs_string() -> Result<String> {
pathbuf_to_string(&exe_pathbuf()?)
}
pub fn exe_string() -> String {
exe_abs_string().unwrap_or_else(|_| "navi".to_string())
}
pub fn create_dir(path: &Path) -> Result<()> {
create_dir_all(path).with_context(|| {
format!(
"Failed to create directory `{}`",
pathbuf_to_string(path).expect("Unable to parse {path}")
)
})
}
pub fn remove_dir(path: &Path) -> Result<()> {
remove_dir_all(path).with_context(|| {
format!(
"Failed to remove directory `{}`",
pathbuf_to_string(path).expect("Unable to parse {path}")
)
})
}
|