use anyhow::{Context, Result};
use std::fs;
use std::path::PathBuf;
use super::Credential;
pub struct FileStore {
path: PathBuf,
}
impl FileStore {
pub fn new() -> Result<Self> {
let config_dir = dirs::config_dir()
.context("Could not determine config directory")?
.join("bitbucket");
fs::create_dir_all(&config_dir).context("Failed to create config directory")?;
let path = config_dir.join("credentials.json");
Ok(Self { path })
}
pub fn store_credential(&self, credential: &Credential) -> Result<()> {
let json =
serde_json::to_string_pretty(credential).context("Failed to serialize credential")?;
#[cfg(unix)]
{
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.mode(0o600)
.open(&self.path)
.and_then(|mut file| {
use std::io::Write;
file.write_all(json.as_bytes())
})
.context("Failed to write credential file")?;
}
#[cfg(not(unix))]
{
fs::write(&self.path, json).context("Failed to write credential file")?;
}
Ok(())
}
pub fn get_credential(&self) -> Result<Option<Credential>> {
if !self.path.exists() {
return Ok(None);
}
let json = fs::read_to_string(&self.path).context("Failed to read credential file")?;
let credential: Credential =
serde_json::from_str(&json).context("Failed to parse stored credential")?;
Ok(Some(credential))
}
pub fn delete_credential(&self) -> Result<()> {
if self.path.exists() {
fs::remove_file(&self.path).context("Failed to delete credential file")?;
}
Ok(())
}
}