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