head	1.24;
access;
symbols;
locks; strict;
comment	@# @;


1.24
date	2001.12.24.15.00.18;	author joe;	state Exp;
branches;
next	1.23;

1.23
date	2001.05.20.10.33.49;	author joe;	state Exp;
branches;
next	1.22;

1.22
date	2001.05.18.14.38.48;	author joe;	state Exp;
branches;
next	1.21;

1.21
date	2001.05.18.14.28.14;	author joe;	state Exp;
branches;
next	1.20;

1.20
date	2001.05.17.11.04.36;	author joe;	state Exp;
branches;
next	1.19;

1.19
date	2001.05.14.19.18.08;	author joe;	state Exp;
branches;
next	1.18;

1.18
date	2001.05.14.19.06.39;	author joe;	state Exp;
branches;
next	1.17;

1.17
date	2001.05.14.18.36.21;	author joe;	state Exp;
branches;
next	1.16;

1.16
date	2001.05.14.15.08.57;	author jlemon;	state Exp;
branches;
next	1.15;

1.15
date	2001.05.13.21.42.39;	author joe;	state Exp;
branches;
next	1.14;

1.14
date	2001.05.13.20.42.13;	author joe;	state Exp;
branches;
next	1.13;

1.13
date	2001.05.13.19.52.20;	author joe;	state Exp;
branches;
next	1.12;

1.12
date	2001.05.13.19.19.44;	author joe;	state Exp;
branches;
next	1.11;

1.11
date	2001.05.13.17.53.28;	author joe;	state Exp;
branches;
next	1.10;

1.10
date	2001.05.13.17.45.58;	author joe;	state Exp;
branches;
next	1.9;

1.9
date	2001.05.13.14.43.50;	author joe;	state Exp;
branches;
next	1.8;

1.8
date	2001.05.13.13.47.54;	author joe;	state Exp;
branches;
next	1.7;

1.7
date	2001.05.12.22.16.17;	author joe;	state Exp;
branches;
next	1.6;

1.6
date	2000.02.13.04.04.29;	author peter;	state Exp;
branches;
next	1.5;

1.5
date	99.09.19.13.11.03;	author peter;	state Exp;
branches;
next	1.4;

1.4
date	99.08.27.22.46.57;	author peter;	state Exp;
branches;
next	1.3;

1.3
date	99.04.05.21.24.49;	author jdp;	state Exp;
branches;
next	1.2;

1.2
date	97.06.08.16.56.46;	author peter;	state Exp;
branches;
next	1.1;

1.1
date	97.06.08.02.18.37;	author peter;	state Exp;
branches;
next	;


desc
@@


1.24
log
@Make sure that the user enters a commit message, and bomb out if
not.  This doesn't fix all cases of this because cvs doesn't invoke
loginfo/logcheck if the log message is completely blank.  Usually
there is an rcstemple in there though, so we'll catch most instances.
@
text
@#! /usr/bin/perl -w
#
# $FreeBSD$
#
# This hack is to sanitise the results of what the user may have
# "done" while editing the commit log message.. :-)   Peter Wemm.
#
# Note: this uses an enhancement to cvs's verifymsg functionality.
# Normally, the check is advisory only, the FreeBSD version reads
# back the file after the verifymsg file so that this script can
# make changes.
#

use strict;
use lib $ENV{CVSROOT};
use CVSROOT::cfg;


#############################################################
#
# Main Body
#
############################################################

my $filename = shift;
die "Usage: logcheck filename\n" unless $filename;




# Read the log file in, stripping 'CVS:' lines and removing trailing
# white spaces.
open IN, "< $filename" or
    die "logcheck: Cannot open for reading: $filename: $!\n";
my @@log_in = map { s/^(.*?)\s*$/$1/; $1 } grep { !/^CVS:/ } <IN>;
close IN;

# Remove duplicate blank lines.
my $i = 0;
while ($i < scalar(@@log_in) - 1) {
	if ($log_in[$i] eq "" && $log_in[$i + 1] eq "") {
		splice(@@log_in, $i, 1);
		next;
        }
        ++$i;
}

# Remove leading and trailing blank lines.  (There will be at most
# one because of the duplicate removal above).
shift @@log_in if $log_in[0] eq "";
pop @@log_in if $log_in[-1] eq "";

