use std::path::PathBuf;
use anyhow::{
Context,
Result,
};
pub async fn guess_if_published(package: &cargo_metadata::Package) -> Result<bool> {
if let Some(ref publish) = package.publish
&& publish.is_empty()
{
return Ok(false);
}
let has_license_in_metadata = package.license.is_some() || package.license_file.is_some();
let manifest_path = package.manifest_path.as_std_path();
let manifest_dir = manifest_path
.parent()
.unwrap_or_else(|| std::path::Path::new("."));
let has_license = tokio::fs::metadata(manifest_dir.join("LICENSE"))
.await
.is_ok()
|| tokio::fs::metadata(manifest_dir.join("LICENSE-MIT"))
.await
.is_ok()
|| tokio::fs::metadata(manifest_dir.join("LICENSE-APACHE"))
.await
.is_ok();
let workflows_dir = manifest_dir.join(".github/workflows");
let has_publish_in_workflows = if tokio::fs::metadata(&workflows_dir).await.is_err() {
false
} else {
let mut entries = match tokio::fs::read_dir(&workflows_dir).await {
Ok(entries) => entries,
Err(_) => return Ok(false),
};
let mut found = false;
while let Some(entry) = entries.next_entry().await? {
let path = entry.path();
let ext = path.extension();
if ext != Some("yml".as_ref()) && ext != Some("yaml".as_ref()) {
continue;
}
if let Ok(content) = tokio::fs::read_to_string(&path).await
&& content.contains("cargo publish")
{
found = true;
break;
}
}
found
};
let likely_published = has_license_in_metadata || has_license || has_publish_in_workflows;
Ok(likely_published)
}
pub async fn compute_cache_key(package: &cargo_metadata::Package) -> Result<String> {
let git_hash = tokio::task::spawn_blocking(|| {
let repo = match gix::discover(".") {
Ok(r) => r,
Err(_) => return None,
};
match repo.head_id() {
Ok(id) => Some(id.to_hex().to_string()),
Err(_) => None,
}
})
.await
.context("Failed to spawn blocking task")?;
if let Some(hash) = git_hash {
return Ok(hash);
}
let manifest_path = package.manifest_path.as_std_path();
let mtime = tokio::task::spawn_blocking({
let path = manifest_path.to_path_buf();
move || {
std::fs::metadata(&path)
.ok()
.and_then(|meta| meta.modified().ok())
.map(|time| {
time.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
.to_string()
})
}
})
.await
.context("Failed to spawn blocking task")?;
Ok(mtime.unwrap_or_else(|| "unknown".to_string()))
}
pub fn get_badge_cache_path(cache_name: &str) -> Result<PathBuf> {
let target_dir = if let Ok(dir) = std::env::var("CARGO_TARGET_DIR") {
PathBuf::from(dir)
} else {
let mut path = std::env::current_dir()?;
let mut found = None;
loop {
let target = path.join("target");
if target.exists() {
found = Some(target);
break;
}
if let Some(parent) = path.parent() {
path = parent.to_path_buf();
} else {
break;
}
}
found.unwrap_or_else(|| std::env::current_dir().unwrap().join("target"))
};
Ok(target_dir.join(format!(".cargo-version-info-{}-cache.json", cache_name)))
}