101 lines
2.0 KiB
Rust
101 lines
2.0 KiB
Rust
|
use crate::common::*;
|
||
|
|
||
|
pub(crate) struct Changelog {
|
||
|
releases: Vec<Release>,
|
||
|
}
|
||
|
|
||
|
impl Changelog {
|
||
|
#[throws]
|
||
|
pub(crate) fn new(repo: &Repository) -> Self {
|
||
|
let mut current = repo.head()?.peel_to_commit()?;
|
||
|
|
||
|
let mut entries = Vec::new();
|
||
|
|
||
|
let mut head = true;
|
||
|
|
||
|
loop {
|
||
|
let manifest_bytes = current
|
||
|
.tree()?
|
||
|
.get_path("Cargo.toml".as_ref())?
|
||
|
.to_object(&repo)?
|
||
|
.as_blob()
|
||
|
.unwrap()
|
||
|
.content()
|
||
|
.to_vec();
|
||
|
|
||
|
let manifest = Manifest::from_slice(&manifest_bytes)?;
|
||
|
|
||
|
let entry = Entry::new(¤t, manifest.package.unwrap().version.as_ref(), head)?;
|
||
|
|
||
|
head = false;
|
||
|
|
||
|
entries.push(entry);
|
||
|
|
||
|
match current.parent_count() {
|
||
|
0 => break,
|
||
|
1 => current = current.parent(0)?,
|
||
|
count => panic!("Commit has {} parents", count),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
entries.reverse();
|
||
|
|
||
|
let mut releases = Vec::new();
|
||
|
|
||
|
let mut last_version = entries[0].version.clone();
|
||
|
|
||
|
let mut unreleased = Vec::new();
|
||
|
|
||
|
for entry in entries {
|
||
|
if entry.version != last_version {
|
||
|
let version = entry.version.clone();
|
||
|
let time = entry.time;
|
||
|
|
||
|
unreleased.push(entry);
|
||
|
|
||
|
releases.push(Release {
|
||
|
version: Some(version.clone()),
|
||
|
time,
|
||
|
entries: unreleased,
|
||
|
});
|
||
|
|
||
|
last_version = version;
|
||
|
|
||
|
unreleased = Vec::new();
|
||
|
} else {
|
||
|
unreleased.push(entry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !unreleased.is_empty() {
|
||
|
releases.push(Release {
|
||
|
version: None,
|
||
|
time: Utc::now(),
|
||
|
entries: unreleased,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
releases.reverse();
|
||
|
|
||
|
for release in &mut releases {
|
||
|
release.entries.reverse();
|
||
|
}
|
||
|
|
||
|
Self { releases }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Display for Changelog {
|
||
|
#[throws(fmt::Error)]
|
||
|
fn fmt(&self, f: &mut Formatter) {
|
||
|
writeln!(f, "Changelog")?;
|
||
|
writeln!(f, "=========")?;
|
||
|
|
||
|
for release in &self.releases {
|
||
|
writeln!(f)?;
|
||
|
writeln!(f)?;
|
||
|
write!(f, "{}", release)?;
|
||
|
}
|
||
|
}
|
||
|
}
|