git 0.0.12

The library provides basic operations with Git repositories.
#![feature(macro_rules)]

macro_rules! cmd(
    ($name:expr) => (::std::io::process::Command::new($name));
);

macro_rules! fmt(
    ($($arg:tt)*) => (format!($($arg)*).as_slice());
);

macro_rules! get(
    ($name:expr) => (::std::os::getenv($name).unwrap());
);

macro_rules! run(
    ($command:expr) => (
        assert!($command.stdout(::std::io::process::InheritFd(1))
                        .stderr(::std::io::process::InheritFd(2))
                        .status().unwrap().success());
    );
);

macro_rules! link(
    ($name:expr) => (println!("cargo:rustc-flags=-l {}", $name));
);

macro_rules! look(
    ($path:expr) => (println!("cargo:rustc-flags=-L {}", $path));
);

fn main() {
    let ssh = require("libssh2", None);
    require("openssl", Some("-lssl -lcrypto"));
    require("zlib", Some("-lz"));

    if get!("TARGET").contains("apple") {
       link!("iconv");
    }

    let root = Path::new(get!("CARGO_MANIFEST_DIR"));
    let from = root.join_many(&["build", "libgit2"]);
    let into = Path::new(get!("OUT_DIR"));

    run!(cmd!("cmake").cwd(&into)
                      .arg(&from)
                      .arg("-DBUILD_CLAR=OFF")
                      .arg("-DBUILD_EXAMPLES=OFF")
                      .arg("-DBUILD_SHARED_LIBS=OFF")
                      .arg("-DCMAKE_C_FLAGS=-fPIC")
                      .arg("-DTHREADSAFE=ON")
                      .arg(fmt!("-DCMAKE_MODULE_PATH={}",
                                root.join_many(&["build", "cmake"]).display()))
                      .arg(fmt!("-DUSE_SSH={}",
                                if ssh { "ON" } else { "OFF" })));

    run!(cmd!("make").cwd(&into).arg(fmt!("-j{}", get!("NUM_JOBS"))));

    look!(into.display());
    link!("git2:static");
}

fn require(name: &str, fallback: Option<&str>) -> bool {
    macro_rules! rescue(
        ($fallback:expr) => ({
            match $fallback {
                Some(output) => interpret(output),
                None => {},
            }
            return false;
        });
    );

    let result = match cmd!("pkg-config").arg("--libs").arg(name).output() {
        Ok(result) => result,
        Err(_) => rescue!(fallback),
    };

    if !result.status.success() {
        rescue!(fallback);
    }

    interpret(std::str::from_utf8(result.output.as_slice()).unwrap());

    true
}

fn interpret(output: &str) {
    for chunk in output.split(' ') {
        if chunk.starts_with("-l") {
            link!(chunk.slice_from(2));
        } else if chunk.starts_with("-L") {
            look!(chunk.slice_from(2));
        }
    }
}