daily pastebin goal
15%
SHARE
TWEET

git pre-commit hook

a guest Sep 19th, 2012 112 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env perl
  2. # Copy me to the .git/hooks directory and rename file to "pre-commit"
  3. #
  4. # This script is invoked by "git commit" and runs some PHP and JS syntax checks
  5. # on the files staged for commit. It exits with a non-zero status if any check
  6. # fails.
  7.  
  8. use strict;
  9. use warnings;
  10.  
  11. exit run_hooks(\&check_php_syntax, \&check_js_syntax);
  12.  
  13. sub run_hooks {
  14.         my @hooks = @_;
  15.  
  16.         # Get a list of files staged for commit
  17.         my @staged_files = staged_files();
  18.  
  19.         # Stash unstaged changes. That is, set the working copy
  20.         # to the same state as HEAD, but keep any changes that have been
  21.         # staged for commit.
  22.         run_command('git', 'stash', 'save', '--quiet', '--keep-index');
  23.  
  24.         # Execute each hook on the changes
  25.         my $failed = 0;
  26.         foreach my $hook (@hooks) {
  27.                 $failed = $hook->(@staged_files) || $failed;
  28.         }
  29.  
  30.         # Restore the stashed changes to the working copy
  31.         run_command('git', 'stash', 'pop', '--quiet');
  32.  
  33.         print "\nAborting commit due to pre-commit hook errors...\n" if $failed;
  34.  
  35.         return $failed;
  36. }
  37.  
  38. sub run_command {
  39.         system(@_) == 0 or die "system @_ failed: $?";
  40. }
  41.  
  42. sub staged_files {
  43.         my $output = qx{git diff --cached --name-status};
  44.         my @lines = split("\n", $output);
  45.         my @staged_files;
  46.  
  47.         # parse diff to extract status and file name
  48.         foreach my $line (@lines) {
  49.                 my ($status, $name) = split /\s+/, $line, 2;
  50.                 $name =~ s/(?:^")|(?:"$)//g; # extract name from quotes
  51.                 next if $status eq 'D'; # skip deleted items
  52.                 push @staged_files, $name;
  53.         }
  54.  
  55.         return @staged_files;
  56. }
  57.  
  58. sub check_php_syntax {
  59.         my @files = grep /(?:\.php)|(?:\.ctp)$/, @_;
  60.         my $failed = 0;
  61.  
  62.         local $/ = undef; # enable slurp mode
  63.  
  64.         foreach my $file (@files) {
  65.                 my $output = qx{php -l $file};
  66.                 my $error = ($output =~ /Parse error/);
  67.                 $failed = $failed || $error;
  68.  
  69.                 print $output if $error;
  70.         }
  71.  
  72.         print "\n" if $failed;
  73.  
  74.         return $failed;
  75. }
  76.  
  77. sub check_js_syntax {
  78.         my @files = grep /\.js/, @_;
  79.         my $failed = 0;
  80.  
  81.         local $/ = undef; # enable slurp mode
  82.  
  83.         foreach my $file (@files) {
  84.                 my $output = qx{jsl -nologo -nofilelisting -nosummary -nocontext -process $file};
  85.                 my $code = ($? >> 8);
  86.                 my $error = ($code >= 3);
  87.                 $failed = $failed || $error;
  88.  
  89.                 print $output if $error;
  90.         }
  91.  
  92.         return $failed;
  93. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top