use std::path::PathBuf;
use anyhow::{
Context,
Result,
};
use cargo_plugin_utils::common::find_package;
use clap::Parser;
#[derive(Parser, Debug)]
pub struct CurrentArgs {
#[arg(long)]
manifest_path: Option<PathBuf>,
#[arg(long, default_value = "version")]
format: String,
#[arg(long, env = "GITHUB_OUTPUT")]
github_output: Option<String>,
}
pub fn current(args: CurrentArgs) -> Result<()> {
let mut logger = cargo_plugin_utils::logger::Logger::new();
logger.status("Reading", "package version");
let package = find_package(args.manifest_path.as_deref())?;
let version = package.version.to_string();
logger.finish();
match args.format.as_str() {
"version" => println!("{}", version),
"json" => println!("{{\"version\":\"{}\"}}", version),
"github-actions" => {
let output_file = args.github_output.as_deref().unwrap_or("/dev/stdout");
let output = format!("version={}\n", version);
std::fs::write(output_file, output)
.with_context(|| format!("Failed to write to {}", output_file))?;
}
_ => anyhow::bail!("Invalid format: {}", args.format),
}
Ok(())
}
#[cfg(test)]
mod tests {
use tempfile::NamedTempFile;
use super::*;
fn create_temp_cargo_project(content: &str) -> tempfile::TempDir {
let dir = tempfile::tempdir().unwrap();
let manifest_path = dir.path().join("Cargo.toml");
std::fs::write(&manifest_path, content).unwrap();
let src_dir = dir.path().join("src");
std::fs::create_dir_all(&src_dir).unwrap();
std::fs::write(src_dir.join("lib.rs"), "// Test library\n").unwrap();
dir
}
#[test]
fn test_current_workspace_version() {
let _dir = tempfile::tempdir().unwrap();
std::fs::write(
_dir.path().join("Cargo.toml"),
r#"
[workspace.package]
version = "0.1.2"
[workspace]
members = ["member1"]
"#,
)
.unwrap();
let member_dir = _dir.path().join("member1");
std::fs::create_dir_all(member_dir.join("src")).unwrap();
std::fs::write(
member_dir.join("Cargo.toml"),
r#"
[package]
name = "member1"
version.workspace = true
"#,
)
.unwrap();
std::fs::write(member_dir.join("src").join("lib.rs"), "// Test library\n").unwrap();
let manifest_path = member_dir.join("Cargo.toml");
let args = CurrentArgs {
manifest_path: Some(manifest_path),
format: "version".to_string(),
github_output: None,
};
assert!(current(args).is_ok());
}
#[test]
fn test_current_package_version() {
let _dir = create_temp_cargo_project(
r#"
[package]
name = "test"
version = "1.2.3"
"#,
);
let manifest_path = _dir.path().join("Cargo.toml");
let args = CurrentArgs {
manifest_path: Some(manifest_path.clone()),
format: "version".to_string(),
github_output: None,
};
let result = current(args);
if let Err(e) = &result {
eprintln!("Error in test_current_package_version: {}", e);
eprintln!("Manifest path: {:?}", manifest_path);
}
assert!(result.is_ok());
}
#[test]
fn test_current_json_format() {
let _dir = create_temp_cargo_project(
r#"
[package]
name = "test"
version = "0.5.0"
"#,
);
let manifest_path = _dir.path().join("Cargo.toml");
let args = CurrentArgs {
manifest_path: Some(manifest_path),
format: "json".to_string(),
github_output: None,
};
assert!(current(args).is_ok());
}
#[test]
fn test_current_github_actions_format() {
let _dir = create_temp_cargo_project(
r#"
[package]
name = "test"
version = "2.0.0"
"#,
);
let manifest_path = _dir.path().join("Cargo.toml");
let output_file = NamedTempFile::new().unwrap();
let args = CurrentArgs {
manifest_path: Some(manifest_path),
format: "github-actions".to_string(),
github_output: Some(output_file.path().to_string_lossy().to_string()),
};
assert!(current(args).is_ok());
let content = std::fs::read_to_string(output_file.path()).unwrap();
assert!(content.contains("version=2.0.0"));
}
#[test]
fn test_current_invalid_format() {
let _dir = create_temp_cargo_project(
r#"
[package]
name = "test"
version = "1.0.0"
"#,
);
let manifest_path = _dir.path().join("Cargo.toml");
let args = CurrentArgs {
manifest_path: Some(manifest_path),
format: "invalid".to_string(),
github_output: None,
};
assert!(current(args).is_err());
}
#[test]
fn test_current_file_not_found() {
let args = CurrentArgs {
manifest_path: Some("/nonexistent/Cargo.toml".into()),
format: "version".to_string(),
github_output: None,
};
assert!(current(args).is_err());
}
#[test]
fn test_current_no_version() {
let _dir = create_temp_cargo_project(
r#"
[package]
name = "test"
"#,
);
let manifest_path = _dir.path().join("Cargo.toml");
let args = CurrentArgs {
manifest_path: Some(manifest_path),
format: "version".to_string(),
github_output: None,
};
let result = current(args);
assert!(result.is_ok());
}
}