2020-04-07 02:28:48 +02:00
|
|
|
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 {
|
2020-04-08 07:21:59 +02:00
|
|
|
let summary_bytes = current
|
|
|
|
.summary_bytes()
|
|
|
|
.ok_or_else(|| anyhow!("Commit had no summary"))?;
|
2020-04-07 02:28:48 +02:00
|
|
|
|
2020-04-08 07:21:59 +02:00
|
|
|
let summary = String::from_utf8_lossy(summary_bytes);
|
2020-04-07 02:28:48 +02:00
|
|
|
|
2020-04-08 07:21:59 +02:00
|
|
|
if !summary.starts_with("fixup!") {
|
|
|
|
let manifest_bytes = current
|
|
|
|
.tree()?
|
|
|
|
.get_path("Cargo.toml".as_ref())?
|
|
|
|
.to_object(&repo)?
|
|
|
|
.as_blob()
|
|
|
|
.unwrap()
|
|
|
|
.content()
|
|
|
|
.to_vec();
|
2020-04-07 02:28:48 +02:00
|
|
|
|
2020-04-08 07:21:59 +02:00
|
|
|
let manifest = Manifest::from_slice(&manifest_bytes)?;
|
|
|
|
|
|
|
|
let entry = Entry::new(¤t, manifest.package.unwrap().version.as_ref(), head)?;
|
2020-04-07 02:28:48 +02:00
|
|
|
|
2020-04-08 07:21:59 +02:00
|
|
|
entries.push(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
head = false;
|
2020-04-07 02:28:48 +02:00
|
|
|
|
|
|
|
match current.parent_count() {
|
|
|
|
0 => break,
|
|
|
|
1 => current = current.parent(0)?,
|
2020-04-08 07:21:59 +02:00
|
|
|
_ => throw!(anyhow!("Commit had multiple parents!")),
|
2020-04-07 02:28:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|