bug-hello
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/3] copy: add git hooks from coreutils


From: Sami Kerola
Subject: [PATCH 1/3] copy: add git hooks from coreutils
Date: Sun, 28 Dec 2014 11:27:23 +0000

Copy git hooks from coreutils to assure commit messages are suitable
for ChangeLog.  For example 'Signd-off-by' lines should not be used,
and such error has already slipped twice to hello, see 9aaee4c9 and
bc966b6f.

* bootstrap.conf: Add bootstrap_epilogue() to maintain up to date copy
  of scripts in .git/hooks/ directory.
* scripts/git-hooks/applypatch-msg: Add script.
* scripts/git-hooks/commit-msg: Add script.
* scripts/git-hooks/pre-applypatch: Add script.
* scripts/git-hooks/pre-commit: Add script.
---
 bootstrap.conf                   |  17 +++++
 scripts/git-hooks/applypatch-msg |  15 ++++
 scripts/git-hooks/commit-msg     | 153 +++++++++++++++++++++++++++++++++++++++
 scripts/git-hooks/pre-applypatch |  14 ++++
 scripts/git-hooks/pre-commit     |  50 +++++++++++++
 5 files changed, 249 insertions(+)
 create mode 100755 scripts/git-hooks/applypatch-msg
 create mode 100755 scripts/git-hooks/commit-msg
 create mode 100755 scripts/git-hooks/pre-applypatch
 create mode 100755 scripts/git-hooks/pre-commit

diff --git a/bootstrap.conf b/bootstrap.conf
index 6d33b1e..4e0b388 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -100,3 +100,20 @@ bootstrap_post_import_hook ()
 # File that should exist in the top directory of a checked out hierarchy,
 # but not in a distribution tarball.
 checkout_only_file=README-dev
