1#! @PERL@
2# -*-Perl-*-
3#
4# XXX: FIXME: handle multiple '-f logfile' arguments
5#
6# XXX -- I HATE Perl!  This *will* be re-written in shell/awk/sed soon!
7#
8
9# Usage:  log.pl [-u user] [[-m mailto] ...] [-s] [-V] -f logfile 'dirname file ...'
10#
11#	-u user		- $USER passed from loginfo
12#	-m mailto	- for each user to receive cvs log reports
13#			(multiple -m's permitted)
14#	-s		- to prevent "cvs status -v" messages
15#	-V		- without '-s', don't pass '-v' to cvs status
16#	-f logfile	- for the logfile to append to (mandatory,
17#			but only one logfile can be specified).
18
19# here is what the output looks like:
20#
21#    From: woods@kuma.domain.top
22#    Subject: CVS update: testmodule
23#
24#    Date: Wednesday November 23, 1994 @ 14:15
25#    Author: woods
26#
27#    Update of /local/src-CVS/testmodule
28#    In directory kuma:/home/kuma/woods/work.d/testmodule
29#    
30#    Modified Files:
31#    	test3 
32#    Added Files:
33#    	test6 
34#    Removed Files:
35#    	test4 
36#    Log Message:
37#    - wow, what a test
38#
39# (and for each file the "cvs status -v" output is appended unless -s is used)
40#
41#    ==================================================================
42#    File: test3           	Status: Up-to-date
43#    
44#       Working revision:	1.41	Wed Nov 23 14:15:59 1994
45#       Repository revision:	1.41	/local/src-CVS/cvs/testmodule/test3,v
46#       Sticky Options:	-ko
47#    
48#       Existing Tags:
49#    	local-v2                 	(revision: 1.7)
50#    	local-v1                 	(revision: 1.1.1.2)
51#    	CVS-1_4A2                	(revision: 1.1.1.2)
52#    	local-v0                 	(revision: 1.2)
53#    	CVS-1_4A1                	(revision: 1.1.1.1)
54#    	CVS                      	(branch: 1.1.1)
55
56use strict;
57use IO::File;
58
59my $cvsroot = $ENV{'CVSROOT'};
60
61# turn off setgid
62#
63$) = $(;
64
65my $dostatus = 1;
66my $verbosestatus = 1;
67my $users;
68my $login;
69my $donefiles;
70my $logfile;
71my @files;
72
73# parse command line arguments
74#
75while (@ARGV) {
76	my $arg = shift @ARGV;
77
78	if ($arg eq '-m') {
79		$users = "$users " . shift @ARGV;
80	} elsif ($arg eq '-u') {
81		$login = shift @ARGV;
82	} elsif ($arg eq '-f') {
83		($logfile) && die "Too many '-f' args";
84		$logfile = shift @ARGV;
85	} elsif ($arg eq '-s') {
86		$dostatus = 0;
87	} elsif ($arg eq '-V') {
88		$verbosestatus = 0;
89	} else {
90		($donefiles) && die "Too many arguments!\n";
91		$donefiles = 1;
92		@files = split(/ /, $arg);
93	}
94}
95
96# the first argument is the module location relative to $CVSROOT
97#
98my $modulepath = shift @files;
99
100my $mailcmd = "| Mail -s 'CVS update: $modulepath'";
101
102# Initialise some date and time arrays
103#
104my @mos = ('January','February','March','April','May','June','July',
105	'August','September','October','November','December');
106my @days = ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
107
108my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
109$year += 1900;
110
111# get a login name for the guy doing the commit....
112#
113if ($login eq '') {
114	$login = getlogin || (getpwuid($<))[0] || "nobody";
115}
116
117# open log file for appending
118#
119my $logfh = new IO::File ">>" . $logfile
120	or die "Could not open(" . $logfile . "): $!\n";
121
122# send mail, if there's anyone to send to!
123#
124my $mailfh;
125if ($users) {
126	$mailcmd = "$mailcmd $users";
127	$mailfh = new IO::File $mailcmd
128		or die "Could not Exec($mailcmd): $!\n";
129}
130
131# print out the log Header
132#
133$logfh->print ("\n");
134$logfh->print ("****************************************\n");
135$logfh->print ("Date:\t$days[$wday] $mos[$mon] $mday, $year @ $hour:" . sprintf("%02d", $min) . "\n");
136$logfh->print ("Author:\t$login\n\n");
137
138if ($mailfh) {
139	$mailfh->print ("\n");
140	$mailfh->print ("Date:\t$days[$wday] $mos[$mon] $mday, $year @ $hour:" . sprintf("%02d", $min) . "\n");
141	$mailfh->print ("Author:\t$login\n\n");
142}
143
144# print the stuff from logmsg that comes in on stdin to the logfile
145#
146my $infh = new IO::File "< -";
147foreach ($infh->getlines) {
148	$logfh->print;
149	if ($mailfh) {
150		$mailfh->print ($_);
151	}
152}
153undef $infh;
154
155$logfh->print ("\n");
156
157# after log information, do an 'cvs -Qq status -v' on each file in the arguments.
158#
159if ($dostatus != 0) {
160	while (@files) {
161		my $file = shift @files;
162		if ($file eq "-") {
163			$logfh->print ("[input file was '-']\n");
164			if ($mailfh) {
165				$mailfh->print ("[input file was '-']\n");
166			}
167			last;
168		}
169		my $rcsfh = new IO::File;
170		my $pid = $rcsfh->open ("-|");
171		if ( !defined $pid )
172		{
173			die "fork failed: $!";
174		}
175		if ($pid == 0)
176		{
177			my @command = ('cvs', '-nQq', 'status');
178			if ($verbosestatus)
179			{
180				push @command, '-v';
181			}
182			push @command, $file;
183			exec @command;
184			die "cvs exec failed: $!";
185		}
186		my $line;
187		while ($line = $rcsfh->getline) {
188			$logfh->print ($line);
189			if ($mailfh) {
190				$mailfh->print ($line);
191			}
192		}
193		undef $rcsfh;
194	}
195}
196
197$logfh->close()
198	or die "Write to $logfile failed: $!";
199
200if ($mailfh)
201{
202	$mailfh->close;
203	die "Pipe to $mailcmd failed" if $?;
204}
205
206## must exit cleanly
207##
208exit 0;
209