| #!/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; |