workmn 0.0.5

Manages the lifecycle of projects on the local machine
Documentation
use super::project::RawProject;
use super::tag::RawTag;
use super::ConfLocation;
use config::{Config, ConfigError, Value};
use std::collections::HashMap;
use std::convert::TryFrom;

fn load_project(pair: (String, Value)) -> Result<RawProject, String> {
    let project_name = pair.0.clone();

    match RawProject::try_from(pair) {
        Ok(project) => Ok(project),
        Err(e) => Err(format!("unable to load project {}: {}", project_name, e)),
    }
}

fn load_tag(pair: (String, Value)) -> Result<RawTag, String> {
    let tag_name = pair.0.clone();

    match RawTag::try_from(pair) {
        Ok(tag) => Ok(tag),
        Err(e) => Err(format!("unable to load tag {}: {}", tag_name, e)),
    }
}

impl super::Conf {
    pub fn load<L>(location: &L) -> Result<Self, ConfigError>
    where
        L: ConfLocation,
    {
        let mut errors = Vec::new();
        let mut final_projects = HashMap::with_capacity(0); //raw_projects.len());
        let mut final_tags = HashMap::with_capacity(0); // raw_tags.len());

        let project_files: Vec<_> = location
            .project_files()
            .into_iter()
            .map(config::File::from)
            .collect();

        if !project_files.is_empty() {
            let raw_projects = Config::new().merge(project_files)?.get_table("projects")?;
            final_projects.reserve(raw_projects.len());

            for pair in raw_projects {
                match load_project(pair) {
                    Ok(proj) => {
                        final_projects.insert(proj.name.clone(), proj);
                    }
                    Err(msg) => {
                        errors.push(msg);
                    }
                }
            }
        } else {
            errors.push(String::from("no project files found"));
        }

        let tag_files: Vec<_> = location
            .tag_files()
            .into_iter()
            .map(config::File::from)
            .collect();

        if !tag_files.is_empty() {
            let raw_tags = config::Config::new().merge(tag_files)?.get_table("tags")?;
            final_tags.reserve(raw_tags.len());

            for pair in raw_tags {
                match load_tag(pair) {
                    Ok(tag) => {
                        final_tags.insert(tag.name.clone(), tag);
                    }
                    Err(msg) => {
                        errors.push(msg);
                    }
                }
            }
        } else {
            errors.push(String::from("no tag files found"));
        }

        Ok(Self {
            projects: final_projects,
            tags: final_tags,
            load_errors: errors,
        })
    }
}