Skip to content

Commit

Permalink
Parse the version and date from verbose info
Browse files Browse the repository at this point in the history
The plain `rustc --version` string is not well structured, and in
particular the git commit info is not necessarily present when rustc was
built out of tree, like distro builds. Furthermore, rust-lang/rust#79115
made it possible to have completely custom information in that version's
parenthesized block, which may not look like git info at all.

Adding `--verbose` outputs each field on its own line, in particular
"release: ..." for the version number and "commit-date: ..." for the git
info, although the latter is just "unknown" for out-of-tree builds. This
still works all the way back to Rust 1.0.0.
  • Loading branch information
cuviper committed Mar 8, 2021
1 parent b5caeeb commit 430fe19
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,24 @@ use std::process::Command;

/// Parses (version, date) as available from rustc version string.
fn version_and_date_from_rustc_version(s: &str) -> (Option<String>, Option<String>) {
let last_line = s.lines().last().unwrap_or(s);
let mut components = last_line.trim().split(" ");
let version = components.nth(1);
let date = components.filter(|c| c.ends_with(')')).next()
.map(|s| s.trim_right().trim_right_matches(")").trim_left().trim_left_matches('('));
(version.map(|s| s.to_string()), date.map(|s| s.to_string()))
let split = |s: &str| s.splitn(2, ": ").nth(1).map(str::to_string);
let mut version = None;
let mut date = None;
for line in s.lines() {
if line.starts_with("release:") {
version = split(line);
}
if line.starts_with("commit-date:") {
date = split(line);
}
}
(version, date)
}

/// Returns (version, date) as available from `rustc --version`.
fn get_version_and_date() -> Option<(Option<String>, Option<String>)> {
env::var("RUSTC").ok()
.and_then(|rustc| Command::new(rustc).arg("--version").output().ok())
.or_else(|| Command::new("rustc").arg("--version").output().ok())
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string());
Command::new(rustc).arg("--version").arg("--verbose").output().ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|s| version_and_date_from_rustc_version(&s))
}
Expand Down

0 comments on commit 430fe19

Please sign in to comment.