From f919b440a12f5c31fe55d3b683e90702eb0ac5b0 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 15 Feb 2010 02:10:59 -0600 Subject: add a plugin for commit reporting --- lib/Crawl/Bot/Plugin/Commit.pm | 101 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 lib/Crawl/Bot/Plugin/Commit.pm diff --git a/lib/Crawl/Bot/Plugin/Commit.pm b/lib/Crawl/Bot/Plugin/Commit.pm new file mode 100644 index 0000000..7993271 --- /dev/null +++ b/lib/Crawl/Bot/Plugin/Commit.pm @@ -0,0 +1,101 @@ +package Crawl::Bot::Plugin::Commit; +use Moose; +use autodie; +use File::pushd; +extends 'Crawl::Bot::Plugin'; + +has repo_uri => ( + is => 'ro', + isa => 'Str', + default => 'git://crawl-ref.git.sourceforge.net/gitroot/crawl-ref/crawl-ref ', +); + +has checkout => ( + is => 'ro', + isa => 'Str', + lazy => 1, + default => sub { + my $self = shift; + my $checkout = File::Spec->catdir($self->data_dir, 'crawl-ref'); + mkdir $checkout unless -d $checkout; + my $dir = pushd($checkout); + if (-f 'HEAD') { + system('git fetch ' . $self->repo_uri); + } + else { + system('git clone --bare ' . $self->repo_uri . " $checkout"); + } + $checkout; + }, +); + +has heads => ( + traits => [qw(Hash)], + isa => 'HashRef[Str]', + lazy => 1, + handles => { + has_branch => 'exists', + head => 'accessor', + }, + default => sub { + my $self = shift; + my $dir = pushd($self->checkout); + return { map { $_ => `git rev-parse $_` } $self->branches }; + }, +); + +sub tick { + my $self = shift; + my $dir = pushd($self->checkout); + system('git fetch ' . $self->repo_uri); + for my $branch ($self->branches) { + my $old_head = $self->head($branch) || ''; + my $head = `git rev-parse $branch`; + next if $old_head eq $head; + + if (!$self->has_branch($branch)) { + $self->say_all("New branch created: $branch"); + } + + my @revs = split /\n/, `git rev-list $old_head..$head`; + my %commits = map { $_, $self->parse_commit($_) } @revs; + + my $cherry_picks = @revs; + @revs = grep { $commits{$_}->{body} !~ /\(cherry picked from / } @revs; + $cherry_picks -= @revs; + $self->say_all("Cherry-picked $cherry_picks commits into $branch"); + + for my $rev (@revs) { + my $commit = $commits{$rev}; + $self->say_all("$commit->{author} * r$rev ($commit->{nfiles} changed): $commit->{subject}"); + } + + $self->head($branch => $head); + } +} + +sub branches { + my $self = shift; + my $dir = pushd($self->checkout); + return map { s/^[ \*]*//; $_ } split /\n/, `git branch`; +} + +sub parse_commit { + my $self = shift; + my ($rev) = @_; + my $info = `git log -1 --pretty=format:%aN%x00%s%x00%b%x00 $rev`; + $info =~ /(.*?)\0(.*?)\0(.*?)\0(.*?)/; + my ($author, $subject, $body, $stat) = ($1, $2, $3, $4); + $stat =~ s/(\d+) files changed//; + return { + author => $author, + subject => $subject, + body => $body, + nfiles => $stat, + }; +} + +__PACKAGE__->meta->make_immutable; +no Moose; + +1; -- cgit v1.2.3-54-g00ecf