Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): generate changelog from JSON context #784

Merged
merged 14 commits into from
Aug 23, 2024
Merged
26 changes: 19 additions & 7 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use crate::remote::github::GitHubClient;
use crate::remote::gitlab::GitLabClient;
use crate::template::Template;
use std::collections::HashMap;
use std::io::Write;
use std::io::{
Read,
Write,
};
use std::time::{
SystemTime,
UNIX_EPOCH,
Expand All @@ -39,8 +42,16 @@ pub struct Changelog<'a> {
impl<'a> Changelog<'a> {
/// Constructs a new instance.
pub fn new(releases: Vec<Release<'a>>, config: &'a Config) -> Result<Self> {
let mut changelog = Changelog::build(releases, config)?;
changelog.process_commits();
changelog.process_releases();
changelog.add_remote_data()?;
Ok(changelog)
}

fn build(releases: Vec<Release<'a>>, config: &'a Config) -> Result<Self> {
orhun marked this conversation as resolved.
Show resolved Hide resolved
let trim = config.changelog.trim.unwrap_or(true);
let mut changelog = Self {
Ok(Self {
releases,
header_template: match &config.changelog.header {
Some(header) => Some(Template::new(header.to_string(), trim)?),
Expand All @@ -61,11 +72,12 @@ impl<'a> Changelog<'a> {
},
config,
additional_context: HashMap::new(),
};
changelog.process_commits();
changelog.process_releases();
changelog.add_remote_data()?;
Ok(changelog)
})
}

/// 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)
}

/// Adds a key value pair to the template context.
Expand Down
4 changes: 2 additions & 2 deletions git-cliff-core/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static SHA1_REGEX: Lazy<Regex> = lazy_regex!(r#"^\b([a-f0-9]{40})\b (.*)$"#);

/// Object representing a link
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all(serialize = "camelCase"))]
janbuchar marked this conversation as resolved.
Show resolved Hide resolved
pub struct Link {
/// Text of the link.
pub text: String,
Expand Down Expand Up @@ -98,7 +98,7 @@ impl<'a> From<CommitSignature<'a>> for Signature {

/// Common commit object that is parsed from a repository.
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all(serialize = "camelCase"))]
pub struct Commit<'a> {
/// Commit ID.
pub id: String,
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use serde::{

/// Representation of a release.
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all(serialize = "camelCase"))]
pub struct Release<'a> {
/// Release version, git tag.
pub version: Option<String>,
Expand Down
9 changes: 9 additions & 0 deletions git-cliff/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,15 @@ pub struct Opt {
/// Prints changelog context as JSON.
#[arg(short = 'x', long, help_heading = Some("FLAGS"))]
pub context: bool,
/// Generates changelog from a JSON context.
#[arg(
long,
help_heading = Some("FLAGS"),
value_name = "PATH",
value_parser = Opt::parse_dir,
num_args = 0..=1,
)]
pub from_context: Option<PathBuf>,
/// Strips the given parts from the changelog.
#[arg(short, long, value_name = "PART", value_enum)]
pub strip: Option<Strip>,
Expand Down
86 changes: 48 additions & 38 deletions git-cliff/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,49 +496,59 @@ pub fn run(mut args: Opt) -> Result<()> {
if args.ignore_tags.is_some() {
config.git.ignore_tags.clone_from(&args.ignore_tags);
}
// Process the repositories.
let repositories = args.repository.clone().unwrap_or(vec![env::current_dir()?]);
let mut releases = Vec::<Release>::new();
for repository in repositories {
// Skip commits
let mut skip_list = Vec::new();
let ignore_file = repository.join(IGNORE_FILE);
if ignore_file.exists() {
let contents = fs::read_to_string(ignore_file)?;
let commits = contents
.lines()
.filter(|v| !(v.starts_with('#') || v.trim().is_empty()))
.map(|v| String::from(v.trim()))
.collect::<Vec<String>>();
skip_list.extend(commits);
}
if let Some(ref skip_commit) = args.skip_commit {
skip_list.extend(skip_commit.clone());
}
if let Some(commit_parsers) = config.git.commit_parsers.as_mut() {
for sha1 in skip_list {
commit_parsers.insert(0, CommitParser {
sha: Some(sha1.to_string()),
skip: Some(true),
..Default::default()
})
}
}

// Process the repository.
let repository = Repository::init(repository)?;
releases.extend(process_repository(
Box::leak(Box::new(repository)),
&mut config,
&args,
)?);
}

// Process commits and releases for the changelog.
if let Some(BumpOption::Specific(bump_type)) = args.bump {
config.bump.bump_type = Some(bump_type)
}
let mut changelog = Changelog::new(releases, &config)?;

let mut changelog: Changelog = if let Some(context_path) = args.from_context {
if context_path == Path::new("-") {
Changelog::from_context(&mut io::stdin(), &config)?
} else {
Changelog::from_context(&mut File::open(context_path)?, &config)?
}
} else {
// Process the repositories.
let repositories =
args.repository.clone().unwrap_or(vec![env::current_dir()?]);
let mut releases = Vec::<Release>::new();
for repository in repositories {
// Skip commits
let mut skip_list = Vec::new();
let ignore_file = repository.join(IGNORE_FILE);
if ignore_file.exists() {
let contents = fs::read_to_string(ignore_file)?;
let commits = contents
.lines()
.filter(|v| !(v.starts_with('#') || v.trim().is_empty()))
.map(|v| String::from(v.trim()))
.collect::<Vec<String>>();
skip_list.extend(commits);
}
if let Some(ref skip_commit) = args.skip_commit {
skip_list.extend(skip_commit.clone());
}
if let Some(commit_parsers) = config.git.commit_parsers.as_mut() {
for sha1 in skip_list {
commit_parsers.insert(0, CommitParser {
sha: Some(sha1.to_string()),
skip: Some(true),
..Default::default()
})
}
}

// Process the repository.
let repository = Repository::init(repository)?;
releases.extend(process_repository(
Box::leak(Box::new(repository)),
&mut config,
&args,
)?);
}
Changelog::new(releases, &config)?
};

// Print the result.
let mut out: Box<dyn io::Write> = if let Some(path) = &args.output {
Expand Down
Loading