# Scan through the commit message looking for templated headers
# as defined in the configuration file, and rcstemplate.
# Assume that these only exist in the last paragraph.
# Filter out blank entries, and type check if necessary.
my $j = $#log_in;	# The index of the last entry in the commit msg.
my $error = 0;
while ($j >= 0) {
	my $logline = $log_in[$j];

	--$j;

	# Hitting a blank line means that we've seen all of the last paragraph.
	last if $logline eq "";

	unless ($logline =~ /^(.*?):\s*(.*)$/) {
		### XXX
		# We're here because we saw a line that didn't match
		# a template header (no ':').  This could be a continuation
		# line from the previous header, or the log message proper.
		# We don't know, so run the risk of checking the last paragraph
		# of the log message for headers.
		next;
	}

	my $header = $1;
	my $value = $2;
	my $pattern = $cfg::TEMPLATE_HEADERS{$header};

	# Ignore unrecognised headers.
	unless (defined($pattern)) {
	### 	print "Warning: unknown template header: $header\n";
		next;
	}

	# Filter out the template header if it's blank.
	if ($value eq "") {
		splice(@@log_in, $j + 1, 1);
		next;
	}

	# Type check the header
	unless ($value =~ /^$pattern$/) {
		print "Error: $header: should match '$pattern'.\n";
		++$error;
		next;
	}
}


# Make sure that there is some content in the log message.
# XXX Note that logcheck isn't evoked if the log message is
# completely empty.  This is a bug in cvs.
my $log = "@@log_in";
die "Log message contains no content!\n" if $log =~ /^\s*$/;


# Write the modified log file back out.
my $tmpfile = $filename . "tmp";
open OUT, "> $tmpfile" or
    die "logcheck: Cannot open for writing: $tmpfile: $!\n";
print OUT map { "$_\n" } @@log_in;
close OUT;


# Stop the commit if there was a problem with the template headers.
if ($error) {
	print "There were $error errors in the template headers.\n";
	print "Please fix the log message and commit again.\n";
	print "A copy of your log message was saved in $tmpfile.\n";
	exit 1;
}



# Nuke likely editor backups.
unlink "$filename.~";
unlink "$filename.bak";


# Overwrite the log message with our sanitised one.  (See the comment
# block at the top of this script for an explaination of why.)
rename($tmpfile, $filename) or
    die "logcheck: Could not rename $tmpfile to $filename: $!";

exit 0;
@


1.23
log
@Use the cfg.pm configuration file instead of hardcoding the template header
typecheck definitions in-line.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.22 2001/05/18 14:38:48 joe Exp $
d100 7
@


1.22
log
@Remove a trailing space in a comment.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.21 2001/05/18 14:28:14 joe Exp $
d15 2
a16 21


############################################################
#
# Configurable options
#
############################################################

# These are the optional headers that can be filled at the end of
# each commit message.  The associated value is a regular-expression
# that is used to type-check the entered value.  If the match failed
# then the commit is rejected.  (See rcstemplate).
my %HEADERS = (
	"Reviewed by"		=> '.*',
	"Submitted by"		=> '.*',
	"Obtained from"		=> '.*',
	"Approved by"		=> '.*',
	"PR"			=> '.*',
	"MFC after"		=> '\d+(?:\s+(?:days?|weeks?|months?))?'
);

d79 1
a79 1
	my $pattern = $HEADERS{$header};
@


1.21
log
@Rearrange the commit message parser for legibility.
@
text
@d3 2
a4 2
# $FreeBSD: CVSROOT/logcheck,v 1.20 2001/05/17 11:04:36 joe Exp $
# 
@


1.20
log
@Fix the trimming of trailing blank lines, to avoid a 'Use of
uninitialized value'.

