scaffold 0.5.1

Quickly add dependencies to your Rust project.
Documentation
use arguments::Arguments;
use arguments::Subcommand;
use scaffold::add_groups;
use scaffold::group_reader::Dependency;
use scaffold::{
    default_toml::DEFAULT_TOML,
    error::Error,
    group_reader::get_groups,
    toml_editor::{read_toml_file, write_toml_file},
    version_getter::VersionGetter,
};
use std::collections::HashMap;
use std::path::PathBuf;
use std::{
    fs::{create_dir_all, OpenOptions},
    io::Write,
    process::exit,
};
use structopt::StructOpt;

mod arguments;

fn main() {
    let arguments: Arguments = Arguments::from_args();

    let groups_path = arguments.get_groups_path();

    if let Err(error) = ensure_groups_exist(&groups_path, arguments.verbose) {
        eprintln!("Failed to create default scaffolding: {}", error);
        exit(1);
    }

    let groups = match get_groups(&groups_path) {
        Ok(groups) => groups,
        Err(error) => {
            eprintln!("Failed to read groups: {}", error);
            exit(1);
        }
    };

    match &arguments.subcommand {
        Subcommand::List => {
            list_groups(&groups, arguments.use_tilde_version);
        }
        Subcommand::Add { group_names } => {
            let mut toml = match read_toml_file(&arguments.get_toml_path()) {
                Ok(toml) => toml,
                Err(_) => {
                    eprintln!(
                        "Could not read TOML file at the specified path: {:?}.",
                        &arguments.get_toml_path()
                    );
                    exit(1);
                }
            };

            if let Err(error) = add_groups(
                &mut toml,
                &groups,
                group_names,
                arguments.ask,
                arguments.verbose,
                arguments.use_tilde_version,
            ) {
                eprintln!("Could not add specified groups: {}", error);
                exit(1);
            }

            toml.sort_dependencies();
            if let Err(error) = write_toml_file(&arguments.get_toml_path(), &toml) {
                eprintln!("Could not write TOML file: {}", error);
                exit(1);
            }
        }
    }
}

fn list_groups(groups: &HashMap<String, Vec<Dependency>>, use_tilde_version: bool) {
    let mut version_getter = VersionGetter::default();

    for (name, dependencies) in groups {
        println!("{}", name);

        for dependency in dependencies {
            println!(
                "    {}",
                dependency.get_pretty_string(&mut version_getter, use_tilde_version)
            );
        }
    }
}

fn ensure_groups_exist(groups_path: &PathBuf, verbose: bool) -> Result<(), Error> {
    if groups_path.exists() {
        return Ok(());
    }

    match groups_path.parent() {
        None => {}
        Some(parent) => {
            if let Err(error) = create_dir_all(parent) {
                eprintln!("Failed to create default path: {}", error);
                exit(1);
            };
        }
    }

    match OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&groups_path)
    {
        Ok(mut file) => match file.write_all(DEFAULT_TOML) {
            Ok(_) => {
                if verbose {
                    println!("Wrote default groups to {:?}.", &groups_path);
                }
                Ok(())
            }
            Err(error) => Err(Error::Io(error)),
        },
        Err(error) => Err(Error::Io(error)),
    }
}