+
+bootstrap_epilogue()
+{
+  # Install our git hooks, as long as "cp" accepts the --backup option,
+  # so that we can back up any existing files.
+  case $(cp --help) in *--backup*) backup=1;; *) backup=0;; esac
+  if test $backup = 1; then
+    hooks=$(cd scripts/git-hooks && git ls-files)
+    for f in $hooks; do
+      # If it is identical, skip it.
+      cmp scripts/git-hooks/$f .git/hooks/$f > /dev/null \
+       && continue
+      cp --backup=numbered scripts/git-hooks/$f .git/hooks
+      chmod a-w .git/hooks/$f
+    done
+  fi
+}
diff --git a/scripts/git-hooks/applypatch-msg b/scripts/git-hooks/applypatch-msg
new file mode 100755
index 0000000..8b2a2fe
--- /dev/null
+++ b/scripts/git-hooks/applypatch-msg
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+       exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff --git a/scripts/git-hooks/commit-msg b/scripts/git-hooks/commit-msg
new file mode 100755
index 0000000..2735b66
--- /dev/null
+++ b/scripts/git-hooks/commit-msg
@@ -0,0 +1,153 @@
+eval '(exit $?0)' && eval 'exec perl -w "$0" ${1+"$@"}'
+  & eval 'exec perl -w "$0" $argv:q'
+    if 0;
+
+use strict;
+use warnings;
+(my $ME = $0) =~ s|.*/||;
+
+# Emulate Git's choice of the editor for the commit message.
+chomp (my $editor = `git var GIT_EDITOR`);
+# And have a sane, minimal fallback in case of weird failures.
+$editor = "vi" if $? != 0 or $editor =~ /^\s*\z/;
+
+# Keywords allowed before the colon on the first line of a commit message:
+# program names and a few general category names.
+my @valid = qw(
+    hello
+
+    copy gnulib tests maint doc build scripts
+    );
+my $v_or = join '|', @valid;
+my $valid_regex = qr/^(?:$v_or)$/;
+
+# Rewrite the $LOG_FILE (old contents in @$LINE_REF) with an additional
+# a commented diagnostic "# $ERR" line at the top.
+sub rewrite($$$)
+{
+  my ($log_file, $err, $line_ref) = @_;
+  local *LOG;
+  open LOG, '>', $log_file
+    or die "$ME: $log_file: failed to open for writing: $!";
+  print LOG "# $err";
+  print LOG @$line_ref;
+  close LOG
+    or die "$ME: $log_file: failed to rewrite: $!\n";
+}
+
+sub re_edit($)
+{
+  my ($log_file) = @_;
+
+  warn "Interrupt (Ctrl-C) to abort...\n";
+
+  system 'sh', '-c', "$editor $log_file";
+  ($? & 127) || ($? >> 8)
+    and die "$ME: $log_file: the editor ($editor) failed, aborting\n";
+}
+
+sub bad_first_line($)
+{
+  my ($line) = @_;
+
+  $line =~ /^[Vv]ersion \d/
+    and return '';
+
+  $line =~ /:/
+    or return 'missing colon on first line of log message';
+
+  $line =~ /\.$/
+    and return 'do not use a period "." at the end of the first line';
+
+  # The token(s) before the colon on the first line must be on our list
+  # Tokens may be space- or comma-separated.
+  (my $pre_colon = $line) =~ s/:.*//;
+  my @word = split (/[ ,]/, $pre_colon);
+  my @bad = grep !/$valid_regex/, @word;
+  @bad
+    and return 'invalid first word(s) of summary line: ' . join (', ', @bad);
+
+  return '';
+}
+
+# Given a $LOG_FILE name and a address@hidden buffer,
+# read the contents of the file into the buffer and analyze it.
+# If the log message passes muster, return the empty string.
+# If not, return a diagnostic.
+sub check_msg($$)
+{
+  my ($log_file, $line_ref) = @_;
+
+  local *LOG;
+  open LOG, '<', $log_file
+    or return "failed to open for reading: $!";
+  @$line_ref = <LOG>;
+  close LOG;
+
+  my @line = @$line_ref;
+  chomp @line;
+
+  # Don't filter out blank or comment lines; git does that already,
+  # and if we were to ignore them here, it could lead to committing
+  # with lines that start with "#" in the log.
+
+  # Filter out leading blank and comment lines.
+  # while (@line && $line[0] =~ /^(?:#.*|[ \t]*)$/) { shift @line; }
+
+  # Filter out blank and comment lines at EOF.
+  # while (@line && $line[$#line] =~ /^(?:#.*|[ \t]*)$/) { pop @line; }
+
+  @line == 0
+    and return 'no log message';
+
+  my $bad = bad_first_line $line[0];
+  $bad
+    and return $bad;
+
+  # Second line should be blank or not present.
+  2 <= @line && length $line[1]
+    and return 'second line must be empty';
+
+  # Limit line length to allow for the ChangeLog's leading TAB.
+  foreach my $line (@line)
+    {
+      72 < length $line && $line =~ /^[^#]/
+       and return 'line longer than 72';
+    }
+
+  my $buf = join ("\n", @line) . "\n";
+  $buf =~ m!https?://bugzilla\.redhat\.com/show_bug\.cgi\?id=(\d+)!s
+    and return "use shorter http://bugzilla.redhat.com/$1";;
+
+  $buf =~ m!https?://debbugs\.gnu\.org/(?:cgi/bugreport\.cgi\?bug=)?(\d+)!s
+    and return "use shorter http://bugs.gnu.org/$1";;
+
+  $buf =~ /^ *Signed-off-by:/mi
+    and return q(do not use "Signed-off-by:");
+
+  return '';
+}
+
+{
+  @ARGV == 1
+    or die;
+
+  my $log_file = $ARGV[0];
+
+  while (1)
+    {
+      my @line;
+      my $err = check_msg $log_file, address@hidden;
+      $err eq ''
+       and last;
+      $err = "$ME: $err\n";
+      warn $err;
+      # Insert the diagnostic as a comment on the first line of $log_file.
+      rewrite $log_file, $err, address@hidden;
+      re_edit $log_file;
+
+      # Stop if our parent is killed.
+      getppid() == 1
+       and last;
+    }
+}
diff --git a/scripts/git-hooks/pre-applypatch b/scripts/git-hooks/pre-applypatch
new file mode 100755
index 0000000..b1f187c
--- /dev/null
+++ b/scripts/git-hooks/pre-applypatch
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+       exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff --git a/scripts/git-hooks/pre-commit b/scripts/git-hooks/pre-commit
new file mode 100755
index 0000000..18c4829
--- /dev/null
+++ b/scripts/git-hooks/pre-commit
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+       against=HEAD
+else
+       # Initial commit: diff against an empty tree object
+       against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+       # Note that the use of brackets around a tr range is ok here, (it's
+       # even required, for portability to Solaris 10's /usr/bin/tr), since
+       # the square bracket bytes happen to fall in the designated range.
+       test $(git diff --cached --name-only --diff-filter=A -z $against |
+         LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+       echo "Error: Attempt to add a non-ascii file name."
+       echo
+       echo "This can cause problems if you want to work"
+       echo "with people on other platforms."
+       echo
+       echo "To be portable it is advisable to rename the file ..."
+       echo
+       echo "If you know what you are doing you can disable this"
+       echo "check using:"
+       echo
+       echo "  git config hooks.allownonascii true"
+       echo
+       exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
-- 
2.2.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]