Noticed by:	imp
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.19 2001/05/14 19:18:08 joe Exp $
d72 5
a76 3
# Filter out blank templated entries, and type check if necessary.
# (looking from the end of the commit message backwards)
my $j = scalar(@@log_in) - 1;
d78 3
a80 1
while ($j >= 0  and  my $header = $log_in[$j]) {
d83 2
a84 23
	if ($header =~ /^(.*?):\s*(.*)$/) {
		my $header = $1;
		my $value = $2;
		my $pattern = $HEADERS{$header};

		# Ignore unrecognised headers.
		unless (defined($pattern)) {
		### 	print "Warning: unknown template header: $header\n";
			next;
		}

		# Filter out the template header if it's blank.
		if ($value eq "") {
			splice(@@log_in, $j + 1, 1);
			next;
		}

		# Type check the header
		unless ($value =~ /^$pattern$/) {
			print "Error: $header: should match /^$pattern\$/.\n";
			++$error;
			next;
		}
d86 1
a86 1
	} else {
d93 23
@


1.19
log
@Be more careful when removing duplicate lines.  Remember that
perl considers "0" false, not true, so explicitly check each
line against "".
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.18 2001/05/14 19:06:39 joe Exp $
d57 1
a57 1
# Remove leading, trailing and duplicate blank lines.
d59 1
a59 1
while ($i < scalar(@@log_in)) {
d66 5
a70 1
shift @@log_in unless $log_in[0];
@


1.18
log
@Be more exact when checking for empty template entries to filter
from the log message.

Submitted by:	Ian Dowse <iedowse@@maths.tcd.ie>
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.17 2001/05/14 18:36:21 joe Exp $
d60 1
a60 1
	unless ($log_in[$i] or $log_in[$i + 1]) {
@


1.17
log
@Show the user why a failed syntax check occurred by showing the
regular expression that was used to perform the check.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.16 2001/05/14 15:08:57 jlemon Exp $
d87 1
a87 1
		unless ($value) {
@


1.16
log
@Make the "MFC after" syntax check match the claimed syntax.
Permit 'month[s]' as well, while I'm here; other scripts should
also be updated to accept this as well.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.15 2001/05/13 21:42:39 joe Exp $
d94 1
a94 1
			print "Error: syntax check failed for: $header\n";
@


1.15
log
@Remove a number of unnecessary warnings that occured whilst parsing
the log message.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.14 2001/05/13 20:42:13 joe Exp $
d33 1
a33 1
	"MFC after"		=> '[\d]+( (days|weeks))?'
@


1.14
log
@Relax the handling of seemingly extra lines in the templated header
block at the bottom of the commit log.  Committers are sometimes
wrapping lines and therefore introducing lines that don't look like
a header.

This change should return the previous behaviour.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.13 2001/05/13 19:52:20 joe Exp $
d80 1
a80 1
		# Warn and ignore unrecognised headers.
d82 1
a82 1
			print "Warning: unknown template header: $header\n";
d86 1
a86 1
		# Skip the header if it's blank.
d100 6
a105 3
		## print "Error: malformed line in template headers: $header\n";
		## ++$error;
		print "Warning: malformed line in template headers: $header\n";
@


1.13
log
@* Tidy up the error handling to make it clearer what's happening.
* If a commit fails because of a template error point the user to
  a saved copy of the log message for when they re-commit.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.12 2001/05/13 19:19:44 joe Exp $
d100 3
a102 2
		print "Error: malformed line in template headers: $header\n";
		++$error;
@


1.12
log
@By default defined template headers should match /^.*$/, not /^$/.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.11 2001/05/13 17:53:28 joe Exp $
d71 1
d82 1
a82 1
			print "Warning: unrecognised header: $header\n";
d94 3
a96 2
			print "Parse error in header ($header)\n";
			exit 1;
d100 3
a102 2
		print "Malformed line in with headers: $header\n";
		exit 1;
d115 10
d129 3
@


1.11
log
@Pull the templated headers and their associated type-checking
patterns into a configuration section at the top of the script.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.10 2001/05/13 17:45:58 joe Exp $
d28 5
a32 5
	"Reviewed by"		=> "",
	"Submitted by"		=> "",
	"Obtained from"		=> "",
	"Approved by"		=> "",
	"PR"			=> "",
@


1.10
log
@Remove trailing spaces in the log message correctly.

PR:
Submitted by:
Reviewed by:
Approved by:
Obtained from:
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.9 2001/05/13 14:43:50 joe Exp $
d16 28
a45 4
my $tmpfile = $filename . "tmp";

open(IN, "< $filename") ||
	die "logcheck: Cannot open for reading: $filename: $!\n";
a46 2
open(OUT, "> $tmpfile") ||
	die "logcheck: Cannot open for writing: $tmpfile: $!\n";
d52 4
a55 1
my @@log_in = map { s/^(.*?)\s*$/$1/; $_ } grep { !/^CVS:/ } <IN>;
d69 15
a83 9
foreach (@@log_in) {
	# Delete if they only have whitespace after them.
	if (/^Reviewed by:$/i ||
	    /^Submitted by:$/i ||
	    /^Obtained from:$/i ||
	    /^Approved by:$/i ||
	    /^PR:$/i) {
		next;
	}
d85 5
a89 4
	# Special handling for type checking the 'MFC after' field.
	if (/^MFC after:\s*(.*)$/) {
		# Ignore it if no value was filled in.
		next unless $1;
d91 3
a93 2
		unless ($1 =~ /[\d]+ (days?|weeks?)$/) {
			print "Parse error in 'MFC after:'\n";
d96 4
d101 2
d104 5
a108 3
	print OUT "$_\n";
}
close IN;
d111 1
d116 2
a117 2
rename("$tmpfile", "$filename") ||
	die "logcheck: Could not rename $tmpfile to $filename: $!";
@


1.9
log
@Simplify the script.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.21 2001/05/13 14:33:06 joe Exp $
d30 1
a30 1
my @@log_in = map { s/^(.*)\s*$/$1/; $1 } grep { !/^CVS:/ } <IN>;
@


1.8
log
@Clean up a new nits and run this using 'strict'.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.7 2001/05/12 22:16:17 joe Exp $
d17 1
a17 3
unless ($filename) {
	die "Usage: logcheck filename\n";
}
a25 9
# In-place edit the result of the user's edit on the file.
my $blank = 0;	# true if the last line was blank
my $first = 0;	# true if we have seen the first real text

while(<IN>) {
	# Dont let CVS: lines upset things, strip them out.
	if (/^CVS:/) {
		next;
	}
a26 2
	chomp;		# strip trailing newline
	s/[\s]+$//;	# strip trailing whitespace
d28 9
a36 4
	# collapse multiple blank lines, and trailing blank lines.
	if (/^$/) {
		# Blank line. Remember in case more text follows.
		$blank = 1;
d38 4
a41 9
	} else {
		# Delete if they only have whitespace after them.
		if (/^Reviewed by:$/i ||
		    /^Submitted by:$/i ||
		    /^Obtained from:$/i ||
		    /^Approved by:$/i ||
		    /^PR:$/i) {
			next;
		}
d43 10
a52 10
		# Special handling for type checking the 'MFC after' field.
		if (/^MFC after:\s*(.*)$/) {
			# Ignore it if no value was filled in.
			next unless $1;

			unless ($1 =~ /[\d]+ (days?|weeks?)$/) {
				print "Parse error in 'MFC after:'\n";
				exit 1;
			}
		}
d54 8
a61 4
		if ($blank && $first) {
			# Previous line(s) was blank, this isn't. Close the
			# collapsed section.
			print OUT "\n";
a62 3
		$blank = 0;	# record non-blank
		$first = 1;	# record first line
		print OUT "$_\n";
d64 2
d67 2
a68 2
close(IN);
close(OUT);
d70 3
a72 2
unlink($filename . "~");	# Nuke likely editor backups..
unlink($filename . ".bak");	# Nuke likely editor backups..
d75 1
a75 1
	die("logcheck: Could not rename $tmpfile to $filename: $!");
d77 1
a77 1
exit(0);
@


1.7
log
@Recently Maxim Sobolev <sobomax@@FreeBSD.org> introduced an MFC
notification service driven from 'MFC after:' headers in the commit
message.

This commit adds 'MFC after:' into the rcstemplate and associated
code to make sure that if it's used it's used correctly.

Based upon code submitted by Maxim Sobolev <sobomax@@FreeBSD.org>.

Submitted by:	sobomax
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.6 2000/02/13 04:04:29 peter Exp $
d11 1
a11 1
# can make changes.
d14 4
a17 1
if (!@@ARGV) {
d20 1
a20 2
$filename = $ARGV[0];
$tmpfile = $filename . "tmp";
d29 3
a31 2
$blank = 0;	# true if the last line was blank
$first = 0;	# true if we have seen the first real text
a32 1

d38 1
a38 1
	chop;		# strip trailing newline
d66 1
a66 1
				
@


1.6
log
@Update the commit scripts to understand 'Approved by:' and kill cvsedit.
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.5 1999/09/19 13:11:03 peter Exp $
d53 12
@


1.5
log
@Sync with internat.freebsd.org crypto repo.  (part 1)

Submitted by:	markm
@
text
@d3 1
a3 1
# $FreeBSD: CVSROOT/logcheck,v 1.4 1999/08/27 22:46:57 peter Exp $
d21 1
a21 1
	die "cvsedit: Cannot open for reading: $filename: $!\n";
d24 1
a24 1
	die "cvsedit: Cannot open for writing: $tmpfile: $!\n";
d49 1
@


1.4
log
@$Id$ -> $FreeBSD$
@
text
@d1 1
a1 1
#! /usr/bin/perl
d3 1
a3 1
# $FreeBSD$
@


1.3
log
@Take perl from /usr/bin rather than /usr/local/bin.
@
text
@d3 1
a3 1
# $Id: logcheck,v 1.2 1997/06/08 16:56:46 peter Exp $
@


1.2
log
@Cosmetic, use same perl as the other scripts
@
text
@d1 1
a1 1
#! /usr/local/bin/perl
d3 1
a3 1
# $Id: logcheck,v 1.1 1997/06/08 02:18:37 peter Exp $
@


1.1
log
@Checkin of eventual replacement for the editinfo stuff.  This will be run
from the verifymsg hook to clean the log message on all commits including
remote ones, cvs commit -m 'msg' and cvs commit -F msgfile, rather than
just local commits on freefall with the editor.
@
text
@d1 1
a1 1
#! /usr/bin/perl
d3 1
a3 1
# $Id$
@
