diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2020-02-02 11:38:26 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2020-02-02 11:38:26 -0700 |
commit | 389125925095d1ffff276ac25671365f20540d98 (patch) | |
tree | d616ab4f260599a2bc20d605cc53268d1ff7a709 /hooks | |
parent | bc687302753c78c8acdffbf89aa4b3a0ba3fb466 (diff) | |
download | dotfiles-389125925095d1ffff276ac25671365f20540d98.tar.gz |
add chained_hook hook
Diffstat (limited to 'hooks')
-rwxr-xr-x | hooks/git/chained_hook | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/hooks/git/chained_hook b/hooks/git/chained_hook new file mode 100755 index 00000000..ad6a422e --- /dev/null +++ b/hooks/git/chained_hook @@ -0,0 +1,60 @@ +#!/usr/bin/perl + +# Some aspects of this approach are due to: +# http://blog.bluefeet.net/2011/08/chained-git-hooks/ +# see: http://web.archive.org/web/20111231092040/http://blog.bluefeet.net/2011/08/chained-git-hooks/ +# +# This implementation using IO::Pipe is +# Copyright (C) 2020 Sean Whitton <spwhitton@spwhitton.name> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Use by symlinking this hook to .git/hooks/pre-push (or whichever +# hook you want to chain) and then add your hooks as +# .git/hooks/pre-push_01foo, .git/hooks/pre-push_02bar etc. + +use 5.028; +use strict; +use warnings; + +use IO::Pipe; +use File::Spec::Functions qw(catfile); + +(my $hook_type = $0) =~ s{^.+/}{}; +my $config_hooks_path = `git config core.hooksPath`; +chomp(my $hook_dir = $config_hooks_path || `git rev-parse --git-path hooks`); +opendir(my $dirh, $hook_dir); +my @hooks = sort grep /^${hook_type}_/, readdir $dirh; + +my @stdin = <STDIN>; + +foreach my $hook (@hooks) { + my $pipe = IO::Pipe->new; + my $pid = fork; + die "fork() failed: $!" unless defined $pid; + if ($pid) { + $pipe->writer; + print $pipe $_ for @stdin; + $pipe->close; + wait; + # give up as soon as one hook fails; since we sort the hooks, + # we can put more expensive hooks later in the sequence + die "hook $hook exited non-zero" if $?; + } else { + $pipe->reader; + open STDIN, "<&=" . $pipe->fileno + or die "couldn't open child's STDIN"; + exec catfile($hook_dir, $hook), @ARGV; + } +} |