1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
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 clone --mirror ' . $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');
for my $branch ($self->branches) {
my $old_head = $self->head($branch) || '';
my $head = `git rev-parse $branch`;
chomp ($old_head, $head);
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{$_}->{subject} !~ /\(cherry picked from /
&& $commits{$_}->{body} !~ /\(cherry picked from / } @revs;
$cherry_picks -= @revs;
$self->say_all("Cherry-picked $cherry_picks commits into $branch")
if $cherry_picks > 0;
for my $rev (@revs) {
my $commit = $commits{$rev};
my $abbr = substr($rev, 0, 12);
$self->say_all("$commit->{author} * r$abbr ($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 $dir = pushd($self->checkout);
my $info = `git log -1 --pretty=format:%aN%x00%s%x00%b%x00 $rev`;
$info =~ /(.*?)\x00(.*?)\x00(.*?)\x00(.*?)/s;
my ($author, $subject, $body, $stat) = ($1, $2, $3, $4);
$stat =~ s/(\d+) files changed/$1/;
return {
author => $author,
subject => $subject,
body => $body,
nfiles => $stat,
};
}
__PACKAGE__->meta->make_immutable;
no Moose;
1;
|