summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Tay <sam.chong.tay@gmail.com>2020-06-08 23:16:05 -0700
committerSam Tay <sam.chong.tay@gmail.com>2020-06-08 23:16:05 -0700
commit0056c5a93feabf96f432c5a50bd492742483acbd (patch)
tree2bf23190da8964c2a62f97ca05198c36cd491abc
parent546fc51006e2bcb9acf301a8c06a49a1d982bce1 (diff)
Clean up reading/writing to files
-rw-r--r--src/config.rs19
-rw-r--r--src/error.rs6
-rw-r--r--src/main.rs1
-rw-r--r--src/stackexchange.rs25
-rw-r--r--src/utils.rs24
5 files changed, 50 insertions, 25 deletions
diff --git a/src/config.rs b/src/config.rs
index 1d854b9..af51de3 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,10 +1,10 @@
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::fs;
-use std::fs::File;
use std::path::PathBuf;
-use crate::error::{Error, PermissionType, Result};
+use crate::error::{Error, Result};
+use crate::utils;
#[derive(Deserialize, Serialize, Debug)]
pub struct Config {
@@ -27,25 +27,22 @@ impl Default for Config {
pub fn user_config() -> Result<Config> {
let project = project_dir()?;
let dir = project.config_dir();
- fs::create_dir_all(&dir)
- .map_err(|_| Error::Permissions(PermissionType::Create, dir.to_path_buf()))?;
+ fs::create_dir_all(&dir)?;
let filename = config_file_name()?;
- match File::open(&filename) {
- Err(_) => {
+ match utils::open_file(&filename)? {
+ None => {
let def = Config::default();
write_config(&def)?;
Ok(def)
}
- Ok(file) => serde_yaml::from_reader(file).map_err(|_| Error::MalformedFile(filename)),
+ Some(file) => serde_yaml::from_reader(file).map_err(|_| Error::MalformedFile(filename)),
}
}
fn write_config(config: &Config) -> Result<()> {
let filename = config_file_name()?;
- let file = File::create(&filename)
- .map_err(|_| Error::Permissions(PermissionType::Create, filename.clone()))?;
- serde_yaml::to_writer(file, config)
- .map_err(|_| Error::Permissions(PermissionType::Write, filename.clone()))
+ let file = utils::create_file(&filename)?;
+ Ok(serde_yaml::to_writer(file, config)?)
}
fn config_file_name() -> Result<PathBuf> {
diff --git a/src/error.rs b/src/error.rs
index d125fb2..86fb55f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -10,6 +10,10 @@ pub enum Error {
Crossterm(#[from] crossterm::ErrorKind),
#[error("Reqwest error: {0}")]
Reqwest(#[from] reqwest::Error),
+ #[error("SerdeJson error: {0}")]
+ SerdeJson(#[from] serde_json::Error),
+ #[error("SerdeYaml error: {0}")]
+ SerdeYaml(#[from] serde_yaml::Error),
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[error("File `{}` is malformed; try removing it", .0.display())]
@@ -28,6 +32,6 @@ pub enum Error {
#[derive(Debug)]
pub enum PermissionType {
- Create,
+ Read,
Write,
}
diff --git a/src/main.rs b/src/main.rs
index 70ab6f4..7d1dd26 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@ mod config;
mod error;
mod stackexchange;
mod term;
+mod utils;
use crossterm::style::Color;
use error::Error;
diff --git a/src/stackexchange.rs b/src/stackexchange.rs
index dce05de..cf03399 100644
--- a/src/stackexchange.rs
+++ b/src/stackexchange.rs
@@ -4,11 +4,11 @@ use reqwest::Url;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
-use std::fs::File;
use std::path::PathBuf;
use crate::config::{project_dir, Config};
-use crate::error::{Error, PermissionType, Result};
+use crate::error::{Error, Result};
+use crate::utils;
/// StackExchange API v2.2 URL
const SE_API_URL: &str = "http://api.stackexchange.com";
@@ -131,8 +131,7 @@ impl LocalStorage {
pub fn new() -> Result<Self> {
let project = project_dir()?;
let dir = project.cache_dir();
- fs::create_dir_all(&dir)
- .map_err(|_| Error::Permissions(PermissionType::Create, dir.to_path_buf()))?;
+ fs::create_dir_all(&dir)?;
Ok(LocalStorage {
sites: None,
filename: dir.join("sites.json"),
@@ -164,12 +163,14 @@ impl LocalStorage {
}
fn fetch_local_sites(&mut self) -> Result<bool> {
- if let Ok(file) = File::open(&self.filename) {
- self.sites = serde_json::from_reader(file)
- .map_err(|_| Error::MalformedFile(self.filename.clone()))?;
- return Ok(true);
+ match utils::open_file(&self.filename)? {
+ Some(file) => {
+ self.sites = serde_json::from_reader(file)
+ .map_err(|_| Error::MalformedFile(self.filename.clone()))?;
+ Ok(true)
+ }
+ None => Ok(false),
}
- Ok(false)
}
// TODO decide whether or not I should give LocalStorage an api key..
@@ -195,10 +196,8 @@ impl LocalStorage {
}
fn store_local_sites(&self) -> Result<()> {
- let file = File::create(&self.filename)
- .map_err(|_| Error::Permissions(PermissionType::Create, self.filename.clone()))?;
- serde_json::to_writer(file, &self.sites)
- .map_err(|_| Error::Permissions(PermissionType::Write, self.filename.clone()))
+ let file = utils::create_file(&self.filename)?;
+ Ok(serde_json::to_writer(file, &self.sites)?)
}
}
diff --git a/src/utils.rs b/src/utils.rs
new file mode 100644
index 0000000..d1ffed8
--- /dev/null
+++ b/src/utils.rs
@@ -0,0 +1,24 @@
+use crate::error::{Error, PermissionType, Result};
+use std::fs::File;
+use std::io::ErrorKind;
+use std::path::PathBuf;
+
+pub fn open_file(filename: &PathBuf) -> Result<Option<File>> {
+ File::open(filename).map(Some).or_else(|e| match e {
+ e if e.kind() == ErrorKind::NotFound => Ok(None),
+ e if e.kind() == ErrorKind::PermissionDenied => {
+ Err(Error::Permissions(PermissionType::Read, filename.clone()))
+ }
+ e => Err(Error::from(e)),
+ })
+}
+
+pub fn create_file(filename: &PathBuf) -> Result<File> {
+ File::create(filename).map_err(|e| {
+ if e.kind() == ErrorKind::PermissionDenied {
+ Error::Permissions(PermissionType::Write, filename.clone())
+ } else {
+ Error::from(e)
+ }
+ })
+}