Skip to content

Commit

Permalink
fix(changelog): fix missing commit fields in context (orhun#837)
Browse files Browse the repository at this point in the history
  • Loading branch information
dqkqd committed Oct 13, 2024
1 parent da1cb61 commit 52712d8
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 3 deletions.
93 changes: 92 additions & 1 deletion git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl<'a> Changelog<'a> {

/// Constructs an instance from a serialized context object.
pub fn from_context<R: Read>(input: &mut R, config: &'a Config) -> Result<Self> {
Changelog::build(serde_json::from_reader(input)?, config)
Changelog::new(serde_json::from_reader(input)?, config)
}

/// Adds a key value pair to the template context.
Expand Down Expand Up @@ -1314,4 +1314,95 @@ chore(deps): fix broken deps
.assert_eq(str::from_utf8(&out).unwrap_or_default());
Ok(())
}

#[test]
fn changelog_context_is_identical_after_writing_and_reading() -> Result<()> {
let (mut config, mut releases) = get_test_data();
config.git.split_commits = Some(false);

let commit_id = "fcead7edd312489eb6d16f21e517cd74";
let commit = Commit::new(
String::from(commit_id),
String::from(
"feat(app)!: add some more cool features
Body Message
Footer: Fix #000
Singed-off-by: coolguy
",
),
);
releases[0].commits.push(commit.clone());
let changelog = Changelog::new(releases, &config)?;

let write_then_load_context = |changelog: &Changelog| -> Result<Changelog> {
let mut context = Vec::new();
changelog.write_context(&mut context)?;
let context_str = String::from_utf8(context).expect("");
let from_context =
Changelog::from_context(&mut context_str.as_bytes(), &config)?;
Ok(from_context)
};

let changelog_from_context = write_then_load_context(&changelog)?;

// find our commit
let commit_before_write = changelog
.releases
.iter()
.flat_map(|release| release.commits.iter().find(|c| c.id == commit_id))
.next()
.expect("Commit must exist");

// make sure this is conventional commit before writing
assert!(commit_before_write.conv.is_some());
assert!(commit_before_write
.conv
.as_ref()
.is_some_and(|conv| !conv.footers().is_empty()));

let commit_after_read = changelog_from_context
.releases
.iter()
.flat_map(|release| release.commits.iter().find(|c| c.id == commit_id))
.next()
.expect("Commit must exist");

// make sure after reading, this still is a conventional commit
assert!(commit_after_read.conv.is_some());

// In a conventional commit, `message` and `raw_message` are not identical
// compared to normal commits, because `message` is taken from
// `conv.description()` instead of `self.message`.
// Hence we need to set those two fields before comparing.
let mut commit_before_write = commit_before_write.clone();
commit_before_write.message = commit_after_read.message.clone();
commit_before_write.raw_message = commit_after_read.raw_message.clone();
assert_eq!(&commit_before_write, commit_after_read);

// subsequence changelog are identical
let changelog_from_context2 =
write_then_load_context(&changelog_from_context)?;
let commit_after_read2 = changelog_from_context2
.releases
.iter()
.flat_map(|release| release.commits.iter().find(|c| c.id == commit_id))
.next()
.expect("Commit must exist");
assert_eq!(commit_after_read, commit_after_read2);

let changelog_from_context3 =
write_then_load_context(&changelog_from_context2)?;
let commit_after_read3 = changelog_from_context3
.releases
.iter()
.flat_map(|release| release.commits.iter().find(|c| c.id == commit_id))
.next()
.expect("Commit must exist");
assert_eq!(commit_after_read, commit_after_read3);

Ok(())
}
}
14 changes: 12 additions & 2 deletions git-cliff-core/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ pub struct Commit<'a> {
#[cfg(feature = "bitbucket")]
#[deprecated(note = "Use `remote` field instead")]
pub bitbucket: crate::contributor::RemoteContributor,

/// Message of the normal commit, to avoid lossly message conversion between
/// conventional commit
pub raw_message: Option<String>,
}

impl<'a> From<String> for Commit<'a> {
Expand Down Expand Up @@ -191,6 +195,11 @@ impl Commit<'_> {
}
}

/// Get raw commit message uses for converting to conventional commit
pub fn raw_message(&self) -> &str {
self.raw_message.as_deref().unwrap_or(&self.message)
}

/// Processes the commit.
///
/// * converts commit to a conventional commit
Expand Down Expand Up @@ -226,7 +235,7 @@ impl Commit<'_> {
/// Returns the commit with its conventional type set.
pub fn into_conventional(mut self) -> Result<Self> {
match ConventionalCommit::parse(Box::leak(
self.message.to_string().into_boxed_str(),
self.raw_message().to_string().into_boxed_str(),
)) {
Ok(conv) => {
self.conv = Some(conv);
Expand Down Expand Up @@ -423,8 +432,9 @@ impl Serialize for Commit<'_> {
}
}

let mut commit = serializer.serialize_struct("Commit", 9)?;
let mut commit = serializer.serialize_struct("Commit", 20)?;
commit.serialize_field("id", &self.id)?;
commit.serialize_field("raw_message", &self.raw_message())?;
if let Some(conv) = &self.conv {
commit.serialize_field("message", conv.description())?;
commit.serialize_field("body", &conv.body())?;
Expand Down

0 comments on commit 52712d8

Please sign in to comment.