-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathbuild.rs
95 lines (82 loc) · 3.3 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
use std::{path::PathBuf, process::Command};
fn main() {
// set what version string to use for the build
// currently it depends on what git outputs, or if failed use "unknown"
{
// paths are relative to the workspace root
println!("cargo:rerun-if-changed=server/build.rs");
println!("cargo:rerun-if-changed=.git/HEAD");
let cargo_toml_version = {
let version = env!("CARGO_PKG_VERSION");
if version.is_empty() {
None
} else {
// format is the literal return of what is set in the "Cargo.toml", so to be consistent with git, we modify it to look the same as git (adding "v")
// also add a inidicator for cargo version
Some(format!("v{version}[c]"))
}
};
let cargo_toml_or_default = cargo_toml_version.unwrap_or(String::from("unknown"));
let version = git_version()
// fallback to Cargo.toml version, if git is unavailable (like having downloaded the source archive)
.unwrap_or(cargo_toml_or_default);
println!("cargo:rustc-env=TERMUSIC_VERSION={version}");
}
}
fn git_version() -> Option<String> {
let toplevel_dir = Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.output()
.ok()
.and_then(|v| {
print_stderr(&v.stderr);
String::from_utf8(v.stdout).ok()
})
.map(|mut v| {
// remove the ending "\n" that may exist
v.truncate(v.trim_end().len());
v
})
.map(PathBuf::from)?;
// not in the termusic repository, but still in a git repo, for example in a AUR build
// is there maybe a better way to check this?
if !toplevel_dir.join("Cargo.toml").exists()
&& !toplevel_dir.join("lib").exists()
&& !toplevel_dir.join("tui").exists()
&& !toplevel_dir.join("server").exists()
{
return None;
}
// How to read the git version, first all the variants:
// Termusic-server v0.7.11-302-g63396ee5-dirty[g]
// Termusic-server v0.7.11-302-g63396ee5[g]
// Termusic-server v0.7.11[g]
// Termusic-server v0.7.11[c]
// Termusic-server unknown
//
// "Termusic-server" is the binary name
// "v0.7.11" is the latest tag on the branch
// "302" is the number of commits since the tag, not always present
// "g63396ee5" is 2 parts, the "g" in the beginning means "git"
// the rest "63396ee5" is the abbreviated commit sha
// "dirty" indicates the build has uncommited changes
// "[g]" at the end means the version has been gotten from "git" ("[c]" means from "cargo")
Command::new("git")
.args(["describe", "--tags", "--always", "--dirty"])
.output()
.ok()
.and_then(|v| {
print_stderr(&v.stderr);
String::from_utf8(v.stdout).ok()
})
// ignore output if the string gotten is empty
.and_then(|v| if v.is_empty() { None } else { Some(v) })
// add a indicator for git version
.map(|v| format!("{}[g]", v.trim()))
}
/// print stderr for debugging purposes, it will not be shown unless the build.rs panics
fn print_stderr(stderr: &[u8]) {
if !stderr.is_empty() {
eprintln!("{}", String::from_utf8_lossy(stderr));
}
}