mirror of
https://github.com/denisidoro/navi
synced 2024-11-26 05:20:21 +00:00
Add error info to filesystem operations.
This commit is contained in:
parent
ff264735b9
commit
a4e2311263
4 changed files with 77 additions and 53 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::structures::option::Config;
|
||||
use anyhow::Context;
|
||||
use anyhow::Error;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
|
@ -13,8 +14,12 @@ where
|
|||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
pub fn pathbuf_to_string(pathbuf: PathBuf) -> String {
|
||||
pathbuf.as_os_str().to_str().unwrap().to_string()
|
||||
pub fn pathbuf_to_string(pathbuf: PathBuf) -> Result<String, Error> {
|
||||
pathbuf
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("Invalid path {}", pathbuf.display()))
|
||||
.map(str::to_string)
|
||||
}
|
||||
|
||||
pub fn cheat_pathbuf() -> Result<PathBuf, Error> {
|
||||
|
@ -27,64 +32,75 @@ pub fn cheat_pathbuf() -> Result<PathBuf, Error> {
|
|||
.ok_or_else(|| anyhow!("Unable to acquire user data directory for cheatsheets."))
|
||||
}
|
||||
|
||||
fn follow_symlink(pathbuf: PathBuf) -> PathBuf {
|
||||
let other = fs::read_link(pathbuf.clone());
|
||||
match other {
|
||||
Ok(o) => {
|
||||
let o_str = o.as_os_str().to_str().unwrap();
|
||||
fn follow_symlink(pathbuf: PathBuf) -> Result<PathBuf, Error> {
|
||||
fs::read_link(pathbuf.clone())
|
||||
.map(|o| {
|
||||
let o_str = o
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("Invalid path {}", o.display()))?;
|
||||
if o_str.starts_with('.') {
|
||||
let parent_str = pathbuf.parent().unwrap().as_os_str().to_str().unwrap();
|
||||
let parent_str = pathbuf
|
||||
.parent()
|
||||
.ok_or_else(|| anyhow!("{} has no parent", pathbuf.display()))?
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("Parent of {} is an invalid path", pathbuf.display()))?;
|
||||
let path_str = format!("{}/{}", parent_str, o_str);
|
||||
let p = PathBuf::from(path_str);
|
||||
follow_symlink(p)
|
||||
} else {
|
||||
follow_symlink(o)
|
||||
}
|
||||
}
|
||||
Err(_) => pathbuf,
|
||||
}
|
||||
})
|
||||
.unwrap_or(Ok(pathbuf))
|
||||
}
|
||||
|
||||
fn exe_pathbuf() -> PathBuf {
|
||||
let pathbuf = std::env::current_exe().unwrap();
|
||||
fn exe_pathbuf() -> Result<PathBuf, Error> {
|
||||
let pathbuf = std::env::current_exe().context("Unable to acquire executable's path")?;
|
||||
follow_symlink(pathbuf)
|
||||
}
|
||||
|
||||
pub fn exe_string() -> String {
|
||||
pathbuf_to_string(exe_pathbuf())
|
||||
pub fn exe_string() -> Result<String, Error> {
|
||||
pathbuf_to_string(exe_pathbuf()?)
|
||||
}
|
||||
|
||||
fn cheat_paths_from_config_dir() -> String {
|
||||
let mut paths_str = String::from("");
|
||||
|
||||
if let Ok(f) = cheat_pathbuf() {
|
||||
if let Ok(paths) = fs::read_dir(pathbuf_to_string(f)) {
|
||||
for path in paths {
|
||||
paths_str.push_str(path.unwrap().path().into_os_string().to_str().unwrap());
|
||||
fn cheat_paths_from_config_dir() -> Result<String, Error> {
|
||||
cheat_pathbuf()
|
||||
.and_then(|f| fs::read_dir(pathbuf_to_string(f)?).context("Unable to read directory"))
|
||||
.and_then(|dir_entries| {
|
||||
let mut paths_str = String::from("");
|
||||
for entry in dir_entries {
|
||||
let path = entry.context("Unable to read directory")?;
|
||||
paths_str.push_str(
|
||||
path.path()
|
||||
.into_os_string()
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("Invalid path {}", path.path().display()))?,
|
||||
);
|
||||
paths_str.push_str(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
paths_str
|
||||
Ok(paths_str)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cheat_paths(config: &Config) -> String {
|
||||
pub fn cheat_paths(config: &Config) -> Result<String, Error> {
|
||||
config
|
||||
.path
|
||||
.clone()
|
||||
.unwrap_or_else(cheat_paths_from_config_dir)
|
||||
.ok_or_else(|| anyhow!("No cheat paths"))
|
||||
.or_else(|_| cheat_paths_from_config_dir().context("No cheat paths from config directory"))
|
||||
}
|
||||
|
||||
pub fn create_dir(path: &str) {
|
||||
fs::create_dir_all(path).unwrap_or(());
|
||||
pub fn create_dir(path: &str) -> Result<(), Error> {
|
||||
fs::create_dir_all(path).with_context(|| format!("Failed to create directory {}", path))
|
||||
}
|
||||
|
||||
pub fn remove_dir(path: &str) {
|
||||
fs::remove_dir_all(path).unwrap_or(());
|
||||
pub fn remove_dir(path: &str) -> Result<(), Error> {
|
||||
fs::remove_dir_all(path).with_context(|| format!("Failed to remove directory {}", path))
|
||||
}
|
||||
|
||||
pub fn tmp_path_str() -> String {
|
||||
let cheat_path_str = pathbuf_to_string(cheat_pathbuf().unwrap());
|
||||
format!("{}/tmp", cheat_path_str)
|
||||
pub fn tmp_path_str() -> Result<String, Error> {
|
||||
let cheat_path_str = pathbuf_to_string(cheat_pathbuf()?)?;
|
||||
Ok(format!("{}/tmp", cheat_path_str))
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@ pub enum Variant {
|
|||
Query(String),
|
||||
}
|
||||
|
||||
fn gen_core_fzf_opts(variant: Variant, config: &Config) -> FzfOpts {
|
||||
fn gen_core_fzf_opts(variant: Variant, config: &Config) -> Result<FzfOpts, Error> {
|
||||
let mut opts = FzfOpts {
|
||||
preview: if config.no_preview {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{} preview {{}}", filesystem::exe_string()))
|
||||
Some(format!("{} preview {{}}", filesystem::exe_string()?))
|
||||
},
|
||||
autoselect: !config.no_autoselect,
|
||||
overrides: config.fzf_overrides.clone(),
|
||||
|
@ -45,7 +45,7 @@ fn gen_core_fzf_opts(variant: Variant, config: &Config) -> FzfOpts {
|
|||
Variant::Query(q) => opts.query = Some(q),
|
||||
}
|
||||
|
||||
opts
|
||||
Ok(opts)
|
||||
}
|
||||
|
||||
fn extract_from_selections(raw_snippet: &str, contains_key: bool) -> (&str, &str, &str) {
|
||||
|
@ -172,9 +172,13 @@ fn with_new_lines(txt: String) -> String {
|
|||
pub fn main(variant: Variant, config: Config, contains_key: bool) -> Result<(), Error> {
|
||||
let _ = display::WIDTHS;
|
||||
|
||||
let opts = gen_core_fzf_opts(variant, &config);
|
||||
let (raw_selection, variables) =
|
||||
fzf::call(opts, |stdin| Some(parser::read_all(&config, stdin)));
|
||||
let opts = gen_core_fzf_opts(variant, &config).context("Failed to generate fzf options")?;
|
||||
let (raw_selection, variables) = fzf::call(opts, |stdin| {
|
||||
Some(
|
||||
parser::read_all(&config, stdin)
|
||||
.expect("Failed to read all variables intended for fzf"),
|
||||
)
|
||||
});
|
||||
|
||||
let (key, tags, snippet) = extract_from_selections(&raw_selection[..], contains_key);
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ use std::io::Write;
|
|||
use walkdir::WalkDir;
|
||||
|
||||
pub fn browse() -> Result<(), Error> {
|
||||
let repo_path_str = format!("{}/featured", filesystem::tmp_path_str());
|
||||
let repo_path_str = format!("{}/featured", filesystem::tmp_path_str()?);
|
||||
|
||||
filesystem::remove_dir(&repo_path_str);
|
||||
filesystem::create_dir(&repo_path_str);
|
||||
filesystem::remove_dir(&repo_path_str)?;
|
||||
filesystem::create_dir(&repo_path_str)?;
|
||||
|
||||
let repo_url = "https://github.com/denisidoro/cheats";
|
||||
Repository::clone(repo_url, &repo_path_str)
|
||||
|
@ -34,7 +34,7 @@ pub fn browse() -> Result<(), Error> {
|
|||
None
|
||||
});
|
||||
|
||||
filesystem::remove_dir(&repo_path_str);
|
||||
filesystem::remove_dir(&repo_path_str)?;
|
||||
|
||||
add(repo)
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ pub fn browse() -> Result<(), Error> {
|
|||
pub fn add(uri: String) -> Result<(), Error> {
|
||||
let (actual_uri, user, repo) = git::meta(uri.as_str());
|
||||
|
||||
let cheat_path_str = filesystem::pathbuf_to_string(filesystem::cheat_pathbuf()?);
|
||||
let tmp_path_str = filesystem::tmp_path_str();
|
||||
let cheat_path_str = filesystem::pathbuf_to_string(filesystem::cheat_pathbuf()?)?;
|
||||
let tmp_path_str = filesystem::tmp_path_str()?;
|
||||
let tmp_path_str_with_trailing_slash = format!("{}/", &tmp_path_str);
|
||||
|
||||
filesystem::remove_dir(&tmp_path_str);
|
||||
filesystem::create_dir(&tmp_path_str);
|
||||
filesystem::remove_dir(&tmp_path_str)?;
|
||||
filesystem::create_dir(&tmp_path_str)?;
|
||||
|
||||
eprintln!("Cloning {} into {}...\n", &actual_uri, &tmp_path_str);
|
||||
|
||||
|
@ -89,7 +89,7 @@ pub fn add(uri: String) -> Result<(), Error> {
|
|||
fs::copy(from, to)?;
|
||||
}
|
||||
|
||||
filesystem::remove_dir(&tmp_path_str);
|
||||
filesystem::remove_dir(&tmp_path_str)?;
|
||||
|
||||
eprintln!("The following .cheat files were imported successfully:\n{}\n\nThey are now located at {}\n\nPlease run navi again to check the results.", files, cheat_path_str);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::structures::fnv::HashLine;
|
|||
use crate::structures::fzf::{Opts as FzfOpts, SuggestionType};
|
||||
use crate::structures::option::Config;
|
||||
use crate::welcome;
|
||||
use anyhow::Error;
|
||||
use regex::Regex;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
|
@ -160,11 +161,14 @@ fn read_file(
|
|||
false
|
||||
}
|
||||
|
||||
pub fn read_all(config: &Config, stdin: &mut std::process::ChildStdin) -> VariableMap {
|
||||
pub fn read_all(
|
||||
config: &Config,
|
||||
stdin: &mut std::process::ChildStdin,
|
||||
) -> Result<VariableMap, Error> {
|
||||
let mut variables = VariableMap::new();
|
||||
let mut found_something = false;
|
||||
let mut visited_lines = HashSet::new();
|
||||
let paths = filesystem::cheat_paths(config);
|
||||
let paths = filesystem::cheat_paths(config)?;
|
||||
let folders = paths.split(':');
|
||||
|
||||
for folder in folders {
|
||||
|
@ -186,7 +190,7 @@ pub fn read_all(config: &Config, stdin: &mut std::process::ChildStdin) -> Variab
|
|||
welcome::cheatsheet(stdin);
|
||||
}
|
||||
|
||||
variables
|
||||
Ok(variables)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
Loading…
Reference in a new issue