package App::Changelord::Command::GitGather; use v5.36.0; use Moo; use CLI::Osprey desc => 'gather changes from git commit messages', description_pod => <<'END_POD'; Inspects the git log of the current branch for commit messages looking like change entries. If any are found, add them to the changelog. =head2 Lower bound of the git log C will inspect the git log from the most recent of those three points: =over =item The last change in the NEXT release having a C property. =item The last tagged version. =item The beginning of time. =back =head2 Change-like git message Git messages are compared to the regular expression configured at `project.commit_regex`. If none is found, it defaults to ^(?[^: ]+):(?.*?)(\[(?[^\]]+)\])?$ The regular expression must capture a C field, and may capture a C and C as well. END_POD use Path::Tiny; use Git::Repository; with 'App::Changelord::Role::Changelog'; with 'App::Changelord::Role::Versions'; with 'App::Changelord::Role::ChangeTypes'; has repo => ( is => 'ro', default => sub { Git::Repository->new( work_tree => '.' ) }, ); has commit_regex => ( is => 'lazy' ); sub _build_commit_regex($self) { my $regex = $self->changelog->{project}{commit_regex}; my $default = '^(?[^: ]+):(?.*?)(\[(?[^\]]+)\])?$'; if(!$regex) { warn "project.commit_regex not configured, using the default /$default/\n"; $regex = $default; } return $regex; } sub lower_bound($self) { # either the most recent commit in the current release my @sha1s = grep { $_ } map { $_->{commit} } grep { ref } $self->next_release->{changes}->@*; return pop @sha1s if @sha1s; return $self->latest_version; } sub get_commits($self,$since=undef) { return reverse $self->repo->run( 'log', '--pretty=format:%H %s', $since ? "$since.." : () ); } sub munge_message($self,$message) { my $regex = $self->commit_regex; $message =~ s/(\S+) //; my $commit = $1; return () unless $message =~ qr/$regex/; return { %+, commit => $commit }; } sub save_changelog($self) { my $src = $self->source; path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) ); } sub run ($self) { say "let's check those git logs..."; # figure out lower bound my $from = $self->lower_bound; say "checking since ", ( $from || 'the dawn of time' ); my @messages = map { $self->munge_message($_) } $self->get_commits($from); unless(@messages) { say "\nno change detected"; return; } print "\n"; say " * ", $_->{desc} for @messages; print "\n"; push $self->next_release->{changes}->@*, @messages; $self->save_changelog; say $self->source, " updated"; } 1; __END__