use camino::Utf8Path;
use crate::errors::Result;
use crate::{PackageInfo, Version, WorkspaceInfo};
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
pub struct ChangelogInfo {
pub title: String,
pub body: String,
}
impl WorkspaceInfo {
pub fn changelog_for_version(&self, version: &Version) -> Result<Option<ChangelogInfo>> {
if let Some(changelog_path) = self.root_auto_includes.changelog.as_deref() {
changelog_for_version(changelog_path, version)
} else {
Ok(None)
}
}
}
impl PackageInfo {
pub fn changelog_for_version(&self, version: &Version) -> Result<Option<ChangelogInfo>> {
if let Some(changelog_path) = self.changelog_file.as_deref() {
changelog_for_version(changelog_path, version)
} else {
Ok(None)
}
}
}
pub fn changelog_for_version(
changelog_path: &Utf8Path,
version: &Version,
) -> Result<Option<ChangelogInfo>> {
let changelog_str = axoasset::LocalAsset::load_string(changelog_path)?;
changelog_for_version_inner(changelog_path, &changelog_str, version)
}
pub fn changelog_for_version_inner(
changelog_path: &Utf8Path,
changelog_str: &str,
version: &Version,
) -> Result<Option<ChangelogInfo>> {
let changelogs = parse_changelog::parse(changelog_str)?;
if let Some(info) = try_extract_changelog_exact(&changelogs, version)
.or_else(|| try_extract_changelog_normalized(&changelogs, version))
.or_else(|| try_extract_changelog_unreleased(&changelogs, version))
{
Ok(Some(info))
} else {
Err(crate::errors::AxoprojectError::ChangelogVersionNotFound {
path: changelog_path.to_owned(),
version: version.clone(),
})
}
}
fn try_extract_changelog_exact(
changelogs: &parse_changelog::Changelog,
version: &Version,
) -> Option<ChangelogInfo> {
let version_string = format!("{}", version);
changelogs
.get(&*version_string)
.map(|release_notes| ChangelogInfo {
title: release_notes.title_no_link().to_string(),
body: release_notes.notes.to_string(),
})
}
fn try_extract_changelog_normalized(
changelogs: &parse_changelog::Changelog,
version: &Version,
) -> Option<ChangelogInfo> {
if version.is_stable() {
return None;
}
let stable_version = version.stable_part();
let stable_version_string = format!("{}", stable_version);
let release_notes = changelogs.get(&*stable_version_string)?;
let raw_title = release_notes.title_no_link();
let (prefix, freeform) = raw_title.split_once(&stable_version_string)?;
let title = format!("{}{}{}", prefix, version, freeform);
Some(ChangelogInfo {
title,
body: release_notes.notes.to_string(),
})
}
fn try_extract_changelog_unreleased(
changelogs: &parse_changelog::Changelog,
version: &Version,
) -> Option<ChangelogInfo> {
if version.is_stable() {
return None;
}
let release_notes = changelogs.get("Unreleased")?;
let title = format!("Version {version}");
Some(ChangelogInfo {
title,
body: release_notes.notes.to_string(),
})
}