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
#![feature(plugin_registrar, rustc_private)]
#[macro_use]
extern crate lazy_static;
extern crate rustc;
extern crate rustc_plugin;
extern crate syntax;
extern crate git2;
extern crate time;
use rustc_plugin::Registry;
use syntax::tokenstream::TokenTree;
use syntax::codemap::Span;
use syntax::symbol::Symbol;
use syntax::ext::base::{self, ExtCtxt, MacResult};
use syntax::ext::build::AstBuilder;
use git2::{Repository, DescribeOptions};
lazy_static! {
static ref METADATA: Metadata = Metadata::new();
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("commit", commit);
reg.register_macro("head", head);
reg.register_macro("time", current_time);
}
fn commit<'a>(cx: &'a mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'a> {
base::check_zero_tts(cx, sp, tts, "commit!");
let topmost = cx.expansion_cause().unwrap_or(sp);
base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&METADATA.commit_short)))
}
fn head<'a>(cx: &'a mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'a> {
base::check_zero_tts(cx, sp, tts, "head!");
let topmost = cx.expansion_cause().unwrap_or(sp);
base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&METADATA.head)))
}
fn current_time<'a>(cx: &'a mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'a> {
base::check_zero_tts(cx, sp, tts, "time!");
let topmost = cx.expansion_cause().unwrap_or(sp);
base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&METADATA.time)))
}
struct Metadata {
pub commit_short: String,
pub head: String,
pub time: String,
}
impl Metadata {
pub fn new() -> Metadata {
let repo = Repository::discover(".").expect("should find a repository");
let head = repo.head()
.expect("should find head")
.shorthand()
.expect("head name should be valid utf-8")
.to_string();
let desc = repo.describe(&DescribeOptions::new()
.describe_tags()
.show_commit_oid_as_fallback(true))
.expect("should get repository description");
let commit_oid = desc.format(None).unwrap_or(String::from("error"));
Metadata {
commit_short: commit_oid,
head: head,
time: time::now_utc().rfc3339().to_string(),
}
}
}