hdf5-bitshuffle 0.1.1

HDF5 bitshuffle plugin for Rust
use git2::{Oid, Repository};
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{env, fs};

static CMAKE_SEPARATOR: &[u8] = b"\n";

fn main() {
    let out = PathBuf::from(env::var("OUT_DIR").unwrap());
    let (hdf5_src_path, cmake_file) = search_hdf5_source(out.clone());
    let path = out.clone().join("bitshuffle");
    clone_repo(&path);
    compile(&path, hdf5_src_path, cmake_file);
}

fn clone_repo<P: AsRef<Path>>(path: P) {
    let url = "https://github.com/kiyo-masui/bitshuffle";
    let tag = "02259e2b37bb0796ece84a553efb7d01a0697014";
    let repo = match Repository::open(&path) {
        Ok(repo) => repo,
        Err(_) => match Repository::clone(url, &path) {
            Ok(repo) => repo,
            Err(err) => panic!("Failed to clone bittshuffle repo: {}", err),
        },
    };
    let oid = Oid::from_str(tag).unwrap();
    let commit = repo.find_commit(oid).unwrap();
    let _branch = repo.branch(tag, &commit, false);
    let obj = repo
        .revparse_single(&("refs/heads/".to_owned() + tag))
        .unwrap();
    repo.checkout_tree(&obj, None).unwrap();
    repo.set_head(&("refs/heads/".to_owned() + tag)).unwrap();
}

fn compile(path: &PathBuf, hdf5: PathBuf, mut cmake_file: File) {
    let src = {
        let src = [
            "lz4/lz4.c",
            "src/bitshuffle.c",
            "src/bitshuffle_core.c",
            "src/bshuf_h5filter.c",
            "src/bshuf_h5plugin.c",
            "src/iochain.c",
        ];
        let mut full = vec![];
        for s in &src {
            let path = path.clone().join(s);
            full.push(path);
        }
        full
    };
    let hdf5_include = hdf5.clone().join("include");
    let lz4_include = path.clone().join("lz4");
    cmake_file
        .write_all(lz4_include.to_str().unwrap().as_bytes())
        .unwrap();
    cmake_file.write_all(CMAKE_SEPARATOR).unwrap();
    let src_include = path.clone().join("src");
    cmake_file
        .write_all(src_include.to_str().unwrap().as_bytes())
        .unwrap();
    cc::Build::new()
        .files(src.iter())
        .flag("-w")
        .include(hdf5_include)
        .include(lz4_include)
        .include(src_include)
        .compile("bitshuffle");
}

fn search_hdf5_source(path: PathBuf) -> (PathBuf, File) {
    let path = PathBuf::from(path.parent().unwrap().parent().unwrap());
    let paths = fs::read_dir(&path).unwrap();
    for dir in paths {
        let dir = dir.unwrap();
        let md = dir.metadata().unwrap();
        if !md.is_dir() {
            continue;
        }
        if !dir.path().to_str().unwrap().contains("hdf5-src") {
            continue;
        }
        let out = dir.path().join("out");
        if !out.exists() {
            continue;
        }
        let lib = out.clone().join("lib");
        if !lib.exists() {
            continue;
        }
        let mut file =
            File::create(path.clone().parent().unwrap().join("cmake_cryiorust_hdf5")).unwrap();
        file.write_all(out.clone().join("include").to_str().unwrap().as_bytes())
            .unwrap();
        file.write_all(CMAKE_SEPARATOR).unwrap();
        return (out, file);
    }
    panic!("Cannot find hdf5-src build dir");
}