-
Notifications
You must be signed in to change notification settings - Fork 2
/
build.rs
111 lines (87 loc) · 2.42 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
extern crate toml;
extern crate rustc_serialize;
use std::{env, io, fs, path};
use std::io::prelude::*;
use std::os::unix::fs::PermissionsExt;
fn main() {
copy_file().unwrap();
}
fn find_crate_root(p: &path::Path) -> io::Result<&path::Path> {
println!("looking for root in {:?}", p);
if p.join("Cargo.toml").exists() {
return Ok(p);
}
let parent = p.parent();
match parent {
Some(ref p) => return find_crate_root(p),
None => return Err(io::Error::new(io::ErrorKind::NotFound, "Crate root not found")),
}
}
fn copy_file() -> io::Result<()> {
let ref out = env::var("OUT_DIR").unwrap();
let p = path::Path::new(out);
let root = find_crate_root(&p)?;
let mut f = fs::File::open(root.join("Cargo.toml"))?;
let mut s = String::new();
f.read_to_string(&mut s)?;
let contents = build_script(s);
let hooks_dir = root.join(".git")
.join("hooks");
println!("Hooks dir {:?}", hooks_dir);
if !hooks_dir.exists() {
return Ok(());
}
let pre_commit = hooks_dir.join("pre-commit");
let mut f = fs::File::create(&pre_commit)?;
if cfg!(target_family = "unix") {
let metadata = f.metadata()?;
let mut permissions = metadata.permissions();
permissions.set_mode(0o777);
fs::set_permissions(&pre_commit, permissions)?;
}
f.write_all(contents.as_bytes())
}
fn build_script(s: String) -> String {
let t = toml::Parser::new(&s).parse();
let checks = t.as_ref()
.and_then(|x| get_as_table("package", x))
.and_then(|x| get_as_table("metadata", x))
.and_then(|x| get_as_table("precommit", x))
.iter()
.flat_map(|xs| xs.iter())
.map(format_test)
.collect::<Vec<_>>()
.join("\n");
format_script(checks)
}
fn get_as_table<'a>(name: &str, x: &'a toml::Table) -> Option<&'a toml::Table> {
x.get(name)
.and_then(toml::Value::as_table)
}
fn format_script(s: String) -> String {
format!(r#"
#!/bin/bash
set -eu
check_char='\xE2\x9C\x93'
cross_char='\xE2\x9C\x96'
green='\033[0;32m'
red='\033[0;31m'
nc='\033[0m'
check="$green$check_char$nc"
cross="$red$cross_char$nc"
{}"#,
s)
}
fn format_test((k, v): (&String, &toml::Value)) -> String {
format!(r#"printf "{}"
if result=$({}); then
echo " $check"
else
echo " $cross"
echo " $result"
exit 1
fi
"#,
k,
v.as_str().unwrap())
}