realia 0.2.0

Extra conditional compilation macros
Documentation
use anyhow::{anyhow, Error};

pub struct DepInfo {
    pub name: String,
    pub version: String,
    pub source: Option<String>,
}

pub fn get_deps(anchor_name: &str) -> Result<Vec<DepInfo>, Error> {
    let metadata = crate::metadata::get_metadata()?;

    let position = metadata
        .packages
        .iter()
        .position(|x| x.name == anchor_name)
        .ok_or_else(|| anyhow!("Cannot find metadata for the anchor package"))?;
    let anchor = &metadata.packages[position];

    // If we're in the middle of `cargo publish`, we need to delete the lock
    // file that was generated by the metadata command, or else Cargo will
    // complain about modifying things outside of OUT_DIR.
    let manifest_dir = crate::metadata::get_manifest_dir()?;
    let bad_file = format!(
        "{}/target/package/{}-{}/Cargo.lock",
        manifest_dir,
        anchor_name,
        anchor.version.to_string()
    );
    // If we can't remove, assume it doesn't exist.
    let _ = std::fs::remove_file(bad_file);

    let mut deps = vec![DepInfo {
        name: anchor.name.to_owned(),
        version: anchor.version.to_string(),
        source: match &anchor.source {
            Some(source) => Some(source.to_string()),
            None => None,
        },
    }];
    for dependency in &anchor.dependencies {
        let position = match metadata.packages.iter().position(|x| x.name == dependency.name) {
            Some(x) => x,
            _ => continue, // optional dep
        };
        let package = &metadata.packages[position];
        let applicable = match &dependency.target {
            Some(target) => {
                let default_target = crate::metadata::default_target()?;
                match target_spec::eval(&target.to_string(), &std::env::var("TARGET").unwrap_or(default_target)) {
                    Ok(Some(true)) => true,
                    _ => false,
                }
            }
            _ => true,
        };
        if !applicable {
            continue;
        }
        deps.push(DepInfo {
            name: dependency.name.clone(),
            version: package.version.to_string(),
            source: dependency.source.clone(),
        });
    }
    Ok(deps)
}

pub fn get_dep(anchor_name: &str, dep_name: &str) -> Result<DepInfo, Error> {
    for dep in get_deps(&anchor_name)? {
        if dep.name == dep_name {
            return Ok(dep);
        }
    }
    Err(anyhow!(
        "Unable to find information for dependency '{}' of '{}'",
        dep_name,
        anchor_name
    ))
}