#!/usr/local/bin/perl
#
# Developed using perl, version 5.004_04 built for sun4-solaris
#
# Perl filter to handle pre-commit checking of files.  This program
# records the last directory where commits will be taking place for
# use by the log_accum.pl script.  It also checks the end of line
# termination for files with particular extensions to ensure there
# is no ctrl-M.  If any file with checked extensions
# has any line ending in ctrl-M, the entire commit is rejected.
#
# Add a line to your CVSROOT/commitinfo file something like:
# DEFAULT /cvs_repository/CVSROOT/commit_prep.pl -r
#
# Copyright 2001 David Martin http://www.scm-professionals.com
#
# Adapted from contrib directory sources by:
# David Hampton <hampton@cisco.com> and Greg A. Woods <woods@web.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
#
#	Configurable options
#

# Constants
#
$LAST_FILE     = "/tmp/#cvs.lastdir"; # must match name in log_accum.pl
$ENTRIES       = "CVS/Entries";

#$CrLog = "%s is a text file and contains one or more ctrl-Ms.\nPlease remove ctrl-Ms and commit again!\n";
$CrLog = "%s contains one or more ctrl-Ms.\nPlease remove ctrl-Ms and commit again!\n";

#	Subroutines
#

sub write_line {
    local($filename, $line) = @_;
    open(FILE, ">$filename") || die("Cannot open $filename, stopped");
    print(FILE $line, "\n");
    close(FILE);
}

sub check_line_termination {
    local($i);
    local($filename, $cvsversion) = @_;

    open(FILE, "<$filename") || return(0);

    if ($debug != 0) {
	print STDERR sprintf("file = %s, version = %d.\n", $filename, $cvsversion{$filename});
    }

    @all_lines = ();
    for ($i = 0; <FILE>; $i++) {
	chomp;
	push(@all_lines, $_);
    }

    if (grep(/$/, @all_lines)) {
	print STDERR sprintf($CrLog, $filename);
	return(1);
    }

    return(0);
}

#
#	Main Body	
#

$id = getpgrp();              # You *must* use a shell that does setpgrp()!

# Record the directory for later use by the log_accumulate stript.
#
$record_directory = 0;

# parse command line arguments
#
while (@ARGV) {
    $arg = shift @ARGV;

    if ($arg eq '-d') {
	$debug = 1;
	print STDERR "Debug turned on...\n";
    } elsif ($arg eq '-r') {
	$record_directory = 1;
    } else {
	push(@files, $arg);
    }
}

$directory = shift @files;

if ($debug != 0) {
    print STDERR "dir   - ", $directory, "\n";
    print STDERR "files - ", join(":", @files), "\n";
}

# Suck in the CVS/Entries file
#
open(ENTRIES, $ENTRIES) || die("Cannot open $ENTRIES.\n");
while (<ENTRIES>) {
    local($filename, $version) = split('/', substr($_, 1));
    $cvsversion{$filename} = $version;
}

# Now check each file name passed in, except for dot files.  Dot files
# are considered to be administrative files by this script.
#
$failed = 0;
foreach $arg (@files) {
  if (index($arg, ".") == 0) {
    next;
  }
#  $result = `/usr/bin/file $arg`;
#  if ($debug != 0) {
#    print STDERR $result, "\n";
#  }
#  if ( ( $result =~ /:.*text/ ) ||
#       ( $result =~ /:.*script/ ) ) {
   if ( ( $arg =~ /akefile$/ ) ||
	( $arg =~ /.java$/ ) ||
	( $arg =~ /.html$/ ) ||
	( $arg =~ /.txt$/ ) ||
	( $arg =~ /.sql$/ ) ||
	( $arg =~ /.jsp$/ ) ||
	( $arg =~ /.shtml$/ ) ||
	( $arg =~ /.default$/ ) ||
	( $arg =~ /.mk$/ ) ||
	( $arg =~ /.env$/ ) ||
	( $arg =~ /.dtd$/ ) ||
	( $arg =~ /.ini$/ ) ||
	( $arg =~ /.jj$/ ) ||
	( $arg =~ /.pl$/ ) ||
	( $arg =~ /.policy$/ ) ||
	( $arg =~ /.properties$/ ) ||
	( $arg =~ /.sh$/ ) ||
	( $arg =~ /.xml$/ ) ) {
    if ($debug != 0) {
      print STDERR "Checking for line termination for file ", $arg, "\n";
    }
    $failed += &check_line_termination($arg);
  }
}
if ($failed) {
  print STDERR "\n";
  exit(1);
}

# Record this directory as the last one checked.  This will be used
# by the log_accumulate script to determine when it is processing
# the final directory of a multi-directory commit.
#
if ($record_directory != 0) {
    &write_line("$LAST_FILE.$id", $directory);
}
exit(0);
