use curl::easy::Easy;
const USER_AGENT: &str = "topstitch_crate_unit_test";
fn get_workspace_root() -> std::path::PathBuf {
let workspace_dir = cargo_metadata::MetadataCommand::new()
.exec()
.unwrap()
.workspace_root;
workspace_dir.into()
}
fn fetch_latest_version(crate_name: &str) -> Result<String, Box<dyn std::error::Error>> {
let url = format!("https://crates.io/api/v1/crates/{crate_name}");
let mut data = Vec::new();
let mut easy = Easy::new();
easy.url(&url)?;
easy.useragent(USER_AGENT)?;
{
let mut transfer = easy.transfer();
transfer.write_function(|new_data| {
data.extend_from_slice(new_data);
Ok(new_data.len())
})?;
transfer.perform()?;
}
let response: serde_json::Value = serde_json::from_slice(&data)?;
log::debug!("Response: {:?}", response);
let newest_version = response["crate"]["newest_version"].as_str();
let latest_version = newest_version
.ok_or(format!(
"Failed to parse latest version: {newest_version:?}"
))?
.to_string();
Ok(latest_version)
}
fn fetch_local_version(dirpath: &std::path::Path) -> Result<String, Box<dyn std::error::Error>> {
let cargo_toml = std::fs::read_to_string(dirpath.join("Cargo.toml"))?;
let cargo_toml: toml::Value = toml::from_str(&cargo_toml)?;
let version = cargo_toml["package"]["version"]
.as_str()
.ok_or(format!(
"Failed to parse local version: {}",
cargo_toml["package"]["version"]
))?
.to_string();
Ok(version)
}
fn validate_local_version_gt_released(
crate_name: &str,
workspace_path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
let latest_version = fetch_latest_version(crate_name)?;
let local_version = fetch_local_version(workspace_path)?;
let local_semver = semver::Version::parse(&local_version)?;
let latest_semver = semver::Version::parse(&latest_version)?;
log::info!(
"crate: {} local_version: {} released_version: {}",
crate_name,
local_version,
latest_version
);
if local_semver <= latest_semver {
Err(Box::new(std::io::Error::other(format!(
"Local version {local_version} is not greater than the latest version {latest_version}"
))))
} else {
Ok(())
}
}
#[test]
fn test_topstitch_crate_version() {
let _ = env_logger::builder().is_test(true).try_init();
validate_local_version_gt_released("topstitch", get_workspace_root().as_path()).unwrap();
}