vade-cli 0.1.1

A command-line tool to deploy applications on Linux servers
use miette::{LabeledSpan, Report, SourceCode, miette};
use std::ops::Deref;
use std::path::{Path, PathBuf};
use toml_span::Span;

pub struct RelativePathResolver {
    root: PathBuf,
}

impl RelativePathResolver {
    pub fn with_root(root: PathBuf) -> Self {
        Self { root }
    }

    pub fn resolve(&self, path: &Path) -> ResolvedPath {
        let resolved = if path.is_absolute() {
            path.to_owned()
        } else {
            self.root.join(path)
        };

        ResolvedPath { inner: resolved }
    }
}

pub struct ResolvedPath {
    inner: PathBuf,
}

#[cfg(test)]
impl ResolvedPath {
    pub fn from_str(s: &str) -> Self {
        Self {
            inner: PathBuf::from(s),
        }
    }
}

impl Deref for ResolvedPath {
    type Target = Path;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

pub fn labeled_span(message: String, span: Span) -> LabeledSpan {
    LabeledSpan::new_with_span(Some(message), span.start..span.end)
}

pub fn diagnostic<S: SourceCode + 'static>(
    error: &str,
    details: String,
    span: Span,
    source: S,
) -> Report {
    let labels = vec![labeled_span(details, span)];
    miette!(labels = labels, "{error}").with_source_code(source)
}

pub fn diagnostic_with_help<S: SourceCode + 'static>(
    error: &str,
    details: String,
    help: String,
    span: Span,
    source: S,
) -> Report {
    let labels = vec![labeled_span(details, span)];
    miette!(labels = labels, help = help, "{error}").with_source_code(source)
}

#[cfg(test)]
mod tests {
    use super::*;

    fn test_path_resolver(root: &str, path: &str, expected: &str) {
        let resolver = RelativePathResolver::with_root(PathBuf::from(root));
        let resolved = resolver.resolve(Path::new(path));
        assert_eq!(&*resolved, Path::new(expected));
    }

    #[test]
    fn test_path_resolver_absolute() {
        test_path_resolver("/home/johndoe", "/opt/some-path", "/opt/some-path");
    }

    #[test]
    fn test_path_resolver_relative() {
        test_path_resolver("/home/johndoe", "some-path", "/home/johndoe/some-path");
    }
}