Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [cdt-patch] Re: [cdt-dev] commit list

Thanks Tom. I have sent the request to the Eclipse webmasters and
await a response. I'm hoping this will be straightforward and that
no infrastructure issues will get in the way.

Sebastien

> 
> Sebastien> Tom, can you first email the scripts so we can figure out
> Sebastien> how to hook it into the cvs server?
> 
> I went ahead and made a patch against the CDT CVSROOT.
> A couple notes:
> 
> * Search for FIXME in the patch to see where the name of the mailing
>   list should be inserted
> 
> * Make sure log_accum and commit_prep are chmod +x before `cvs add'ing
>   them.
> 
> * I looked up the URL, so this patch puts cvsweb URLs into the commit
>   messages
> 
> * If your perl isn't in /usr/bin, you'll have to change the scripts a
>   little.  (I don't know what kind of box dev.eclipse.org is...)
> 
> I'm happy to help with debugging if required.
> 
> Tom
> 
> Index: checkoutlist
> ===================================================================
> RCS file: /home/tools/CVSROOT/checkoutlist,v
> retrieving revision 1.1
> diff -u -r1.1 checkoutlist
> --- checkoutlist 6 Dec 2001 18:45:46 -0000 1.1
> +++ checkoutlist 8 Oct 2002 20:59:52 -0000
> @@ -11,3 +11,5 @@
>  #	[<whitespace>]<filename><whitespace><error message><end-of-line>
>  #
>  # comment lines begin with '#'
> +log_accum	CVS commits will continue to use the old script
> +commit_prep	CVS commits will continue to use the old script
> Index: commit_prep
> ===================================================================
> RCS file: commit_prep
> diff -N commit_prep
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ commit_prep 8 Oct 2002 20:59:53 -0000
> @@ -0,0 +1,249 @@
> +#!/usr/bin/perl
> +# -*-Perl-*-
> +#
> +# $Id: commit_prep,v 1.7 2001/12/07 08:59:38 jsm Exp $
> +#
> +# 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.  For new files, it forces the
> +# existence of a RCS "Id" keyword in the first ten lines of the file.
> +# For existing files, it checks version number in the "Id" line to
> +# prevent losing changes because an old version of a file was copied
> +# into the direcory.
> +#
> +# Possible future enhancements:
> +#
> +#    Check for cruft left by unresolved conflicts.  Search for
> +#    "^<<<<<<<$", "^-------$", and "^>>>>>>>$".
> +#
> +#    Look for a copyright and automagically update it to the
> +#    current year.  [[ bad idea!  -- woods ]]
> +#
> +#
> +# Contributed by David Hampton <hampton@xxxxxxxxx>
> +#
> +# Hacked on lots by Greg A. Woods <woods@xxxxxxx>
> +
> +#
> +#	Configurable options
> +#
> +
> +# Constants (remember to protect strings from RCS keyword 
> substitution)
> +#
> +$ENTRIES       = "CVS/Entries";
> +
> +$TMPDIR = "/sourceware/cvs-tmp";
> +
> +# Patterns to find $Log keywords in files
> +#
> +$LogString1 = "\\\$\\Log: .* \\\$";
> +$LogString2 = "\\\$\\Log\\\$";
> +$NoLog = "%s - contains an RCS \$Log keyword.  It must not!\n";
> +
> +# pattern to match an RCS Id keyword line with an existing ID
> +#
> +$IDstring = "\"@\\(#\\)[^:]*:.*\\\$\Id: .*\\\$\"";
> +$NoId = "
> +%s - Does not contain a properly formatted line with the 
> keyword \"Id:\".
> +	I.e. no lines match \"" . $IDstring . "\".
> +	Please see the template files for an example.\n";
> +
> +# pattern to match an RCS Id keyword line for a new file 
> (i.e. un-expanded)
> +#
> +$NewId = "\"@(#)[^:]*:.*\\$\Id\\$\"";
> +
> +$NoName = "
> +%s - The ID line should contain only 
> \"@(#)module/path:\$Name\$:\$\Id\$\"
> +	for a newly created file.\n";
> +
> +$BadName = "
> +%s - The file name '%s' in the ID line does not match
> +	the actual filename.\n";
> +
> +$BadVersion = "
> +%s - How dare you!!!  You replaced your copy of the file '%s',
> +	which was based upon version %s, with an %s version based
> +	upon %s.  Please move your '%s' out of the way, perform an
> +	update to get the current version, and them merge your changes
> +	into that file, then try the commit again.\n";
> +
> +#
> +#	Subroutines
> +#
> +
> +sub write_line {
> +    local($filename, $line) = @_;
> +    open(FILE, ">$filename") || die("Cannot open $filename: $!\n");
> +    print(FILE $line, "\n");
> +    close(FILE);
> +}
> +
> +sub check_version {
> +    local($i, $id, $rname, $version);
> +    local($filename, $cvsversion) = @_;
> +
> +    open(FILE, "<$filename") || return(0);
> +
> +    @all_lines = ();
> +    $idpos = -1;
> +    $newidpos = -1;
> +    for ($i = 0; <FILE>; $i++) {
> +	chop;
> +	push(@all_lines, $_);
> +	if ($_ =~ /$IDstring/) {
> +	    $idpos = $i;
> +	}
> +	if ($_ =~ /$NewId/) {
> +	    $newidpos = $i;
> +	}
> +    }
> +
> +    if (grep(/$LogString1/, @all_lines) || 
> grep(/$LogString2/, @all_lines)) {
> +	print STDERR sprintf($NoLog, $filename);
> +	return(1);
> +    }
> +
> +    if ($debug != 0) {
> +	print STDERR sprintf("file = %s, version = %d.\n", 
> $filename, $cvsversion{$filename});
> +    }
> +
> +    if ($cvsversion{$filename} == 0) {
> +	if ($newidpos != -1 && $all_lines[$newidpos] !~ /$NewId/) {
> +	    print STDERR sprintf($NoName, $filename);
> +	    return(1);
> +	}
> +	return(0);
> +    }
> +
> +    if ($idpos == -1) {
> +	print STDERR sprintf($NoId, $filename);
> +	return(1);
> +    }
> +
> +    $line = $all_lines[$idpos];
> +    $pos = index($line, "Id: ");
> +    if ($debug != 0) {
> +	print STDERR sprintf("%d in '%s'.\n", $pos, $line);
> +    }
> +    ($id, $rname, $version) = split(' ', substr($line, $pos));
> +    if ($rname ne "$filename,v") {
> +	print STDERR sprintf($BadName, $filename, 
> substr($rname, 0, length($rname)-2));
> +	return(1);
> +    }
> +    if ($cvsversion{$filename} < $version) {
> +	print STDERR sprintf($BadVersion, $filename, $filename, 
> $cvsversion{$filename},
> +			     "newer", $version, $filename);
> +	return(1);
> +    }
> +    if ($cvsversion{$filename} > $version) {
> +	print STDERR sprintf($BadVersion, $filename, $filename, 
> $cvsversion{$filename},
> +			     "older", $version, $filename);
> +	return(1);
> +    }
> +    return(0);
> +}
> +
> +#
> +#	Main Body	
> +#
> +
> +$id = getpgrp();		# You *must* use a shell that 
> does setpgrp()!
> +
> +# Check each file (except dot files) for an RCS "Id" keyword.
> +#
> +$check_id = 0;
> +
> +# Record the directory for later use by the log_accumulate stript.
> +#
> +$record_directory = 0;
> +
> +# Default temp file prefix.
> +$temp_name = 'temp';
> +
> +# parse command line arguments
> +#
> +while (@ARGV) {
> +    $arg = shift @ARGV;
> +
> +    if ($arg eq '-d') {
> +	$debug = 1;
> +	print STDERR "Debug turned on...\n";
> +    } elsif ($arg eq '-c') {
> +	$check_id = 1;
> +    } elsif ($arg eq '-r') {
> +	$record_directory = 1;
> +    } elsif ($arg eq '-T') {
> +	$temp_name = shift @ARGV;
> +    } elsif ($arg eq '-L') {
> +	$log_name = shift @ARGV;
> +    } else {
> +	push(@files, $arg);
> +    }
> +}
> +
> +$LAST_FILE     = sprintf ("$TMPDIR/#%s.lastdir", $temp_name);
> +
> +$directory = shift @files;
> +
> +if ($debug != 0) {
> +    print STDERR "dir   - ", $directory, "\n";
> +    print STDERR "files - ", join(":", @files), "\n";
> +    print STDERR "id    - ", $id, "\n";
> +}
> +
> +# Keep a record of all files modified, and the times they 
> were modified,
> +# for optimized remote copying (e.g. periodically rsyncing over only
> +# the files which have been modified).
> +
> +if (defined ($log_name)) {
> +    if ($directory =~ m#^$ENV{"CVSROOT"}([/.])*/(.*)#) {
> +        $print_dir = $2;
> +    } else {
> +        $print_dir = $directory;
> +    }
> +        
> +    $now = time ();
> +    if (open LOGFILE, ">> $log_name") {
> +        foreach (@files) {
> +            print LOGFILE "$now $print_dir/$_\n";
> +        }
> +        close (LOGFILE);
> +        if ($debug != 0) {
> +            print STDERR "Wrote commit log entries to $log_name\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.
> +#
> +if ($check_id != 0) {
> +    $failed = 0;
> +    foreach $arg (@files) {
> +	if (index($arg, ".") == 0) {
> +	    next;
> +	}
> +	$failed += &check_version($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);
> Index: commitinfo
> ===================================================================
> RCS file: /home/tools/CVSROOT/commitinfo,v
> retrieving revision 1.1
> diff -u -r1.1 commitinfo
> --- commitinfo 6 Dec 2001 18:45:46 -0000 1.1
> +++ commitinfo 8 Oct 2002 20:59:53 -0000
> @@ -13,3 +13,5 @@
>  #
>  # If the name "ALL" appears as a regular expression it is always used
>  # in addition to the first matching regex or "DEFAULT".
> +
> +DEFAULT		/home/tools/CVSROOT/commit_prep -T cdt -r
> Index: log_accum
> ===================================================================
> RCS file: log_accum
> diff -N log_accum
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ log_accum 8 Oct 2002 20:59:56 -0000
> @@ -0,0 +1,946 @@
> +#!/usr/bin/perl
> +# -*-Perl-*-
> +#
> +# Perl filter to handle the log messages from the checkin of files in
> +# a directory.  This script will group the lists of files by log
> +# message, and mail a single consolidated log message at the end of
> +# the commit.
> +#
> +# This file assumes a pre-commit checking program that leaves the
> +# names of the first and last commit directories in a temporary file.
> +#
> +# Contributed by David Hampton <hampton@xxxxxxxxx>
> +#
> +# hacked greatly by Greg A. Woods <woods@xxxxxxx>
> +
> +# Usage: log_accum.pl [-d] [-s] [-M module] [[-m mailto] 
> ...] [-f logfile]
> +#	-d		- turn on debugging
> +#       -G database     - interface to Gnats
> +#	-m mailto	- send mail to "mailto" (multiple)
> +#	-M modulename	- set module name to "modulename"
> +#	-f logfile	- write commit messages to logfile too
> +#	-s		- *don't* run "cvs status -v" for each file
> +#       -T text         - use TEXT in temp file names.
> +#       -C name         - Generate cvsweb URLS; must be run 
> using %{sVv}
> +#                         format string.
> +#       -U URL          - Base URL for cvsweb if -C option 
> (above) is used.
> +#       -D DOMAIN       - Domain from which mail should appear
> +#       -l              - Update list of modified files in 
> CVSROOT/commits.  
> +#                         Must be run using %{sVv}.
> +
> +use POSIX;
> +
> +#
> +#	Configurable options
> +#
> +
> +$TMPDIR = "/sourceware/cvs-tmp";
> +
> +# Set this to something that takes "-s"
> +$MAILER	       = "/usr/bin/Mail";
> +
> +# Used with sprintf to form name of Gnats root directory.  Potential
> +# PR info is appended to see if PR actually exists.  %s 
> argument comes
> +# from -G option.
> +$GNATS_ROOT_FORMAT = "/sourceware/gnats/%s-db";
> +
> +# Base name of cvsweb specification.
> +$CVSWEB_URL = "http://sources.redhat.com/cgi-bin/cvsweb.cgi/";;
> +
> +# Constants (don't change these!)
> +#
> +$STATE_NONE    = 0;
> +$STATE_CHANGED = 1;
> +$STATE_ADDED   = 2;
> +$STATE_REMOVED = 3;
> +$STATE_LOG     = 4;
> +
> +#
> +#	Subroutines
> +#
> +
> +sub set_temp_vars {
> +    local ($name) = @_;
> +
> +    $LAST_FILE     = sprintf ("$TMPDIR/#%s.lastdir", $name);
> +
> +    $CHANGED_FILE  = sprintf ("$TMPDIR/#%s.files.changed", $name);
> +    $ADDED_FILE    = sprintf ("$TMPDIR/#%s.files.added", $name);
> +    $REMOVED_FILE  = sprintf ("$TMPDIR/#%s.files.removed", $name);
> +    $LOG_FILE      = sprintf ("$TMPDIR/#%s.files.log", $name);
> +    $URL_FILE      = sprintf ("$TMPDIR/#%s.files.urls", $name);
> +    $COMMITS_FILE  = sprintf ("$TMPDIR/#%s.files.commits", $name);
> +
> +    # Quote for use in a regexp.
> +    ($FILE_PREFIX   = sprintf ("#%s.files", $name)) =~ s/(\W)/\\$1/g;
> +}
> +
> +sub cleanup_tmpfiles {
> +    local($wd, @files);
> +
> +    $wd = `pwd`;
> +    chdir("$TMPDIR") || die("Can't chdir(\"$TMPDIR\")\n");
> +    opendir(DIR, ".");
> +    push(@files, grep(/^$FILE_PREFIX\..*\.$id$/, readdir(DIR)));
> +    closedir(DIR);
> +    foreach (@files) {
> +	unlink $_;
> +    }
> +    unlink $LAST_FILE . "." . $id;
> +
> +    chdir($wd);
> +}
> +
> +sub write_logfile {
> +    local($filename, @lines) = @_;
> +
> +    open(FILE, ">$filename") || die("Cannot open log file 
> $filename.\n");
> +    print FILE join("\n", @lines), "\n";
> +    close(FILE);
> +}
> +
> +sub format_names {
> +    local($dir, @files) = @_;
> +    local(@lines);
> +
> +    if ($dir =~ /^\.\//) {
> +	$dir = $';
> +    }
> +    if ($dir =~ /\/$/) {
> +	$dir = $`;
> +    }
> +    if ($dir eq "") {
> +	$dir = ".";
> +    }
> +
> +    $format = "\t%-" . sprintf("%d", length($dir) > 15 ? 
> length($dir) : 15) . "s%s ";
> +
> +    $lines[0] = sprintf($format, $dir, ":");
> +
> +    if ($debug) {
> +	print STDERR "format_names(): dir = ", $dir, "; files = 
> ", join(":", @files), ".\n";
> +    }
> +    foreach $file (@files) {
> +	if (length($lines[$#lines]) + length($file) > 65) {
> +	    $lines[++$#lines] = sprintf($format, " ", " ");
> +	}
> +	$lines[$#lines] .= $file . " ";
> +    }
> +
> +    @lines;
> +}
> +
> +sub format_lists {
> +    local(@lines) = @_;
> +    local(@text, @files, $lastdir);
> +
> +    if ($debug) {
> +	print STDERR "format_lists(): ", join(":", @lines), "\n";
> +    }
> +    @text = ();
> +    @files = ();
> +    $lastdir = shift @lines;	# first thing is always a directory
> +    if ($lastdir !~ /.*\/$/) {
> +	die("Damn, $lastdir doesn't look like a directory!\n");
> +    }
> +    foreach $line (@lines) {
> +	if ($line =~ /.*\/$/) {
> +	    push(@text, &format_names($lastdir, @files));
> +	    $lastdir = $line;
> +	    @files = ();
> +	} else {
> +	    push(@files, $line);
> +	}
> +    }
> +    push(@text, &format_names($lastdir, @files));
> +
> +    @text;
> +}
> +
> +sub accum_subject {
> +    local(@lines) = @_;
> +    local(@files, $lastdir);
> +
> +    $lastdir = shift @lines;	# first thing is always a directory
> +    @files = ($lastdir);
> +    if ($lastdir !~ /.*\/$/) {
> +	die("Damn, $lastdir doesn't look like a directory!\n");
> +    }
> +    foreach $line (@lines) {
> +	if ($line =~ /.*\/$/) {
> +	    $lastdir = $line;
> +	    push(@files, $line);
> +	} else {
> +	    push(@files, $lastdir . $line);
> +	}
> +    }
> +
> +    @files;
> +}
> +
> +sub compile_subject {
> +    local(@files) = @_;
> +    local($text, @a, @b, @c, $dir, $topdir, $topdir_length);
> +
> +    # find the highest common directory
> +    $dir = '-';
> +    do {
> +	$topdir = $dir;
> +	foreach $file (@files) {
> +	    if ($file =~ /.*\/$/) {
> +		if ($dir eq '-') {
> +		    $dir = $file;
> +		} else {
> +		    if (index($dir,$file) == 0) {
> +			$dir = $file;
> +		    } elsif (index($file,$dir) != 0) {
> +			@a = split /\//,$file;
> +			@b = split /\//,$dir;
> +			@c = ();
> +			CMP: while ($#a > 0 && $#b > 0) {
> +			    if ($a[0] eq $b[0]) {
> +				push(@c, $a[0]);
> +				shift @a;
> +				shift @b;
> +			    } else {
> +				last CMP;
> +			    }
> +			}
> +			$dir = join('/',@c) . '/';
> +		    }
> +		}
> +	    }
> +	}
> +    } until $dir eq $topdir;
> +
> +    # strip out directories and the common prefix topdir.
> +    chop $topdir;
> +
> +    if ($topdir eq "") {
> +        @c = $modulename;
> +        $topdir_length = 0;
> +    } else {
> +        if ($topdir eq ".") {
> +            @c = $modulename;
> +        } else {
> +            @c = ($modulename . '/' . $topdir);
> +        }
> +        $topdir_length = length ($topdir) + 1;
> +    }
> +
> +    foreach $file (@files) {
> +        if ($file !~ /.*\/$/) {
> +            push(@c, substr($file, $topdir_length));
> +        }
> +    }
> +
> +    # put it together and limit the length.
> +    $text = join(' ',@c);
> +    if (length($text) > 50) {
> +	$text = substr($text, 0, 46) . ' ...';
> +    }
> +
> +    $text;
> +}
> +
> +sub append_names_to_file {
> +    local($filename, $dir, @files) = @_;
> +
> +    if (@files) {
> +	open(FILE, ">>$filename") || die("Cannot open file 
> $filename.\n");
> +	if (defined ($dir)) {
> +            print FILE $dir, "\n";
> +        }
> +	print FILE join("\n", @files), "\n";
> +	close(FILE);
> +    }
> +}
> +
> +sub read_line {
> +    local($line);
> +    local($filename) = @_;
> +
> +    open(FILE, "<$filename") || die("Cannot open file $filename.\n");
> +    $line = <FILE>;
> +    close(FILE);
> +    chop($line);
> +    $line;
> +}
> +
> +sub read_logfile {
> +    local(@text);
> +    local($filename, $leader) = @_;
> +
> +    open(FILE, "<$filename");
> +    while (<FILE>) {
> +	chop;
> +	push(@text, $leader.$_);
> +    }
> +    close(FILE);
> +    @text;
> +}
> +
> +sub build_header {
> +    local($header);
> +    local($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
> +    $header = sprintf("CVSROOT:\t%s\nModule name:\t%s\n",
> +		      $cvsroot,
> +		      $modulename);
> +    if (defined($branch)) {
> +	$header .= sprintf("Branch: \t%s\n",
> +		      $branch);
> +    }
> +    $header .= sprintf("Changes by:\t%s@%s\t%04d-%02d-%02d 
> %02d:%02d:%02d",
> +		      $login, $hostdomain,
> +		      $year + 1900, $mon+1, $mday,
> +		      $hour, $min, $sec);
> +}
> +
> +sub mail_notification {
> +    local($name, $subject, @text) = @_;
> +    open(MAIL, "| $MAILER -s \"$subject\" $name");
> +    print MAIL join("\n", @text), "\n";
> +    close(MAIL);
> +}
> +
> +sub write_commitlog {
> +    local($logfile, @text) = @_;
> +
> +    open(FILE, ">>$logfile");
> +    print FILE join("\n", @text), "\n\n";
> +    close(FILE);
> +}
> +
> +# Return a list of all cvsweb URLs for this commit.
> +sub generate_cvsweb_urls {
> +    local ($dir, $branch, @files) = @_;
> +    local (@sp, @result);
> +    local ($start) = $CVSWEB_URL . $dir . '/';
> +    local ($args) = '.diff?cvsroot=' . $cvsweb_name;
> +    if ($branch ne '') {
> +	$args .= '&only_with_tag=' . $branch;
> +    }
> +    local ($r1);
> +    foreach (@files) {
> +	# List is (FILE OLD-REV NEW-REV).
> +	@sp = split (',');
> +	$r1 = $sp[1];
> +	if ($r1 eq 'NONE') {
> +	    # This lets us make a diff corresponding to the first
> +	    # revision.
> +	    $r1 = '0';
> +	}
> +	push (@result, ($start . $sp[0] . $args
> +			. '&r1=' . $sp[1] . '&r2=' . $sp[2]));
> +    }
> +    return @result;
> +}
> +
> +######
> +## cvs commits logging for processing by other programs
> +##
> +## Everything takes place in $CVSROOT/commits - as long as 
> that dir is
> +## writable and exists, the functions should handle the rest.
> +######
> +
> +sub generate_modlist {
> +   my $path = shift;
> +   my $changed_files = shift;  # incl operation, but not what rev #
> +   my $added_files = shift;
> +   my $removed_files = shift;
> +   my @filerevs = @_;          # incl revision #'s but not 
> what op changed them
> +
> +   my @filelist = ();
> +
> +   if ($#changed_files >= 0) {
> +     push @filelist, modlist_add_files ("chg", $path, 
> $changed_files, 
> +                                        \@filerevs);
> +   }
> +   if ($#added_files >= 0) {
> +       push @filelist, modlist_add_files ("add", $path, 
> $added_files, 
> +                                          \@filerevs);
> +   }
> +   if ($#removed_files >= 0) {
> +       push @filelist, modlist_add_files ("rm", $path, 
> $removed_files, 
> +                                          \@filerevs);
> +   }
> +
> +   return @filelist;
> +}
> +
> +sub modlist_add_files {
> +   my ($type, $topdir, $filelist, $filerevs) = @_;
> +
> +   my $type_print = $type;
> +   my @lines_to_add = ();
> +
> +   $topdir =~ s#^\./##;
> +   $topdir =~ s#/$##;
> +   $topdir =~ s#^\.$##;
> +
> +   if ($topdir eq "./" || $topdir eq ".") {
> +      $topdir = "";
> +   } else {
> +      $topdir = $topdir . "/";
> +   }
> +
> +   foreach $entry (@$filelist) {
> +     my $revs = modlist_get_file_revs ($entry, $filerevs);
> +     my $revstr = "NA NA";
> +     if (defined ($revs)) {
> +       $revstr = "@$revs[0] @$revs[1]";
> +     }
> +
> +     if (defined ($branch)) {
> +         $type_print = "${type},branch=$branch";
> +     }
> +     if ($type eq "rm") {
> +       push @lines_to_add, "$type_print $revstr 
> ${topdir}Attic/" . $entry;
> +     }
> +     push @lines_to_add, "$type_print $revstr $topdir" . $entry;
> +  }
> +
> +  return @lines_to_add;
> +}
> +
> +sub modlist_get_file_revs {
> +   my $desired_filename = shift;
> +   my $filerevs = shift;
> +
> +   my $filename = undef;
> +   my $oldrev = "NONE";
> +   my $newrev = "NONE";
> +   my @revpair;
> +
> +   foreach (@$filerevs) {
> +     if (m#^\Q${desired_filename}\E#) {
> +       if (m/(.*),([0-9.NONE]*),([0-9.NONE]*)$/) {
> +          $filename = $1;
> +          $oldrev = $2;
> +          $newrev = $3;
> +       } elsif ($desired_filename eq $_) {
> +          $filename = $_;
> +       }
> +     }
> +   }
> +
> +   if (!defined ($filename)) {
> +      return undef;
> +   }
> +
> +   @revpair = ($oldrev, $newrev);
> +   return \@revpair;
> +}
> +
> +sub modlist_newdir {
> +   my $dirname = shift;
> +
> +   my @filelist = ();
> +
> +   $dirname =~ s#^\./##;
> +   $dirname =~ s#^/##;
> +   $dirname =~ s#/$##;
> +   $dirname = $dirname . "/";
> +   
> +   push @filelist, "newdir NA NA " . $dirname;
> +   modlist_write_to_log (@filelist);
> +}
> +
> +sub modlist_import {
> +   my $parent_dir = shift;
> +   my $text = shift;
> +
> +   my @filelist = ();
> +
> +   $parent_dir =~ s#/$##;
> +   foreach (@$text) {
> +      chomp;
> +      if (m/^    ([UNC]) (.*)/) {
> +          my $type = $1;
> +          my $file = $2;
> +          $file =~ s#^\./##;
> +          $file =~ s#^/##;
> +          push @filelist, "import,stat=$type NA NA " . $file;
> +      }
> +   }
> +
> +   modlist_write_to_log (@filelist);
> +}
> +
> +# Add lines to the commit list logfile of the format
> +# <EPOCH SECONDS> <USERNAME> <TYPE OF CMD> <OLDREV> <NEWREV> 
> <FILENAME/DIRNAME>
> +
> +sub modlist_write_to_log {
> +   my @files = @_;
> +   my @lines = ();
> +   my $now = time ();
> +   my $month = sprintf ("%02d", (localtime)[4] + 1);
> +   my $year = (localtime)[5] + 1900;
> +
> +   my $root_dir = "$cvsroot/CVSROOT/commits";
> +   my $logdir = "$root_dir/commit-logs";
> +   my $logfile = "$logdir/${year}-${month}";
> +   my $plugins = "$root_dir/plugins";
> +
> +   foreach my $dir ("$root_dir", "$logdir")
> +     {
> +       if (! -d "$dir")
> +         {
> +           mkdir ("$dir", 0777) or warn "Unable to create 
> commit-list log dir $dir";
> +           chmod 0777, "$dir";
> +         }
> +     }
> +
> +# Remove "./" at the beg of filenames; add ",v" at the end 
> of filenames,
> +# add username/timestamp to each line for printing.
> +
> +   foreach my $f (@files) {
> +       next if (!defined ($f) or $f eq "");
> +       $f =~ s#^\./##;
> +       $f =~ s# \./# #;
> +       if ($f !~ m#/$# && $f !~ m#,v$#) {
> +          $f = $f . ",v";
> +       }
> +       if ($f =~ m#(.*)/$#) {
> +          $f = $1;
> +       }
> +       push @lines, "$now $login $f\n";
> +   }
> +
> +## Save the commit lines to the main log file
> +      
> +   if (open LOG, ">> $logfile") {
> +      foreach (@lines) {
> +         print LOG;
> +       }
> +      close (LOG);
> +      if (-o "$logfile") {
> +         chmod 0666, "$logfile";
> +      }
> +   } else {
> +     warn "Warning: Unable to write to $logfile !\n";
> +   }
> +
> +## Run any plugin scripts and pass them the lines.
> +
> +   if (-f "$plugins" && open PLUGINS, "< $plugins") {
> +     my $name;
> +     while (<PLUGINS>) {
> +       chomp;
> +       next if m/^\s*#/;
> +       next if (! -x $_);
> +
> +       do { $name = tmpnam(); } until sysopen 
> +                                (TMP, $name, O_RDWR | 
> O_CREAT | O_EXCL, 0600);
> +       foreach (@lines) { print TMP; }
> +       close (TMP);
> +
> +       open (OUTPUT, "$_ $name 1>&2|") or
> +              warn "Warning: Unable to execute plugin '$_' 
> at commit-time";
> +       while (<OUTPUT>) { print; }
> +       close (OUTPUT);
> +       unlink "$name";
> +     }
> +     close (PLUGINS);
> +   }
> +
> +}
> +
> +#
> +#	Main Body
> +#
> +
> +# Initialize basic variables
> +#
> +$debug = 0;
> +$id = getpgrp();		# note, you *must* use a shell 
> which does setpgrp()
> +$state = $STATE_NONE;
> +$login = $ENV{'USER'} || (getpwuid($<))[0] || "nobody";
> +chop($hostname = `hostname`);
> +$cvsroot = $ENV{'CVSROOT'};
> +$do_status = 1;
> +$modulename = "";
> +$temp_name = "temp";
> +$do_cvsweb = 0;
> +$cvsweb_name = '';
> +$do_modlist = 0;
> +
> +# parse command line arguments (file list is seen as one arg)
> +#
> +while (@ARGV) {
> +    $arg = shift @ARGV;
> +
> +    if ($arg eq '-d') {
> +	$debug = 1;
> +	print STDERR "Debug turned on...\n";
> +    } elsif ($arg eq '-m') {
> +	$mailto = "$mailto " . shift @ARGV;
> +    } elsif ($arg eq '-M') {
> +	$modulename = shift @ARGV;
> +    } elsif ($arg eq '-s') {
> +	$do_status = 0;
> +    } elsif ($arg eq '-f') {
> +	($commitlog) && die("Too many '-f' args\n");
> +	$commitlog = shift @ARGV;
> +    } elsif ($arg eq '-G') {
> +	($gnatsdb) && die("Too many '-G' args\n");
> +	$gnatsdb = shift @ARGV;
> +    } elsif ($arg eq '-T') {
> +	$temp_name = shift @ARGV;
> +    } elsif ($arg eq '-C') {
> +	$do_cvsweb = 1;
> +	$cvsweb_name = shift @ARGV;
> +    } elsif ($arg eq '-U') {
> +	$CVSWEB_URL = shift @ARGV;
> +    } elsif ($arg eq '-D') {
> +	$hostdomain = shift @ARGV;
> +    } elsif ($arg eq '-l') {
> +	$do_modlist = 1;
> +    } else {
> +	($donefiles) && die("Too many arguments!  Check usage.\n");
> +	$donefiles = 1;
> +	@files = split(/ /, $arg);
> +    }
> +}
> +
> +if (defined ($hostdomain)) {
> +    # nothing
> +} elsif ($hostname !~ /\./) {
> +    chop($domainname = `domainname`);
> +    $hostdomain = $hostname . "." . $domainname;
> +} else {
> +    $hostdomain = $hostname;
> +}
> +
> +$hostdomain = 'sources.redhat.com' if $hostdomain eq 
> 'sourceware.cygnus.com';
> +# Used with sprintf to form name of Gnats notification mailing list.
> +# %s argument comse from -G option.
> +$GNATS_MAIL_FORMAT = "%s-gnats\@$hostdomain";
> +
> +($mailto) || die("No -m mail recipient specified\n");
> +&set_temp_vars ($temp_name);
> +
> +# for now, the first "file" is the repository directory 
> being committed,
> +# relative to the $CVSROOT location
> +#
> +@path = split('/', $files[0]);
> +
> +# XXX there are some ugly assumptions in here about module names and
> +# XXX directories relative to the $CVSROOT location -- really should
> +# XXX read $CVSROOT/CVSROOT/modules, but that's not so easy 
> to do, since
> +# XXX we have to parse it backwards.
> +#
> +if ($modulename eq "") {
> +    $modulename = $path[0];	# I.e. the module name == top-level dir
> +}
> +if ($commitlog ne "") {
> +    $commitlog = $cvsroot . "/" . $modulename . "/" . 
> $commitlog unless ($commitlog =~ /^\//);
> +}
> +if ($#path == 0) {
> +    $dir = ".";
> +} else {
> +    $dir = join('/', @path[1..$#path]);
> +}
> +$dir = $dir . "/";
> +
> +if ($debug) {
> +    print STDERR "module - ", $modulename, "\n";
> +    print STDERR "dir    - ", $dir, "\n";
> +    print STDERR "path   - ", join(":", @path), "\n";
> +    print STDERR "files  - ", join(":", @files), "\n";
> +    print STDERR "id     - ", $id, "\n";
> +}
> +
> +# Check for a new directory first.  This appears with files 
> set as follows:
> +#
> +#    files[0] - "path/name/newdir"
> +#    files[1] - "-"
> +#    files[2] - "New"
> +#    files[3] - "directory"
> +#
> +if ($files[2] =~ /New/ && $files[3] =~ /directory/) {
> +    local(@text);
> +
> +    @text = ();
> +    push(@text, &build_header());
> +    push(@text, "");
> +    push(@text, $files[0]);
> +    push(@text, "");
> +
> +    while (<STDIN>) {
> +	chop;			# Drop the newline
> +	push(@text, $_);
> +    }
> +
> +    &mail_notification($mailto, $files[0], @text);
> +
> +    if ($commitlog) {
> +	&write_commitlog($commitlog, @text);
> +    }
> +
> +    if ($do_modlist) {
> +	modlist_newdir ($files[0]);
> +    }
> +
> +    exit 0;
> +}
> +
> +# Iterate over the body of the message collecting information.
> +#
> +while (<STDIN>) {
> +    chop;			# Drop the newline
> +
> +    if (/^Modified Files/) { $state = $STATE_CHANGED; next; }
> +    if (/^Added Files/)    { $state = $STATE_ADDED;   next; }
> +    if (/^Removed Files/)  { $state = $STATE_REMOVED; next; }
> +    if (/^Log Message/)    { $state = $STATE_LOG;     next; }
> +    if (/^\s*Tag:|Revision\/Branch/) { /^[^:]+:\s*(.*)/; 
> $branch = $+; next; }
> +
> +    s/^[ \t\n]+//;		# delete leading whitespace
> +    s/[ \t\n]+$//;		# delete trailing whitespace
> +
> +    if ($state == $STATE_CHANGED) { push(@changed_files, split); }
> +    if ($state == $STATE_ADDED)   { push(@added_files,   split); }
> +    if ($state == $STATE_REMOVED) { push(@removed_files, split); }
> +    if ($state == $STATE_LOG)     { push(@log_lines,     $_); }
> +}
> +
> +# Strip leading and trailing blank lines from the log message.  Also
> +# compress multiple blank lines in the body of the message down to a
> +# single blank line.
> +#
> +while ($#log_lines > -1) {
> +    last if ($log_lines[0] ne "");
> +    shift(@log_lines);
> +}
> +while ($#log_lines > -1) {
> +    last if ($log_lines[$#log_lines] ne "");
> +    pop(@log_lines);
> +}
> +for ($i = $#log_lines; $i > 0; $i--) {
> +    if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) {
> +	splice(@log_lines, $i, 1);
> +    }
> +}
> +
> +# Check for an import command.  This appears with files set 
> as follows:
> +#
> +#    files[0] - "path/name"
> +#    files[1] - "-"
> +#    files[2] - "Imported"
> +#    files[3] - "sources"
> +#
> +if ($files[2] =~ /Imported/ && $files[3] =~ /sources/) {
> +    local(@text);
> +
> +    @text = ();
> +    push(@text, &build_header());
> +    push(@text, "");
> +
> +    push(@text, "Log message:");
> +    while ($#log_lines > -1) {
> +	push (@text, "    " . $log_lines[0]);
> +	shift(@log_lines);
> +    }
> +
> +    &mail_notification($mailto, "Import $file[0]", @text);
> +
> +    if ($commitlog) {
> +	&write_commitlog($commitlog, @text);
> +    }
> +
> +    if ($do_modlist) {
> +	modlist_import ($files[0], \@text);
> +    }
> +
> +    exit 0;
> +}
> +
> +# Compute the list of cvsweb URLs if necessary.
> +if ($do_cvsweb) {
> +    @urls = &generate_cvsweb_urls (join ('/', @path), $branch,
> +				   @files[1 .. $#files]);
> +}
> +
> +if ($do_modlist) {
> +    @modlist = generate_modlist (join ('/', @path),
> +                              \@changed_files, 
> \@added_files, \@removed_files,
> +                               @files[1 .. $#files]);
> +}
> +
> +if ($debug) {
> +    print STDERR "Searching for log file index...";
> +}
> +# Find an index to a log file that matches this log message
> +#
> +for ($i = 0; ; $i++) {
> +    local(@text);
> +
> +    last if (! -e "$LOG_FILE.$i.$id"); # the next available one
> +    @text = &read_logfile("$LOG_FILE.$i.$id", "");
> +    last if ($#text == -1);	# nothing in this file, use it
> +    last if (join(" ", @log_lines) eq join(" ", @text)); # 
> it's the same log message as another
> +}
> +if ($debug) {
> +    print STDERR " found log file at $i.$id, now writing tmp 
> files.\n";
> +}
> +
> +# Spit out the information gathered in this pass.
> +#
> +&append_names_to_file("$CHANGED_FILE.$i.$id", $dir, @changed_files);
> +&append_names_to_file("$ADDED_FILE.$i.$id",   $dir, @added_files);
> +&append_names_to_file("$REMOVED_FILE.$i.$id", $dir, @removed_files);
> +&append_names_to_file("$URL_FILE.$i.$id",     $dir, @urls);
> +&append_names_to_file("$COMMITS_FILE.$i.$id", undef, @modlist);
> +&write_logfile("$LOG_FILE.$i.$id", @log_lines);
> +    
> +
> +# Check whether this is the last directory.  If not, quit.
> +#
> +if ($debug) {
> +    print STDERR "Checking current dir against last dir.\n";
> +}
> +$_ = &read_line("$LAST_FILE.$id");
> +
> +if ($_ ne $cvsroot . "/" . $files[0]) {
> +    if ($debug) {
> +	print STDERR sprintf("Current directory %s is not last 
> directory %s.\n", $cvsroot . "/" .$files[0], $_);
> +    }
> +    exit 0;
> +}
> +if ($debug) {
> +    print STDERR sprintf("Current directory %s is last 
> directory %s -- all commits done.\n", $files[0], $_);
> +}
> +
> +#
> +#	End Of Commits!
> +#
> +
> +# This is it.  The commits are all finished.  Lump 
> everything together
> +# into a single message, fire a copy off to the mailing 
> list, and drop
> +# it on the end of the Changes file.
> +#
> +
> +#
> +# Produce the final compilation of the log messages
> +#
> +@text = ();
> +@status_txt = ();
> +@subject_files = ();
> +@log_txt = ();
> +@modlist_txt = ();
> +push(@text, &build_header());
> +push(@text, "");
> +
> +for ($i = 0; ; $i++) {
> +    last if (! -e "$LOG_FILE.$i.$id"); # we're done them all!
> +    @lines = &read_logfile("$CHANGED_FILE.$i.$id", "");
> +    if ($#lines >= 0) {
> +	push(@text, "Modified files:");
> +	push(@text, &format_lists(@lines));
> +	push(@subject_files, &accum_subject(@lines));
> +    }
> +    @lines = &read_logfile("$ADDED_FILE.$i.$id", "");
> +    if ($#lines >= 0) {
> +	push(@text, "Added files:");
> +	push(@text, &format_lists(@lines));
> +	push(@subject_files, &accum_subject(@lines));
> +    }
> +    @lines = &read_logfile("$REMOVED_FILE.$i.$id", "");
> +    if ($#lines >= 0) {
> +	push(@text, "Removed files:");
> +	push(@text, &format_lists(@lines));
> +	push(@subject_files, &accum_subject(@lines));
> +    }
> +    if ($#text >= 0) {
> +	push(@text, "");
> +    }
> +    @log_txt = &read_logfile("$LOG_FILE.$i.$id", "\t");
> +    if ($#log_txt >= 0) {
> +	push(@text, "Log message:");
> +	push(@text, @log_txt);
> +	push(@text, "");
> +    }
> +    @url_txt = &read_logfile("$URL_FILE.$i.$id", "");
> +    if ($#url_txt >= 0) {
> +	push (@text, "Patches:");
> +	# Exclude directories listed in the file.
> +	push (@text, grep (! /\/$/, @url_txt));
> +	push (@text, "");
> +    }
> +    if ($do_modlist) {
> +        push (@modlist_txt, 
> read_logfile("$COMMITS_FILE.$i.$id", ""));
> +    }
> +    if ($do_status) {
> +	local(@changed_files);
> +
> +	@changed_files = ();
> +	push(@changed_files, &read_logfile("$CHANGED_FILE.$i.$id", ""));
> +	push(@changed_files, &read_logfile("$ADDED_FILE.$i.$id", ""));
> +	push(@changed_files, &read_logfile("$REMOVED_FILE.$i.$id", ""));
> +
> +	if ($debug) {
> +	    print STDERR "main: pre-sort changed_files = ", 
> join(":", @changed_files), ".\n";
> +	}
> +	@changed_files = sort(@changed_files);
> +	if ($debug) {
> +	    print STDERR "main: post-sort changed_files = ", 
> join(":", @changed_files), ".\n";
> +	}
> +
> +	foreach $dofile (@changed_files) {
> +	    if ($dofile =~ /\/$/) {
> +		next;		# ignore the silly "dir" entries
> +	    }
> +	    if ($debug) {
> +		print STDERR "main(): doing status on $dofile\n";
> +	    }
> +	    open(STATUS, "-|") || exec 'cvs', '-nQq', 'status', 
> '-v', $dofile;
> +	    while (<STATUS>) {
> +		chop;
> +		push(@status_txt, $_);
> +	    }
> +	}
> +    }
> +}
> +
> +$subject_txt = &compile_subject(@subject_files);
> +
> +# Write to the commitlog file
> +#
> +if ($commitlog) {
> +    &write_commitlog($commitlog, @text);
> +}
> +
> +if ($#modlist_txt >= 0) {
> +    modlist_write_to_log (@modlist_txt);
> +}
> +
> +if ($#status_txt >= 0) {
> +    push(@text, @status_txt);
> +}
> +
> +# Mailout the notification.
> +#
> +&mail_notification($mailto, $subject_txt, @text);
> +
> +# Send mail to Gnats, if required.
> +if ($gnatsdb ne '') {
> +    $log_txt = join ("\n", @log_txt);
> +    while ($log_txt =~ m,PR ([a-z.+]+/[0-9]+)(.*)$,s) {
> +	$pr = $1;
> +	$log_txt = $2;
> +	$file = sprintf ($GNATS_ROOT_FORMAT, $gnatsdb) . "/" . $pr;
> +	if (-f $file) {
> +	    &mail_notification(sprintf ($GNATS_MAIL_FORMAT, $gnatsdb),
> +			       $pr, @text);
> +	}
> +    }
> +}
> +
> +# cleanup
> +#
> +if (! $debug) {
> +    &cleanup_tmpfiles();
> +}
> +
> +exit 0;
> Index: loginfo
> ===================================================================
> RCS file: /home/tools/CVSROOT/loginfo,v
> retrieving revision 1.1
> diff -u -r1.1 loginfo
> --- loginfo 6 Dec 2001 18:45:46 -0000 1.1
> +++ loginfo 8 Oct 2002 20:59:56 -0000
> @@ -24,3 +24,5 @@
>  #DEFAULT (echo ""; id; echo %s; date; cat) >> 
> $CVSROOT/CVSROOT/commitlog
>  # or
>  #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> 
> $CVSROOT/CVSROOT/commitlog
> +
> +DEFAULT (/home/tools/CVSROOT/log_accum -D eclipse.org -T cdt 
> -C Tools_Project -U 
"http://dev.eclipse.org/viewcvs/index.cgi/"; -m FIXME@xxxxxxxxxxx -s %{sVv})
_______________________________________________
cdt-patch mailing list
cdt-patch@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/cdt-patch


Back to the top