I\'d like my remote repository to refuse any pushes that contains a file that contains a tab, but only if the file belongs in a certain class (based on the filename). Is that po
You could setup a pre-push hook, but this is not really in the spirit of the git publication mechanism.
I would rather go with:
Based on benprew's work, here's a pre-script hook that displays an error if any tab characters have been added, as well as the relevant line number. Save the following to .git/hooks/pre-commit
.
(Note: pre-commit
is the filename. There shouldn't be any .
extension)
#!/bin/sh
if git rev-parse --verify HEAD 2>/dev/null
then
git diff-index -p -M --cached HEAD
else
:
fi |
perl -e '
my $found_bad = 0;
my $filename;
my $reported_filename = "";
my $lineno;
sub bad_line {
my ($why, $line) = @_;
if (!$found_bad) {
print STDERR "*\n";
print STDERR "* You have some suspicious patch lines:\n";
print STDERR "*\n";
$found_bad = 1;
}
if ($reported_filename ne $filename) {
print STDERR "* In $filename\n";
$reported_filename = $filename;
}
print STDERR "* $why (line $lineno)\n";
print STDERR "$filename:$lineno:$line\n";
}
while (<>) {
if (m|^diff --git a/(.*) b/\1$|) {
$filename = $1;
next;
}
if (/^@@ -\S+ \+(\d+)/) {
$lineno = $1 - 1;
next;
}
if (/^ /) {
$lineno++;
next;
}
if (s/^\+//) {
$lineno++;
chomp;
if (/ /) {
bad_line("TAB character", $_);
}
}
}
exit($found_bad);
'
It's not exactly what you asked for since it doesn't do any filename checking, but hopefully it helps regardless.
Uh oh, this question seems to have slipped through the cracks. Hope you're still out there, Esben!
You're looking for an update hook, which is run once for each ref updated. The arguments are the name of the ref, the old object name (commit SHA1), and the new object name.
So, all you really need to do is check the diff between the old and new and make sure it meets your standards. This isn't totally straightforward, of course, but it's totally manageable. Here's what I'd do:
Save the following script to .git/hooks/update
.
old=$2
new=$3
# that's a literal tab, because (ba)sh turns \t into t, not a tab
# make sure your editor doesn't expand it to spaces
git diff --name-only $old $new | egrep '(\.(cpp|h)$)|^CMakeLists.txt$' | xargs -d'\n' git diff -U0 $old $new -- | grep -q '^+.* ' && exit 1
That lists all the files which differ between the old and new, greps for all the desired ones, gets the diff for them (with zero lines of context, since we don't care), and greps for an added line (starting with +
) containing a tab. The grep exits success if it finds one, which will let the &&
run exit 1
, causing the hook to exit failure and abort the update!
Note that this is slightly different from your requirements - it checks if the diff adds any tab characters. This is probably better in the long run; once you've made sure your existing code's okay, it's the same thing, except much faster since it doesn't have to search all the content.