cargo-workspace2 0.2.2

A tool to query and manage complex cargo workspaces
Documentation
use crate::cargo::{CargoError, Dependency, Result};
use std::{fs::File, io::Read, path::PathBuf};
use toml_edit::{Document, Item, Value};

/// Parse the root entry of a cargo workspace into a document
pub(crate) fn parse_root_toml(p: PathBuf) -> Result<Document> {
    let mut buf = String::new();
    File::open(p)?.read_to_string(&mut buf)?;
    Ok(buf.parse::<Document>()?)
}

/// For a root-config, get the paths of member crates
pub(crate) fn get_members(doc: &Document) -> Result<Vec<String>> {
    match &doc["workspace"]["members"] {
        Item::Value(Value::Array(arr)) => Ok(arr
            .iter()
            .filter_map(|val| match val {
                Value::String(name) => Some(format!("{}", name)),
                val => {
                    eprintln!("Ignoring value `{:?}` in List of strings", val);
                    None
                }
            })
            .map(|s| s.replace("\"", "").trim().into())
            .map(|s: String| {
                if s.trim().starts_with("#") {
                    s.split("\n").map(ToString::to_string).collect()
                } else {
                    vec![s]
                }
            })
            // Holy shit this crate is useless! Why would it not just
            // strip the commented lines, instead of doing some
            // bullshit like this...
            .fold(vec![], |mut vec, ovec| {
                ovec.into_iter().for_each(|i| {
                    if !i.trim().starts_with("#") && i != "" {
                        vec.push(i.trim().to_string());
                    }
                });
                vec
            })),
        _ => Err(CargoError::NoWorkspace),
    }
}

/// Parse a member crate Cargo.toml file
pub(crate) fn parse_toml(p: PathBuf) -> Result<Document> {
    let mut buf = String::new();
    File::open(p)?.read_to_string(&mut buf)?;
    Ok(buf.parse::<Document>()?)
}

/// Parse a member crate set of dependencies
///
/// When a crate is not a table, it can't be a workspace member
/// dependency, so is skipped.
pub(crate) fn parse_dependencies(doc: &Document) -> Vec<Dependency> {
    match &doc["dependencies"] {
        Item::Table(ref t) => t
            .iter()
            .filter_map(|(n, v)| match v {
                Item::Value(Value::InlineTable(ref t)) => Dependency::parse(n.to_string(), t),
                _ => None,
            })
            .collect(),
        _ => vec![],
    }
}