glv 3.0.5

Git log viewer supporting un/folding merges
use std::path::{Path, PathBuf};

use url::Url;

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("Provided absolute path {0}")]
    AbsolutePath(PathBuf),
    #[error("Url has no domain")]
    NoDomain(Url),
    #[error("Failed to find application cache_path")]
    CacheFailure,
    #[error(transparent)]
    Io(#[from] std::io::Error),
}

fn store(path: PathBuf, body: &str) -> Result<(), Error> {
    if !path.is_relative() {
        return Err(Error::AbsolutePath(path));
    }

    if let Some(proj_dirs) = directories::ProjectDirs::from("", "", "glv") {
        let cache_path = proj_dirs.cache_dir().join(path);
        std::fs::create_dir_all(cache_path.parent().expect("Parent directory"))?;
        Ok(std::fs::write(cache_path, body)?)
    } else {
        Err(Error::CacheFailure)
    }
}

fn fetch(path: PathBuf) -> Result<Option<String>, Error> {
    if !path.is_relative() {
        return Err(Error::AbsolutePath(path));
    }

    let proj_dirs = directories::ProjectDirs::from("", "", "glv").expect("");
    let cache_path = proj_dirs.cache_dir().join(path);
    if cache_path.exists() {
        Ok(Some(std::fs::read_to_string(cache_path)?))
    } else {
        Ok(None)
    }
}

fn path_from_url(url: &Url) -> Result<PathBuf, Error> {
    let domain = url.domain().ok_or_else(|| Error::NoDomain(url.clone()))?;
    let path = format!("{}{}", domain, url.path());
    Ok(Path::new(&path).to_path_buf())
}

#[test]
fn test_path_from_url() {
    use pretty_assertions::assert_eq;
    let url = Url::parse("https://github.com/kalkin/bar").unwrap();
    let result = path_from_url(&url).unwrap();
    let actual = result.to_str().unwrap();
    let expected = "github.com/kalkin/bar";
    assert_eq!(expected, actual);
}

pub fn store_api_response(url: &Url, id: &str, body: &str) -> Result<(), Error> {
    let path = path_from_url(url)?.join(id);
    store(path, body)
}

pub fn fetch_api_response(url: &Url, id: &str) -> Result<Option<String>, Error> {
    let path = path_from_url(url)?.join(id);
    fetch(path)
}