[
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