git-pre-push-hook.pl 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/perl -w
  2. # To use this script: symlink it to .git/hooks/pre-push, then "git push"
  3. #
  4. # This script is called by "git push" after it has checked the remote status,
  5. # but before anything has been pushed. If this script exits with a non-zero
  6. # status nothing will be pushed.
  7. #
  8. # This hook is called with the following parameters:
  9. #
  10. # $1 -- Name of the remote to which the push is being done
  11. # $2 -- URL to which the push is being done
  12. #
  13. # If pushing without using a named remote those arguments will be equal.
  14. #
  15. # Information about the commits which are being pushed is supplied as lines to
  16. # the standard input in the form:
  17. #
  18. # <local ref> <local sha1> <remote ref> <remote sha1>
  19. use warnings;
  20. use strict;
  21. my $remote = $ARGV[0];
  22. my $url = $ARGV[1];
  23. #print("remote: $remote\n");
  24. #print("url: $url\n");
  25. $url =~ s/\.git$//; # change myorg/myproject.git to myorg/myproject
  26. $url =~ s#^git\@github\.com\:#https://github.com/#i;
  27. my $commiturl = $url =~ /\Ahttps?:\/\/github.com\// ? "$url/commit/" : '';
  28. my $z40 = '0000000000000000000000000000000000000000';
  29. my $reported = 0;
  30. while (<STDIN>) {
  31. chomp;
  32. my ($local_ref, $local_sha, $remote_ref, $remote_sha) = split / /;
  33. #print("local_ref: $local_ref\n");
  34. #print("local_sha: $local_sha\n");
  35. #print("remote_ref: $remote_ref\n");
  36. #print("remote_sha: $remote_sha\n");
  37. my $range = '';
  38. if ($remote_sha eq $z40) { # New branch, examine all commits
  39. $range = $local_sha;
  40. } else { # Update to existing branch, examine new commits
  41. $range = "$remote_sha..$local_sha";
  42. }
  43. my $gitcmd = "git log --reverse --oneline --no-abbrev-commit '$range'";
  44. open(GITPIPE, '-|', $gitcmd) or die("\n\n$0: Failed to run '$gitcmd': $!\n\nAbort push!\n\n");
  45. while (<GITPIPE>) {
  46. chomp;
  47. if (/\A([a-fA-F0-9]+)\s+(.*?)\Z/) {
  48. my $hash = $1;
  49. my $msg = $2;
  50. if (!$reported) {
  51. print("\nCommits expected to be pushed:\n");
  52. $reported = 1;
  53. }
  54. #print("hash: $hash\n");
  55. #print("msg: $msg\n");
  56. print("$commiturl$hash -- $msg\n");
  57. } else {
  58. die("$0: Unexpected output from '$gitcmd'!\n\nAbort push!\n\n");
  59. }
  60. }
  61. die("\n\n$0: Failing exit code from running '$gitcmd'!\n\nAbort push!\n\n") if !close(GITPIPE);
  62. }
  63. print("\n") if $reported;
  64. exit(0); # Let the push go forward.