feat(package): support cargo workspace versions (#4161)

This commit is contained in:
David Knaack 2022-07-20 11:17:27 +02:00 committed by GitHub
parent d8ac940098
commit 0a1235e279
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 122 additions and 3 deletions

View File

@ -7,6 +7,8 @@ use quick_xml::events::Event as QXEvent;
use quick_xml::Reader as QXReader;
use regex::Regex;
use serde_json as json;
use std::fs;
use std::io::Read;
/// Creates a module with the current package version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -213,10 +215,45 @@ fn get_sbt_version(context: &Context, config: &PackageConfig) -> Option<String>
}
fn get_cargo_version(context: &Context, config: &PackageConfig) -> Option<String> {
let file_contents = context.read_file_from_pwd("Cargo.toml")?;
let mut file_contents = context.read_file_from_pwd("Cargo.toml")?;
let cargo_toml: toml::Value = toml::from_str(&file_contents).ok()?;
let raw_version = cargo_toml.get("package")?.get("version")?.as_str()?;
let mut cargo_toml: toml::Value = toml::from_str(&file_contents).ok()?;
let cargo_version = cargo_toml.get("package").and_then(|p| p.get("version"));
let raw_version = if let Some(v) = cargo_version.and_then(|v| v.as_str()) {
// regular version string
v
} else if cargo_version
.and_then(|v| v.get("workspace"))
.and_then(|w| w.as_bool())
.unwrap_or_default()
{
// workspace version string (`package.version.worspace = true`)
// need to read the Cargo.toml file from the workspace root
let mut version = None;
// disover the workspace root
for path in context.current_dir.ancestors().skip(1) {
// Assume the workspace root is the first ancestor that contains a Cargo.toml file
if let Ok(mut file) = fs::File::open(path.join("Cargo.toml")) {
file.read_to_string(&mut file_contents).ok()?;
cargo_toml = toml::from_str(&file_contents).ok()?;
// Read workspace.package.version
version = cargo_toml
.get("workspace")?
.get("package")?
.get("version")?
.as_str();
break;
}
}
version?
} else {
// This might be a workspace file
cargo_toml
.get("workspace")?
.get("package")?
.get("version")?
.as_str()?
};
format_version(raw_version, config.version_format)
}
@ -356,6 +393,88 @@ mod tests {
project_dir.close()
}
#[test]
fn test_extract_cargo_version_ws() -> io::Result<()> {
let ws_config_name = "Cargo.toml";
let ws_config_content = toml::toml! {
[workspace.package]
version = "0.1.0"
}
.to_string();
let config_name = "member/Cargo.toml";
let config_content = toml::toml! {
[package]
version.workspace = true
}
.to_string();
let project_dir = create_project_dir()?;
fs::create_dir(project_dir.path().join("member"))?;
fill_config(&project_dir, ws_config_name, Some(&ws_config_content))?;
fill_config(&project_dir, config_name, Some(&config_content))?;
// Version can be read both from the workspace and the member.
expect_output(&project_dir, Some("v0.1.0"), None);
let actual = ModuleRenderer::new("package")
.path(project_dir.path().join("member"))
.collect();
let expected = Some(format!(
"is {} ",
Color::Fixed(208).bold().paint("📦 v0.1.0")
));
assert_eq!(actual, expected);
project_dir.close()
}
#[test]
fn test_extract_cargo_version_ws_false() -> io::Result<()> {
let ws_config_name = "Cargo.toml";
let ws_config_content = toml::toml! {
[workspace.package]
version = "0.1.0"
}
.to_string();
let config_name = "member/Cargo.toml";
let config_content = toml::toml! {
[package]
version.workspace = false
}
.to_string();
let project_dir = create_project_dir()?;
fs::create_dir(project_dir.path().join("member"))?;
fill_config(&project_dir, ws_config_name, Some(&ws_config_content))?;
fill_config(&project_dir, config_name, Some(&config_content))?;
// Version can be read both from the workspace and the member.
let actual = ModuleRenderer::new("package")
.path(project_dir.path().join("member"))
.collect();
let expected = None;
assert_eq!(actual, expected);
project_dir.close()
}
#[test]
fn test_extract_cargo_version_ws_missing_parent() -> io::Result<()> {
let config_name = "Cargo.toml";
let config_content = toml::toml! {
[package]
name = "starship"
version.workspace = true
}
.to_string();
let project_dir = create_project_dir()?;
fill_config(&project_dir, config_name, Some(&config_content))?;
expect_output(&project_dir, None, None);
project_dir.close()
}
#[test]
fn test_extract_nimble_package_version() -> io::Result<()> {
let config_name = "test_project.nimble";