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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use chrono::TimeZone;
use git2::{Commit, ObjectType, Repository};
use std::{env, fs, path};
pub fn get_info() {
let mut commit_id = "UNKNOWN".into();
let mut commit_date = chrono::Utc::now().format("%Y-%m-%d").to_string();
let crate_dir =
path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
let mut repo_dir = crate_dir.clone();
let repo = Repository::open(&repo_dir).or_else(move |_| {
repo_dir.pop();
Repository::open(&repo_dir)
});
let mut release_file = crate_dir.clone();
release_file.push("release.txt");
if let Ok(repo) = repo {
let commit = find_last_commit(&repo).expect("Couldn't find last commit");
commit_id = oid_to_short_sha(commit.id());
let timestamp = commit.time().seconds();
let dt = chrono::Utc.timestamp(timestamp, 0);
commit_date = dt.format("%Y-%m-%d").to_string()
} else if let Ok(release_file) = fs::File::open(release_file) {
let mut cargo_toml = crate_dir.clone();
cargo_toml.push("Cargo.toml");
let cargo_toml = fs::File::open(cargo_toml).expect("Can't open Cargo.toml");
commit_date = read_release_date(cargo_toml, release_file);
commit_id = "RELEASE".into();
}
println!("cargo:rustc-env=COMMIT_ID={}", commit_id);
println!("cargo:rustc-env=BUILD_REL_DATE={}", commit_date);
}
fn find_last_commit(repo: &Repository) -> Result<Commit, git2::Error> {
let obj = repo.head()?.resolve()?.peel(ObjectType::Commit)?;
obj.into_commit()
.map_err(|_| git2::Error::from_str("Couldn't find commit"))
}
fn oid_to_short_sha(oid: git2::Oid) -> String {
oid.to_string()[..8].to_string()
}
fn read_release_date(mut cargo_toml: fs::File, mut release_file: fs::File) -> String {
use std::io::Read;
let mut content = String::new();
release_file
.read_to_string(&mut content)
.expect("Failed to read version file");
let mut lines = content.lines();
let version = lines.next().expect("Failed to read version number");
let date = lines.next().expect("Failed to read release date");
let mut cargo_toml_content = String::new();
cargo_toml
.read_to_string(&mut cargo_toml_content)
.expect("Failed to read `Cargo.toml`");
let cargo_toml = cargo_toml_content
.parse::<toml::Value>()
.expect("Failed to parse `Cargo.toml`");
let package = cargo_toml["package"]
.as_table()
.expect("Failed to find 'package' section in `Cargo.toml`");
let cargo_version = package["version"]
.as_str()
.expect("Failed to read version from `Cargo.toml`");
if cargo_version != version {
panic!(
"Version from 'version.txt' `{}` different from 'Cargo.toml' `{}`",
version, cargo_version
);
}
date.into()
}