refactor: propagate version formatting errors (#2566)

* refactor: propagate version formatting errors

* refactor: trim version formatting boilerplate

* refactor(node): unwrap version formatting

* docs: fix typo

* docs: remove dots after `version_format`

* feat: lazy version parsing

* refactor(version-formatter): collect segments into string
This commit is contained in:
Dario Vladović 2021-04-10 19:06:25 +02:00 committed by GitHub
parent 436eb61efd
commit fe030c2064
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 172 additions and 158 deletions

View File

@ -1379,7 +1379,7 @@ By default the module will be shown if any of the following conditions are met:
| Option | Default | Description |
| ------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `format` | `"via [${symbol}(${version} )]($style)"` | The format for the module. |
| `version_format`. | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `version_format` | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `detect_extensions` | `["java", "class", "gradle", "jar", "cljs", "cljc"]` | Which extensions should trigger this module. |
| `detect_files` | `["pom.xml", "build.gradle.kts", "build.sbt", ".java-version", ".deps.edn", "project.clj", "build.boot"]` | Which filenames should trigger this module. |
| `detect_folders` | `[]` | Which folders should trigger this modules. |
@ -1825,9 +1825,9 @@ By default the module will be shown if any of the following conditions are met:
| Option | Default | Description |
| ------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| `format` | `"via [$symbol($version )]($style)"` | The format for the module. |
| `version_format`. | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `version_format` | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `symbol` | `" "` | A format string representing the symbol of NodeJS. |
| `detect_extensions` | `["js", "mjs", "cjs", "ts"]` | Which extensions should trigger this moudle. |
| `detect_extensions` | `["js", "mjs", "cjs", "ts"]` | Which extensions should trigger this module. |
| `detect_files` | `["package.json", ".node-version"]` | Which filenames should trigger this module. |
| `detect_folders` | `["node_modules"]` | Which folders should trigger this module. |
| `style` | `"bold green"` | The style for the module. |
@ -2135,7 +2135,7 @@ By default the module will be shown if any of the following conditions are met:
| Option | Default | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| `format` | `'via [${symbol}${pyenv_prefix}(${version} )(\($virtualenv\) )]($style)'` | The format for the module. |
| `version_format`. | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `version_format` | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `symbol` | `"🐍 "` | A format string representing the symbol of Python |
| `style` | `"yellow bold"` | The style for the module. |
| `pyenv_version_name` | `false` | Use pyenv to get Python version |
@ -2214,7 +2214,7 @@ The module will be shown if any of the following conditions are met:
| Option | Default | Description |
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------- |
| `format` | `"via [$symbol($version )]($style)"` | The format for the module. |
| `version_format`. | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `version_format` | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `symbol` | `"💎 "` | A format string representing the symbol of Ruby. |
| `detect_extensions` | `["rb"]` | Which extensions should trigger this module. |
| `detect_files` | `["Gemfile", ".ruby-version"]` | Which filenames should trigger this module. |
@ -2254,7 +2254,7 @@ The module will be shown if any of the following conditions are met:
| Option | Default | Description |
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------- |
| `format` | `"via [$symbol($version )]($style)"` | The format for the module. |
| `version_format`. | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `version_format` | `v{raw}` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
| `symbol` | `"🦀 "` | A format string representing the symbol of Rust |
| `detect_extensions` | `["rs"]` | Which extensions should trigger this module. |
| `detect_files` | `["Cargo.toml"]` | Which filenames should trigger this module. |

View File

@ -30,7 +30,7 @@ type VariableMapType<'a> =
type StyleVariableMapType<'a> =
BTreeMap<String, Option<Result<Cow<'a, str>, StringFormatterError>>>;
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum StringFormatterError {
Custom(String),
Parse(PestError<Rule>),

View File

@ -1,5 +1,7 @@
use super::string_formatter::StringFormatterError;
use super::StringFormatter;
use once_cell::sync::Lazy;
use std::ops::Deref;
use versions::Versioning;
pub struct VersionFormatter<'a> {
@ -17,26 +19,32 @@ impl<'a> VersionFormatter<'a> {
Ok(Self { formatter })
}
/// Format version string using provided format
pub fn format_version(
version: &'a str,
format: &'a str,
) -> Result<String, StringFormatterError> {
Self::new(format).and_then(|formatter| formatter.format(version))
}
/// Formats a version structure into a readable string
///
/// No matter what comes in, this will return some usable string
pub fn format_version(self, version: &str) -> String {
let parsed = Versioning::new(version);
pub fn format(self, version: &'a str) -> Result<String, StringFormatterError> {
let parsed = Lazy::new(|| Versioning::new(version));
let formatted = self
.formatter
.map(|variable| match variable {
"raw" => Some(Ok(version.to_string())),
"major" => match parsed.as_ref() {
"major" => match parsed.deref().as_ref() {
Some(Versioning::Ideal(v)) => Some(Ok(v.major.to_string())),
Some(Versioning::General(v)) => Some(Ok(v.nth_lenient(0)?.to_string())),
_ => None,
},
"minor" => match parsed.as_ref() {
"minor" => match parsed.deref().as_ref() {
Some(Versioning::Ideal(v)) => Some(Ok(v.minor.to_string())),
Some(Versioning::General(v)) => Some(Ok(v.nth_lenient(1)?.to_string())),
_ => None,
},
"patch" => match parsed.as_ref() {
"patch" => match parsed.deref().as_ref() {
Some(Versioning::Ideal(v)) => Some(Ok(v.patch.to_string())),
Some(Versioning::General(v)) => Some(Ok(v.nth_lenient(2)?.to_string())),
_ => None,
@ -44,14 +52,13 @@ impl<'a> VersionFormatter<'a> {
_ => None,
})
.parse(None);
match formatted {
Ok(segments) => segments
formatted.map(|segments| {
segments
.iter()
.map(|segment| segment.value.as_str())
.collect::<Vec<&str>>()
.join(""),
Err(_) => version.to_string(),
}
.collect::<String>()
})
}
}
@ -59,39 +66,37 @@ impl<'a> VersionFormatter<'a> {
mod tests {
use super::*;
const VERSION_FORMAT: &str = "major:${major} minor:${minor} patch:${patch} raw:${raw}";
#[test]
fn test_semver_full() {
const FORMAT_STR: &str = "major:${major} minor:${minor} patch:${patch} raw:${raw}";
let result = VersionFormatter::new(FORMAT_STR)
.unwrap()
.format_version("1.2.3");
assert_eq!(result, "major:1 minor:2 patch:3 raw:1.2.3");
assert_eq!(
VersionFormatter::format_version("1.2.3", VERSION_FORMAT),
Ok("major:1 minor:2 patch:3 raw:1.2.3".to_string())
);
}
#[test]
fn test_semver_partial() {
const FORMAT_STR: &str = "major:${major} minor:${minor} patch:${patch} raw:${raw}";
let result = VersionFormatter::new(FORMAT_STR)
.unwrap()
.format_version("1.2");
assert_eq!(result, "major:1 minor:2 patch: raw:1.2");
assert_eq!(
VersionFormatter::format_version("1.2", VERSION_FORMAT),
Ok("major:1 minor:2 patch: raw:1.2".to_string())
);
}
#[test]
fn test_general() {
const FORMAT_STR: &str = "major:${major} minor:${minor} patch:${patch} raw:${raw}";
let result = VersionFormatter::new(FORMAT_STR)
.unwrap()
.format_version("1.2-a.3");
assert_eq!(result, "major:1 minor:2 patch: raw:1.2-a.3");
assert_eq!(
VersionFormatter::format_version("1.2-a.3", VERSION_FORMAT),
Ok("major:1 minor:2 patch: raw:1.2-a.3".to_string())
);
}
#[test]
fn test_mess() {
const FORMAT_STR: &str = "major:${major} minor:${minor} patch:${patch} raw:${raw}";
let result = VersionFormatter::new(FORMAT_STR)
.unwrap()
.format_version("utter junk");
assert_eq!(result, "major: minor: patch: raw:utter junk");
fn test_dummy() {
assert_eq!(
VersionFormatter::format_version("dummy version", VERSION_FORMAT),
Ok("major: minor: patch: raw:dummy version".to_string())
);
}
}

View File

@ -34,10 +34,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None,
})
.map(|variable| match variable {
"version" => {
let java_version = get_java_version(context, &config)?;
Some(Ok(java_version))
}
"version" => get_java_version(context, &config).map(Ok),
_ => None,
})
.parse(None)
@ -74,19 +71,21 @@ fn get_java_version(context: &Context, config: &JavaConfig) -> Option<String> {
output.stdout
};
parse_java_version(config.version_format, &java_version)
format_java_version(&java_version, config.version_format)
}
fn parse_java_version(version_format: &str, java_version: &str) -> Option<String> {
fn format_java_version(java_version: &str, version_format: &str) -> Option<String> {
let re = Regex::new(JAVA_VERSION_PATTERN).ok()?;
let captures = re.captures(java_version)?;
let version = &captures["version"];
Some(
VersionFormatter::new(version_format)
.ok()?
.format_version(version),
)
match VersionFormatter::format_version(version, version_format) {
Ok(formatted) => Some(formatted),
Err(error) => {
log::warn!("Error formating `java` version:\n{}", error);
Some(format!("v{}", version))
}
}
}
#[cfg(test)]
@ -98,106 +97,106 @@ mod tests {
use std::io;
#[test]
fn test_parse_java_version_openjdk() {
fn test_format_java_version_openjdk() {
let java_8 = "OpenJDK 64-Bit Server VM (25.222-b10) for linux-amd64 JRE (1.8.0_222-b10), built on Jul 11 2019 10:18:43 by \"openjdk\" with gcc 4.4.7 20120313 (Red Hat 4.4.7-23)";
let java_11 = "OpenJDK 64-Bit Server VM (11.0.4+11-post-Ubuntu-1ubuntu219.04) for linux-amd64 JRE (11.0.4+11-post-Ubuntu-1ubuntu219.04), built on Jul 18 2019 18:21:46 by \"build\" with gcc 8.3.0";
assert_eq!(
parse_java_version("v${raw}", java_11),
format_java_version(java_11, "v${raw}"),
Some("v11.0.4".to_string())
);
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
}
#[test]
fn test_parse_java_version_oracle() {
fn test_format_java_version_oracle() {
let java_8 = "Java HotSpot(TM) Client VM (25.65-b01) for linux-arm-vfp-hflt JRE (1.8.0_65-b17), built on Oct 6 2015 16:19:04 by \"java_re\" with gcc 4.7.2 20120910 (prerelease)";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
}
#[test]
fn test_parse_java_version_redhat() {
fn test_format_java_version_redhat() {
let java_8 = "OpenJDK 64-Bit Server VM (25.222-b10) for linux-amd64 JRE (1.8.0_222-b10), built on Jul 11 2019 20:48:53 by \"root\" with gcc 7.3.1 20180303 (Red Hat 7.3.1-5)";
let java_12 = "OpenJDK 64-Bit Server VM (12.0.2+10) for linux-amd64 JRE (12.0.2+10), built on Jul 18 2019 14:41:47 by \"jenkins\" with gcc 7.3.1 20180303 (Red Hat 7.3.1-5)";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
assert_eq!(
parse_java_version("v${raw}", java_12),
format_java_version(java_12, "v${raw}"),
Some("v12.0.2".to_string())
);
}
#[test]
fn test_parse_java_version_zulu() {
fn test_format_java_version_zulu() {
let java_8 = "OpenJDK 64-Bit Server VM (25.222-b10) for linux-amd64 JRE (Zulu 8.40.0.25-CA-linux64) (1.8.0_222-b10), built on Jul 11 2019 11:36:39 by \"zulu_re\" with gcc 4.4.7 20120313 (Red Hat 4.4.7-3)";
let java_11 = "OpenJDK 64-Bit Server VM (11.0.4+11-LTS) for linux-amd64 JRE (Zulu11.33+15-CA) (11.0.4+11-LTS), built on Jul 11 2019 21:37:17 by \"zulu_re\" with gcc 4.9.2 20150212 (Red Hat 4.9.2-6)";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
assert_eq!(
parse_java_version("v${raw}", java_11),
format_java_version(java_11, "v${raw}"),
Some("v11.0.4".to_string())
);
}
#[test]
fn test_parse_java_version_eclipse_openj9() {
fn test_format_java_version_eclipse_openj9() {
let java_8 = "Eclipse OpenJ9 OpenJDK 64-bit Server VM (1.8.0_222-b10) from linux-amd64 JRE with Extensions for OpenJDK for Eclipse OpenJ9 8.0.222.0, built on Jul 17 2019 21:29:18 by jenkins with g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)";
let java_11 = "Eclipse OpenJ9 OpenJDK 64-bit Server VM (11.0.4+11) from linux-amd64 JRE with Extensions for OpenJDK for Eclipse OpenJ9 11.0.4.0, built on Jul 17 2019 21:51:37 by jenkins with g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
assert_eq!(
parse_java_version("v${raw}", java_11),
format_java_version(java_11, "v${raw}"),
Some("v11.0.4".to_string())
);
}
#[test]
fn test_parse_java_version_graalvm() {
fn test_format_java_version_graalvm() {
let java_8 = "OpenJDK 64-Bit GraalVM CE 19.2.0.1 (25.222-b08-jvmci-19.2-b02) for linux-amd64 JRE (8u222), built on Jul 19 2019 17:37:13 by \"buildslave\" with gcc 7.3.0";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v8".to_string())
);
}
#[test]
fn test_parse_java_version_amazon_corretto() {
fn test_format_java_version_amazon_corretto() {
let java_8 = "OpenJDK 64-Bit Server VM (25.222-b10) for linux-amd64 JRE (1.8.0_222-b10), built on Jul 11 2019 20:48:53 by \"root\" with gcc 7.3.1 20180303 (Red Hat 7.3.1-5)";
let java_11 = "OpenJDK 64-Bit Server VM (11.0.4+11-LTS) for linux-amd64 JRE (11.0.4+11-LTS), built on Jul 11 2019 20:06:11 by \"\" with gcc 7.3.1 20180303 (Red Hat 7.3.1-5)";
assert_eq!(
parse_java_version("v${raw}", java_8),
format_java_version(java_8, "v${raw}"),
Some("v1.8.0".to_string())
);
assert_eq!(
parse_java_version("v${raw}", java_11),
format_java_version(java_11, "v${raw}"),
Some("v11.0.4".to_string())
);
}
#[test]
fn test_parse_java_version_sapmachine() {
fn test_format_java_version_sapmachine() {
let java_11 = "OpenJDK 64-Bit Server VM (11.0.4+11-LTS-sapmachine) for linux-amd64 JRE (11.0.4+11-LTS-sapmachine), built on Jul 17 2019 08:58:43 by \"\" with gcc 7.3.0";
assert_eq!(
parse_java_version("v${raw}", java_11),
format_java_version(java_11, "v${raw}"),
Some("v11.0.4".to_string())
);
}
#[test]
fn test_parse_java_version_unknown() {
fn test_format_java_version_unknown() {
let unknown_jre = "Unknown JRE";
assert_eq!(parse_java_version("v${raw}", unknown_jre), None);
assert_eq!(format_java_version(unknown_jre, "v${raw}"), None);
}
#[test]

View File

@ -57,18 +57,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None,
})
.map(|variable| match variable {
"version" => {
let nodejs_detected_version = &nodejs_version
.deref()
.as_ref()
.map(|version| version.trim());
match nodejs_detected_version {
Some(version) => Some(Ok(VersionFormatter::new(config.version_format)
.ok()?
.format_version(&version.to_string().drain(1..).collect::<String>()))),
None => None,
}
}
"version" => Some(Ok(format_node_version(
nodejs_version.deref().as_ref()?,
config.version_format,
))),
_ => None,
})
.parse(None)
@ -114,6 +106,18 @@ fn check_engines_version(nodejs_version: &str, engines_version: Option<String>)
r.matches(&v)
}
fn format_node_version(node_version: &str, version_format: &str) -> String {
let version = node_version.trim_start_matches('v').trim();
match VersionFormatter::format_version(version, version_format) {
Ok(formatted) => formatted,
Err(error) => {
log::warn!("Error formating `node` version:\n{}", error);
format!("v{}", version)
}
}
}
#[cfg(test)]
mod tests {
use crate::test::ModuleRenderer;

View File

@ -41,10 +41,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None,
})
.map(|variable| match variable {
"version" => {
let version = get_python_version(context, &config)?;
Some(Ok(version.trim().to_string()))
}
"version" => get_python_version(context, &config).map(Ok),
"virtualenv" => {
let virtual_env = get_python_virtual_env(context);
virtual_env.as_ref().map(|e| Ok(e.trim().to_string()))
@ -68,7 +65,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
fn get_python_version(context: &Context, config: &PythonConfig) -> Option<String> {
if config.pyenv_version_name {
return Some(context.exec_cmd("pyenv", &["version-name"])?.stdout);
let version_name = context.exec_cmd("pyenv", &["version-name"])?.stdout;
return Some(version_name.trim().to_string());
};
let version = config
.python_binary
@ -83,21 +81,23 @@ fn get_python_version(context: &Context, config: &PythonConfig) -> Option<String
}
})?;
format_python_version(config.version_format, &version)
format_python_version(&version, config.version_format)
}
fn format_python_version(version_format: &str, python_version: &str) -> Option<String> {
fn format_python_version(python_version: &str, version_format: &str) -> Option<String> {
let version = python_version
// split into ["Python", "3.8.6", ...]
.split_whitespace()
// get down to "3.8.6"
.nth(1)?;
Some(
VersionFormatter::new(version_format)
.ok()?
.format_version(version),
)
match VersionFormatter::format_version(version, version_format) {
Ok(formatted) => Some(formatted),
Err(error) => {
log::warn!("Error formating `python` version:\n{}", error);
Some(format!("v{}", version))
}
}
}
fn get_python_virtual_env(context: &Context) -> Option<String> {
@ -128,45 +128,48 @@ mod tests {
#[test]
fn test_format_python_version() {
let input = "Python 3.7.2";
assert_eq!(
format_python_version("v${major}.${minor}.${patch}", input),
format_python_version("Python 3.7.2", "v${major}.${minor}.${patch}"),
Some("v3.7.2".to_string())
);
}
#[test]
fn test_format_python_version_truncated() {
let input = "Python 3.7.2";
assert_eq!(
format_python_version("v${major}.${minor}", input),
format_python_version("Python 3.7.2", "v${major}.${minor}"),
Some("v3.7".to_string())
);
}
#[test]
fn test_format_python_version_is_malformed() {
let input = "Python 3.7";
assert_eq!(
format_python_version("v${major}.${minor}.${patch}", input),
format_python_version("Python 3.7", "v${major}.${minor}.${patch}"),
Some("v3.7.".to_string())
);
}
#[test]
fn test_format_python_version_anaconda() {
let input = "Python 3.6.10 :: Anaconda, Inc.";
assert_eq!(
format_python_version("v${major}.${minor}.${patch}", input),
format_python_version(
"Python 3.6.10 :: Anaconda, Inc.",
"v${major}.${minor}.${patch}"
),
Some("v3.6.10".to_string())
);
}
#[test]
fn test_format_python_version_pypy() {
let input = "Python 3.7.9 (7e6e2bb30ac5fbdbd443619cae28c51d5c162a02, Nov 24 2020, 10:03:59)\n[PyPy 7.3.3-beta0 with GCC 10.2.0]";
assert_eq!(
format_python_version("v${major}.${minor}.${patch}", input),
format_python_version(
"\
Python 3.7.9 (7e6e2bb30ac5fbdbd443619cae28c51d5c162a02, Nov 24 2020, 10:03:59)
[PyPy 7.3.3-beta0 with GCC 10.2.0]",
"v${major}.${minor}.${patch}"
),
Some("v3.7.9".to_string())
);
}

View File

@ -35,8 +35,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
})
.map(|variable| match variable {
"version" => format_ruby_version(
&config,
&context.exec_cmd("ruby", &["-v"])?.stdout.as_str(),
&context.exec_cmd("ruby", &["-v"])?.stdout,
config.version_format,
)
.map(Ok),
_ => None,
@ -55,7 +55,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
Some(module)
}
fn format_ruby_version(config: &RubyConfig, ruby_version: &str) -> Option<String> {
fn format_ruby_version(ruby_version: &str, version_format: &str) -> Option<String> {
let version = ruby_version
// split into ["ruby", "2.6.0p0", "linux/amd64"]
.split_whitespace()
@ -66,11 +66,13 @@ fn format_ruby_version(config: &RubyConfig, ruby_version: &str) -> Option<String
// return "2.6.0"
.next()?;
Some(
VersionFormatter::new(config.version_format)
.ok()?
.format_version(version),
)
match VersionFormatter::format_version(version, version_format) {
Ok(formatted) => Some(formatted),
Err(error) => {
log::warn!("Error formating `ruby` version:\n{}", error);
Some(format!("v{}", version))
}
}
}
#[cfg(test)]
@ -130,25 +132,25 @@ mod tests {
#[test]
fn test_format_ruby_version() {
let test_config = RubyConfig::default();
let config = RubyConfig::default();
assert_eq!(
format_ruby_version(
&test_config,
"ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-darwin19.0]"
"ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-darwin19.0]",
config.version_format
),
Some("v2.1.10".to_string())
);
assert_eq!(
format_ruby_version(
&test_config,
"ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]"
"ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]",
config.version_format
),
Some("v2.5.1".to_string())
);
assert_eq!(
format_ruby_version(
&test_config,
"ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-musl]"
"ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-musl]",
config.version_format
),
Some("v2.7.0".to_string())
);

View File

@ -72,27 +72,25 @@ fn get_module_version(context: &Context, config: &RustConfig) -> Option<String>
// - `rustup show`
// - `rustup show active-toolchain`
// - `rustup which`
let module_version = if let Some(toolchain) = env_rustup_toolchain(context)
if let Some(toolchain) = env_rustup_toolchain(context)
.or_else(|| execute_rustup_override_list(&context.current_dir))
.or_else(|| find_rust_toolchain_file(&context))
{
match execute_rustup_run_rustc_version(&toolchain) {
RustupRunRustcVersionOutcome::RustcVersion(stdout) => {
format_rustc_version(config, stdout)
RustupRunRustcVersionOutcome::RustcVersion(rustc_version) => {
format_rustc_version(&rustc_version, config.version_format)
}
RustupRunRustcVersionOutcome::ToolchainName(toolchain) => toolchain,
RustupRunRustcVersionOutcome::ToolchainName(toolchain) => Some(toolchain),
RustupRunRustcVersionOutcome::RustupNotWorking => {
// If `rustup` is not in `$PATH` or cannot be executed for other reasons, we can
// safely execute `rustc --version`.
format_rustc_version(config, execute_rustc_version()?)
format_rustc_version(&execute_rustc_version()?, config.version_format)
}
RustupRunRustcVersionOutcome::Err => return None,
RustupRunRustcVersionOutcome::Err => None,
}
} else {
format_rustc_version(config, execute_rustc_version()?)
};
Some(module_version)
format_rustc_version(&execute_rustc_version()?, config.version_format)
}
}
fn env_rustup_toolchain(context: &Context) -> Option<String> {
@ -205,14 +203,19 @@ fn execute_rustc_version() -> Option<String> {
}
}
fn format_rustc_version(config: &RustConfig, mut rustc_stdout: String) -> String {
let offset = &rustc_stdout.find('(').unwrap_or_else(|| rustc_stdout.len());
let formatted_version: String = rustc_stdout.drain(..offset).collect();
let full_version_string = formatted_version.replace("rustc", "");
let version_string = full_version_string.trim();
match VersionFormatter::new(config.version_format) {
Ok(formatter) => formatter.format_version(&version_string),
_ => format!("v{}", version_string),
fn format_rustc_version(rustc_version: &str, version_format: &str) -> Option<String> {
let version = rustc_version
// split into ["rustc", "1.34.0", ...]
.split_whitespace()
// get down to "1.34.0"
.nth(1)?;
match VersionFormatter::format_version(version, version_format) {
Ok(formatted) => Some(formatted),
Err(error) => {
log::warn!("Error formating `rust` version:\n{}", error);
Some(format!("v{}", version))
}
}
}
@ -326,27 +329,25 @@ mod tests {
#[test]
fn test_format_rustc_version() {
let test_config: RustConfig = RustConfig::default();
let nightly_input = String::from("rustc 1.34.0-nightly (b139669f3 2019-04-10)");
let config = RustConfig::default();
let rustc_stable = "rustc 1.34.0 (91856ed52 2019-04-10)";
let rustc_beta = "rustc 1.34.0-beta.1 (2bc1d406d 2019-04-10)";
let rustc_nightly = "rustc 1.34.0-nightly (b139669f3 2019-04-10)";
assert_eq!(
format_rustc_version(&test_config, nightly_input),
"v1.34.0-nightly"
format_rustc_version(rustc_nightly, config.version_format),
Some("v1.34.0-nightly".to_string())
);
let beta_input = String::from("rustc 1.34.0-beta.1 (2bc1d406d 2019-04-10)");
assert_eq!(
format_rustc_version(&test_config, beta_input),
"v1.34.0-beta.1"
format_rustc_version(rustc_beta, config.version_format),
Some("v1.34.0-beta.1".to_string())
);
let stable_input = String::from("rustc 1.34.0 (91856ed52 2019-04-10)");
assert_eq!(format_rustc_version(&test_config, stable_input), "v1.34.0");
let version_without_hash = String::from("rustc 1.34.0");
assert_eq!(
format_rustc_version(&test_config, version_without_hash),
"v1.34.0"
format_rustc_version(rustc_stable, config.version_format),
Some("v1.34.0".to_string())
);
assert_eq!(
format_rustc_version("rustc 1.34.0", config.version_format),
Some("v1.34.0".to_string())
);
}