3e993bb657
This is a simple but powerful continuous integration build system for Git. It works by receiving push events from repositories through the post-receive hook, aggregates them on a per-branch basis into a first-come-first-serve build queue, and lets a background build daemon perform builds one at a time. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
105 lines
2.1 KiB
Perl
105 lines
2.1 KiB
Perl
#!/usr/bin/perl
|
|
#
|
|
# A hook that notifies its companion cidaemon through a simple
|
|
# queue file that a ref has been updated via a push (actually
|
|
# by a receive-pack running on the server).
|
|
#
|
|
# See cidaemon for per-repository configuration details.
|
|
#
|
|
# To use this hook, add it as the post-receive hook, make it
|
|
# executable, and set its configuration options.
|
|
#
|
|
|
|
local $ENV{PATH} = '/opt/git/bin';
|
|
|
|
use strict;
|
|
use warnings;
|
|
use File::Spec;
|
|
use Storable qw(retrieve nstore);
|
|
use Fcntl ':flock';
|
|
|
|
my $git_dir = File::Spec->rel2abs($ENV{GIT_DIR});
|
|
my $queue_name = `git config --get builder.queue`;chop $queue_name;
|
|
$queue_name =~ m,^([^\s]+)$,; $queue_name = $1; # untaint
|
|
unless ($queue_name) {
|
|
1 while <STDIN>;
|
|
print STDERR "\nerror: builder.queue not set. Not enqueing.\n\n";
|
|
exit;
|
|
}
|
|
my $queue_lock = "$queue_name.lock";
|
|
|
|
my @skip;
|
|
open S, "git config --get-all builder.skip|";
|
|
while (<S>) {
|
|
chop;
|
|
push @skip, $_;
|
|
}
|
|
close S;
|
|
|
|
my @new_branch_base;
|
|
open S, "git config --get-all builder.newBranchBase|";
|
|
while (<S>) {
|
|
chop;
|
|
push @new_branch_base, $_;
|
|
}
|
|
close S;
|
|
|
|
sub skip ($)
|
|
{
|
|
local $_ = shift;
|
|
foreach my $p (@skip) {
|
|
return 1 if /^$p/;
|
|
}
|
|
0;
|
|
}
|
|
|
|
open LOCK, ">$queue_lock" or die "Can't open $queue_lock: $!";
|
|
flock LOCK, LOCK_EX;
|
|
|
|
my $queue = -f $queue_name ? retrieve $queue_name : [];
|
|
my %existing;
|
|
foreach my $r (@$queue) {
|
|
my ($gd, $ref) = @$r;
|
|
$existing{$gd}{$ref} = $r;
|
|
}
|
|
|
|
my @new_branch_commits;
|
|
my $loaded_new_branch_commits = 0;
|
|
|
|
while (<STDIN>) {
|
|
chop;
|
|
my ($old, $new, $ref) = split / /, $_, 3;
|
|
|
|
next if $old eq $new;
|
|
next if $new =~ /^0{40}$/;
|
|
next if skip $ref;
|
|
|
|
my $r = $existing{$git_dir}{$ref};
|
|
if ($r) {
|
|
$r->[3] = $new;
|
|
} else {
|
|
if ($old =~ /^0{40}$/) {
|
|
if (!$loaded_new_branch_commits && @new_branch_base) {
|
|
open M,'-|','git','show-ref',@new_branch_base;
|
|
while (<M>) {
|
|
($_) = split / /, $_;
|
|
push @new_branch_commits, $_;
|
|
}
|
|
close M;
|
|
$loaded_new_branch_commits = 1;
|
|
}
|
|
$old = [@new_branch_commits];
|
|
} else {
|
|
$old = [$old];
|
|
}
|
|
|
|
$r = [$git_dir, $ref, $old, $new];
|
|
$existing{$git_dir}{$ref} = $r;
|
|
push @$queue, $r;
|
|
}
|
|
}
|
|
nstore $queue, $queue_name;
|
|
|
|
flock LOCK, LOCK_UN;
|
|
close LOCK;
|