[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