dredd-hooks 0.3.0

Dredd HTTP API testing integration for Rust
Documentation
#[macro_use] extern crate serde_derive;
extern crate cargo_edit;
extern crate cargo;
extern crate docopt;

use std::process::Command;
use std::os::unix::process::CommandExt;

use cargo_edit::Manifest;
use cargo::core::shell::Verbosity;
use cargo::core::Workspace;
use cargo::ops::{compile, CompileOptions, CompileMode, CompileFilter};
use cargo::util::config::Config;
use docopt::Docopt;

const USAGE: &'static str = "
cargo-dredd

Usage:
  cargo dredd <blueprint> <server-url> [options]

Options:
  --language=<rust>  The language flag that will be passed to dredd [default: rust].
";

#[derive(Debug, Deserialize)]
struct Args {
    arg_blueprint: String,
    arg_server_url: String,
    flag_language: Option<String>,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.deserialize())
                            .unwrap_or_else(|e| e.exit());

    let hook_binaries = cargo_compile();

    let mut cmd = Command::new("dredd");
    cmd.args(&[args.arg_blueprint, args.arg_server_url]);
    cmd.arg(format!("--language={}", args.flag_language.unwrap_or("rust".to_owned()).to_owned()));
    for binary in hook_binaries {
        cmd.args(&[format!("--hookfiles={}", binary)]);
    }

    cmd.exec();
}

fn cargo_compile() -> Vec<String> {
    let mut manifest = Manifest::open(&None).unwrap();
    let config = manifest.get_table(&[
        "package".to_owned(),
        "metadata".to_owned(),
        "dredd_hooks".to_owned()]
    ).expect("No [package.metadata.dredd_hooks] value found in Cargo.toml");
    if config.is_empty() {
        panic!("No [package.metadata.dredd_hooks] value found in Cargo.toml");
    }

    let hook_targets: Vec<String> = config.get("hook_targets")
                             .expect("No `hook_targets` value found.")
                             .as_array()
                             .expect("`hook_targets` is not an array.")
                             .iter()
                             .filter(|n| n.is_str())
                             .map(|n| n.as_str().unwrap().to_owned())
                             .collect();

    let config = Config::default().unwrap();
    config.shell().set_verbosity(Verbosity::Normal);
    let manifest_path = config.cwd().join("Cargo.toml");
    let workspace = Workspace::new(&manifest_path, &config).unwrap();
    let mut compile_config = CompileOptions::default(&config, CompileMode::Test);
    compile_config.filter = CompileFilter::new(false, &[],
                                               false, &hook_targets,
                                               false, &[],
                                               false, &[],
                                               false);

    let res = compile(&workspace, &compile_config).unwrap();
    res.tests.iter().map(|n| n.3.to_str().unwrap().to_owned()).collect()
}