/contrib/cvs/contrib/log_accum.in

https://bitbucket.org/freebsd/freebsd-head/ · Autoconf · 749 lines · 434 code · 98 blank · 217 comment · 106 complexity · bbb4d641bab5440fb57f56b0f04a35fa MD5 · raw file

  1. #! @PERL@ -T
  2. # -*-Perl-*-
  3. # Copyright (C) 1994-2005 The Free Software Foundation, Inc.
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2, or (at your option)
  7. # any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. ###############################################################################
  14. ###############################################################################
  15. ###############################################################################
  16. #
  17. # THIS SCRIPT IS PROBABLY BROKEN. REMOVING THE -T SWITCH ON THE #! LINE ABOVE
  18. # WOULD FIX IT, BUT THIS IS INSECURE. WE RECOMMEND FIXING THE ERRORS WHICH THE
  19. # -T SWITCH WILL CAUSE PERL TO REPORT BEFORE RUNNING THIS SCRIPT FROM A CVS
  20. # SERVER TRIGGER. PLEASE SEND PATCHES CONTAINING THE CHANGES YOU FIND
  21. # NECESSARY TO RUN THIS SCRIPT WITH THE TAINT-CHECKING ENABLED BACK TO THE
  22. # <@PACKAGE_BUGREPORT@> MAILING LIST.
  23. #
  24. # For more on general Perl security and taint-checking, please try running the
  25. # `perldoc perlsec' command.
  26. #
  27. ###############################################################################
  28. ###############################################################################
  29. ###############################################################################
  30. # Perl filter to handle the log messages from the checkin of files in
  31. # a directory. This script will group the lists of files by log
  32. # message, and mail a single consolidated log message at the end of
  33. # the commit.
  34. #
  35. # This file assumes a pre-commit checking program that leaves the
  36. # names of the first and last commit directories in a temporary file.
  37. #
  38. # IMPORTANT: what the above means is, this script interacts with
  39. # commit_prep, in that they have to agree on the tmpfile name to use.
  40. # See $LAST_FILE below.
  41. #
  42. # How this works: CVS triggers this script once for each directory
  43. # involved in the commit -- in other words, a single commit can invoke
  44. # this script N times. It knows when it's on the last invocation by
  45. # examining the contents of $LAST_FILE. Between invocations, it
  46. # caches information for its future incarnations in various temporary
  47. # files in /tmp, which are named according to the process group and
  48. # the committer (by themselves, neither of these are unique, but
  49. # together they almost always are, unless the same user is doing two
  50. # commits simultaneously). The final invocation is the one that
  51. # actually sends the mail -- it gathers up the cached information,
  52. # combines that with what it found out on this pass, and sends a
  53. # commit message to the appropriate mailing list.
  54. #
  55. # (Ask Karl Fogel <kfogel@collab.net> if questions.)
  56. #
  57. # Contributed by David Hampton <hampton@cisco.com>
  58. # Roy Fielding removed useless code and added log/mail of new files
  59. # Ken Coar added special processing (i.e., no diffs) for binary files
  60. #
  61. ############################################################
  62. #
  63. # Configurable options
  64. #
  65. ############################################################
  66. #
  67. # Where do you want the RCS ID and delta info?
  68. # 0 = none,
  69. # 1 = in mail only,
  70. # 2 = in both mail and logs.
  71. #
  72. $rcsidinfo = 2;
  73. #if you are using CVS web then set this to some value... if not set it to ""
  74. #
  75. # When set properly, this will cause links to aspects of the project to
  76. # print in the commit emails.
  77. #$CVSWEB_SCHEME = "http";
  78. #$CVSWEB_DOMAIN = "nongnu.org";
  79. #$CVSWEB_PORT = "80";
  80. #$CVSWEB_URI = "source/browse/";
  81. #$SEND_URL = "true";
  82. $SEND_DIFF = "true";
  83. # Set this to a domain to have CVS pretend that all users who make
  84. # commits have mail accounts within that domain.
  85. #$EMULATE_LOCAL_MAIL_USER="nongnu.org";
  86. # Set this to '-c' for context diffs; defaults to '-u' for unidiff format.
  87. $difftype = '-uN';
  88. ############################################################
  89. #
  90. # Constants
  91. #
  92. ############################################################
  93. $STATE_NONE = 0;
  94. $STATE_CHANGED = 1;
  95. $STATE_ADDED = 2;
  96. $STATE_REMOVED = 3;
  97. $STATE_LOG = 4;
  98. $TMPDIR = $ENV{'TMPDIR'} || '/tmp';
  99. $FILE_PREFIX = '#cvs.';
  100. $LAST_FILE = "$TMPDIR/${FILE_PREFIX}lastdir"; # Created by commit_prep!
  101. $ADDED_FILE = "$TMPDIR/${FILE_PREFIX}files.added";
  102. $REMOVED_FILE = "$TMPDIR/${FILE_PREFIX}files.removed";
  103. $LOG_FILE = "$TMPDIR/${FILE_PREFIX}files.log";
  104. $BRANCH_FILE = "$TMPDIR/${FILE_PREFIX}files.branch";
  105. $MLIST_FILE = "$TMPDIR/${FILE_PREFIX}files.mlist";
  106. $SUMMARY_FILE = "$TMPDIR/${FILE_PREFIX}files.summary";
  107. $CVSROOT = $ENV{'CVSROOT'};
  108. $MAIL_CMD = "| /usr/lib/sendmail -i -t";
  109. #$MAIL_CMD = "| /var/qmail/bin/qmail-inject";
  110. $MAIL_FROM = 'commitlogger'; #not needed if EMULATE_LOCAL_MAIL_USER
  111. $SUBJECT_PRE = 'CVS update:';
  112. ############################################################
  113. #
  114. # Subroutines
  115. #
  116. ############################################################
  117. sub format_names {
  118. local($dir, @files) = @_;
  119. local(@lines);
  120. $lines[0] = sprintf(" %-08s", $dir);
  121. foreach $file (@files) {
  122. if (length($lines[$#lines]) + length($file) > 60) {
  123. $lines[++$#lines] = sprintf(" %8s", " ");
  124. }
  125. $lines[$#lines] .= " ".$file;
  126. }
  127. @lines;
  128. }
  129. sub cleanup_tmpfiles {
  130. local(@files);
  131. opendir(DIR, $TMPDIR);
  132. push(@files, grep(/^${FILE_PREFIX}.*\.${id}\.${cvs_user}$/, readdir(DIR)));
  133. closedir(DIR);
  134. foreach (@files) {
  135. unlink "$TMPDIR/$_";
  136. }
  137. }
  138. sub write_logfile {
  139. local($filename, @lines) = @_;
  140. open(FILE, ">$filename") || die ("Cannot open log file $filename: $!\n");
  141. print(FILE join("\n", @lines), "\n");
  142. close(FILE);
  143. }
  144. sub append_to_file {
  145. local($filename, $dir, @files) = @_;
  146. if (@files) {
  147. local(@lines) = &format_names($dir, @files);
  148. open(FILE, ">>$filename") || die ("Cannot open file $filename: $!\n");
  149. print(FILE join("\n", @lines), "\n");
  150. close(FILE);
  151. }
  152. }
  153. sub write_line {
  154. local($filename, $line) = @_;
  155. open(FILE, ">$filename") || die("Cannot open file $filename: $!\n");
  156. print(FILE $line, "\n");
  157. close(FILE);
  158. }
  159. sub append_line {
  160. local($filename, $line) = @_;
  161. open(FILE, ">>$filename") || die("Cannot open file $filename: $!\n");
  162. print(FILE $line, "\n");
  163. close(FILE);
  164. }
  165. sub read_line {
  166. local($filename) = @_;
  167. local($line);
  168. open(FILE, "<$filename") || die("Cannot open file $filename: $!\n");
  169. $line = <FILE>;
  170. close(FILE);
  171. chomp($line);
  172. $line;
  173. }
  174. sub read_line_nodie {
  175. local($filename) = @_;
  176. local($line);
  177. open(FILE, "<$filename") || return ("");
  178. $line = <FILE>;
  179. close(FILE);
  180. chomp($line);
  181. $line;
  182. }
  183. sub read_file_lines {
  184. local($filename) = @_;
  185. local(@text) = ();
  186. open(FILE, "<$filename") || return ();
  187. while (<FILE>) {
  188. chomp;
  189. push(@text, $_);
  190. }
  191. close(FILE);
  192. @text;
  193. }
  194. sub read_file {
  195. local($filename, $leader) = @_;
  196. local(@text) = ();
  197. open(FILE, "<$filename") || return ();
  198. while (<FILE>) {
  199. chomp;
  200. push(@text, sprintf(" %-10s %s", $leader, $_));
  201. $leader = "";
  202. }
  203. close(FILE);
  204. @text;
  205. }
  206. sub read_logfile {
  207. local($filename, $leader) = @_;
  208. local(@text) = ();
  209. open(FILE, "<$filename") || die ("Cannot open log file $filename: $!\n");
  210. while (<FILE>) {
  211. chomp;
  212. push(@text, $leader.$_);
  213. }
  214. close(FILE);
  215. @text;
  216. }
  217. #
  218. # do an 'cvs -Qn status' on each file in the arguments, and extract info.
  219. #
  220. sub change_summary {
  221. local($out, @filenames) = @_;
  222. local(@revline);
  223. local($file, $rev, $rcsfile, $line, $vhost, $cvsweb_base);
  224. while (@filenames) {
  225. $file = shift @filenames;
  226. if ("$file" eq "") {
  227. next;
  228. }
  229. open(RCS, "-|") || exec "$cvsbin/cvs", '-Qn', 'status', '--', $file;
  230. $rev = "";
  231. $delta = "";
  232. $rcsfile = "";
  233. while (<RCS>) {
  234. if (/^[ \t]*Repository revision/) {
  235. chomp;
  236. @revline = split(' ', $_);
  237. $rev = $revline[2];
  238. $rcsfile = $revline[3];
  239. $rcsfile =~ s,^$CVSROOT/,,;
  240. $rcsfile =~ s/,v$//;
  241. }
  242. }
  243. close(RCS);
  244. if ($rev ne '' && $rcsfile ne '') {
  245. open(RCS, "-|") || exec "$cvsbin/cvs", '-Qn', 'log', "-r$rev",
  246. '--', $file;
  247. while (<RCS>) {
  248. if (/^date:/) {
  249. chomp;
  250. $delta = $_;
  251. $delta =~ s/^.*;//;
  252. $delta =~ s/^[\s]+lines://;
  253. }
  254. }
  255. close(RCS);
  256. }
  257. $diff = "\n\n";
  258. $vhost = $path[0];
  259. if ($CVSWEB_PORT eq "80") {
  260. $cvsweb_base = "$CVSWEB_SCHEME://$vhost.$CVSWEB_DOMAIN/$CVSWEB_URI";
  261. }
  262. else {
  263. $cvsweb_base = "$CVSWEB_SCHEME://$vhost.$CVSWEB_DOMAIN:$CVSWEB_PORT/$CVSWEB_URI";
  264. }
  265. if ($SEND_URL eq "true") {
  266. $diff .= $cvsweb_base . join("/", @path) . "/$file";
  267. }
  268. #
  269. # If this is a binary file, don't try to report a diff; not only is
  270. # it meaningless, but it also screws up some mailers. We rely on
  271. # Perl's 'is this binary' algorithm; it's pretty good. But not
  272. # perfect.
  273. #
  274. if (($file =~ /\.(?:pdf|gif|jpg|mpg)$/i) || (-B $file)) {
  275. if ($SEND_URL eq "true") {
  276. $diff .= "?rev=$rev&content-type=text/x-cvsweb-markup\n\n";
  277. }
  278. if ($SEND_DIFF eq "true") {
  279. $diff .= "\t<<Binary file>>\n\n";
  280. }
  281. }
  282. else {
  283. #
  284. # Get the differences between this and the previous revision,
  285. # being aware that new files always have revision '1.1' and
  286. # new branches always end in '.n.1'.
  287. #
  288. if ($rev =~ /^(.*)\.([0-9]+)$/) {
  289. $prev = $2 - 1;
  290. $prev_rev = $1 . '.' . $prev;
  291. $prev_rev =~ s/\.[0-9]+\.0$//;# Truncate if first rev on branch
  292. if ($rev eq '1.1') {
  293. if ($SEND_URL eq "true") {
  294. $diff .= "?rev=$rev&content-type=text/x-cvsweb-markup\n\n";
  295. }
  296. if ($SEND_DIFF eq "true") {
  297. open(DIFF, "-|")
  298. || exec "$cvsbin/cvs", '-Qn', 'update', '-p', '-r1.1',
  299. '--', $file;
  300. $diff .= "Index: $file\n=================================="
  301. . "=================================\n";
  302. }
  303. }
  304. else {
  305. if ($SEND_URL eq "true") {
  306. $diff .= ".diff?r1=$prev_rev&r2=$rev\n\n";
  307. }
  308. if ($SEND_DIFF eq "true") {
  309. $diff .= "(In the diff below, changes in quantity "
  310. . "of whitespace are not shown.)\n\n";
  311. open(DIFF, "-|")
  312. || exec "$cvsbin/cvs", '-Qn', 'diff', "$difftype",
  313. '-b', "-r$prev_rev", "-r$rev", '--', $file;
  314. }
  315. }
  316. if ($SEND_DIFF eq "true") {
  317. while (<DIFF>) {
  318. $diff .= $_;
  319. }
  320. close(DIFF);
  321. }
  322. $diff .= "\n\n";
  323. }
  324. }
  325. &append_line($out, sprintf("%-9s%-12s%s%s", $rev, $delta,
  326. $rcsfile, $diff));
  327. }
  328. }
  329. sub build_header {
  330. local($header);
  331. delete $ENV{'TZ'};
  332. local($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  333. $header = sprintf(" User: %-8s\n Date: %02d/%02d/%02d %02d:%02d:%02d",
  334. $cvs_user, $year%100, $mon+1, $mday,
  335. $hour, $min, $sec);
  336. # $header = sprintf("%-8s %02d/%02d/%02d %02d:%02d:%02d",
  337. # $login, $year%100, $mon+1, $mday,
  338. # $hour, $min, $sec);
  339. }
  340. # !!! Destination Mailing-list and history file mappings here !!!
  341. #sub mlist_map
  342. #{
  343. # local($path) = @_;
  344. # my $domain = "nongnu.org";
  345. #
  346. # if ($path =~ /^([^\/]+)/) {
  347. # return "cvs\@$1.$domain";
  348. # } else {
  349. # return "cvs\@$domain";
  350. # }
  351. #}
  352. sub derive_subject_from_changes_file ()
  353. {
  354. my $subj = "";
  355. for ($i = 0; ; $i++)
  356. {
  357. open (CH, "<$CHANGED_FILE.$i.$id.$cvs_user") or last;
  358. while (my $change = <CH>)
  359. {
  360. # A changes file looks like this:
  361. #
  362. # src foo.c newfile.html
  363. # www index.html project_nav.html
  364. #
  365. # Each line is " Dir File1 File2 ..."
  366. # We only care about Dir, since the subject line should
  367. # summarize.
  368. $change =~ s/^[ \t]*//;
  369. $change =~ /^([^ \t]+)[ \t]*/;
  370. my $dir = $1;
  371. # Fold to rightmost directory component
  372. $dir =~ /([^\/]+)$/;
  373. $dir = $1;
  374. if ($subj eq "") {
  375. $subj = $dir;
  376. } else {
  377. $subj .= ", $dir";
  378. }
  379. }
  380. close (CH);
  381. }
  382. if ($subj ne "") {
  383. $subj = "MODIFIED: $subj ...";
  384. }
  385. else {
  386. # NPM: See if there's any file-addition notifications.
  387. my $added = &read_line_nodie("$ADDED_FILE.$i.$id.$cvs_user");
  388. if ($added ne "") {
  389. $subj .= "ADDED: $added ";
  390. }
  391. # print "derive_subject_from_changes_file().. added== $added \n";
  392. ## NPM: See if there's any file-removal notications.
  393. my $removed = &read_line_nodie("$REMOVED_FILE.$i.$id.$cvs_user");
  394. if ($removed ne "") {
  395. $subj .= "REMOVED: $removed ";
  396. }
  397. # print "derive_subject_from_changes_file().. removed== $removed \n";
  398. ## NPM: See if there's any branch notifications.
  399. my $branched = &read_line_nodie("$BRANCH_FILE.$i.$id.$cvs_user");
  400. if ($branched ne "") {
  401. $subj .= "BRANCHED: $branched";
  402. }
  403. # print "derive_subject_from_changes_file().. branched== $branched \n";
  404. ## NPM: DEFAULT: DIRECTORY CREATION (c.f. "Check for a new directory first" in main mody)
  405. if ($subj eq "") {
  406. my $subject = join("/", @path);
  407. $subj = "NEW: $subject";
  408. }
  409. }
  410. return $subj;
  411. }
  412. sub mail_notification
  413. {
  414. local($addr_list, @text) = @_;
  415. local($mail_to);
  416. my $subj = &derive_subject_from_changes_file ();
  417. if ($EMULATE_LOCAL_MAIL_USER ne "") {
  418. $MAIL_FROM = "$cvs_user\@$EMULATE_LOCAL_MAIL_USER";
  419. }
  420. $mail_to = join(", ", @{$addr_list});
  421. print "Mailing the commit message to $mail_to (from $MAIL_FROM)\n";
  422. $ENV{'MAILUSER'} = $MAIL_FROM;
  423. # Commented out on hocus, so comment it out here. -kff
  424. # $ENV{'QMAILINJECT'} = 'f';
  425. open(MAIL, "$MAIL_CMD -f$MAIL_FROM");
  426. print MAIL "From: $MAIL_FROM\n";
  427. print MAIL "To: $mail_to\n";
  428. print MAIL "Subject: $SUBJECT_PRE $subj\n\n";
  429. print(MAIL join("\n", @text));
  430. close(MAIL);
  431. # print "Mailing the commit message to $MAIL_TO...\n";
  432. #
  433. # #added by jrobbins@collab.net 1999/12/15
  434. # # attempt to get rid of anonymous
  435. # $ENV{'MAILUSER'} = 'commitlogger';
  436. # $ENV{'QMAILINJECT'} = 'f';
  437. #
  438. # open(MAIL, "| /var/qmail/bin/qmail-inject");
  439. # print(MAIL "To: $MAIL_TO\n");
  440. # print(MAIL "Subject: cvs commit: $ARGV[0]\n");
  441. # print(MAIL join("\n", @text));
  442. # close(MAIL);
  443. }
  444. ## process the command line arguments sent to this script
  445. ## it returns an array of files, %s, sent from the loginfo
  446. ## command
  447. sub process_argv
  448. {
  449. local(@argv) = @_;
  450. local(@files);
  451. local($arg);
  452. print "Processing log script arguments...\n";
  453. while (@argv) {
  454. $arg = shift @argv;
  455. if ($arg eq '-u') {
  456. $cvs_user = shift @argv;
  457. } else {
  458. ($donefiles) && die "Too many arguments!\n";
  459. $donefiles = 1;
  460. $ARGV[0] = $arg;
  461. @files = split(' ', $arg);
  462. }
  463. }
  464. return @files;
  465. }
  466. #############################################################
  467. #
  468. # Main Body
  469. #
  470. ############################################################
  471. #
  472. # Setup environment
  473. #
  474. umask (002);
  475. # Connect to the database
  476. $cvsbin = "/usr/bin";
  477. #
  478. # Initialize basic variables
  479. #
  480. $id = getpgrp();
  481. $state = $STATE_NONE;
  482. $cvs_user = $ENV{'USER'} || getlogin || (getpwuid($<))[0] || sprintf("uid#%d",$<);
  483. @files = process_argv(@ARGV);
  484. @path = split('/', $files[0]);
  485. if ($#path == 0) {
  486. $dir = ".";
  487. } else {
  488. $dir = join('/', @path[1..$#path]);
  489. }
  490. #print("ARGV - ", join(":", @ARGV), "\n");
  491. #print("files - ", join(":", @files), "\n");
  492. #print("path - ", join(":", @path), "\n");
  493. #print("dir - ", $dir, "\n");
  494. #print("id - ", $id, "\n");
  495. #
  496. # Map the repository directory to an email address for commitlogs to be sent
  497. # to.
  498. #
  499. #$mlist = &mlist_map($files[0]);
  500. ##########################
  501. #
  502. # Check for a new directory first. This will always appear as a
  503. # single item in the argument list, and an empty log message.
  504. #
  505. if ($ARGV[0] =~ /New directory/) {
  506. $header = &build_header;
  507. @text = ();
  508. push(@text, $header);
  509. push(@text, "");
  510. push(@text, " ".$ARGV[0]);
  511. &mail_notification([ $mlist ], @text);
  512. exit 0;
  513. }
  514. #
  515. # Iterate over the body of the message collecting information.
  516. #
  517. while (<STDIN>) {
  518. chomp; # Drop the newline
  519. if (/^Revision\/Branch:/) {
  520. s,^Revision/Branch:,,;
  521. push (@branch_lines, split);
  522. next;
  523. }
  524. # next if (/^[ \t]+Tag:/ && $state != $STATE_LOG);
  525. if (/^Modified Files/) { $state = $STATE_CHANGED; next; }
  526. if (/^Added Files/) { $state = $STATE_ADDED; next; }
  527. if (/^Removed Files/) { $state = $STATE_REMOVED; next; }
  528. if (/^Log Message/) { $state = $STATE_LOG; next; }
  529. s/[ \t\n]+$//; # delete trailing space
  530. push (@changed_files, split) if ($state == $STATE_CHANGED);
  531. push (@added_files, split) if ($state == $STATE_ADDED);
  532. push (@removed_files, split) if ($state == $STATE_REMOVED);
  533. if ($state == $STATE_LOG) {
  534. if (/^PR:$/i ||
  535. /^Reviewed by:$/i ||
  536. /^Submitted by:$/i ||
  537. /^Obtained from:$/i) {
  538. next;
  539. }
  540. push (@log_lines, $_);
  541. }
  542. }
  543. #
  544. # Strip leading and trailing blank lines from the log message. Also
  545. # compress multiple blank lines in the body of the message down to a
  546. # single blank line.
  547. # (Note, this only does the mail and changes log, not the rcs log).
  548. #
  549. while ($#log_lines > -1) {
  550. last if ($log_lines[0] ne "");
  551. shift(@log_lines);
  552. }
  553. while ($#log_lines > -1) {
  554. last if ($log_lines[$#log_lines] ne "");
  555. pop(@log_lines);
  556. }
  557. for ($i = $#log_lines; $i > 0; $i--) {
  558. if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) {
  559. splice(@log_lines, $i, 1);
  560. }
  561. }
  562. #
  563. # Find the log file that matches this log message
  564. #
  565. for ($i = 0; ; $i++) {
  566. last if (! -e "$LOG_FILE.$i.$id.$cvs_user");
  567. @text = &read_logfile("$LOG_FILE.$i.$id.$cvs_user", "");
  568. last if ($#text == -1);
  569. last if (join(" ", @log_lines) eq join(" ", @text));
  570. }
  571. #
  572. # Spit out the information gathered in this pass.
  573. #
  574. &write_logfile("$LOG_FILE.$i.$id.$cvs_user", @log_lines);
  575. &append_to_file("$BRANCH_FILE.$i.$id.$cvs_user", $dir, @branch_lines);
  576. &append_to_file("$ADDED_FILE.$i.$id.$cvs_user", $dir, @added_files);
  577. &append_to_file("$CHANGED_FILE.$i.$id.$cvs_user", $dir, @changed_files);
  578. &append_to_file("$REMOVED_FILE.$i.$id.$cvs_user", $dir, @removed_files);
  579. &append_line("$MLIST_FILE.$i.$id.$cvs_user", $mlist);
  580. if ($rcsidinfo) {
  581. &change_summary("$SUMMARY_FILE.$i.$id.$cvs_user", (@changed_files, @added_files));
  582. }
  583. #
  584. # Check whether this is the last directory. If not, quit.
  585. #
  586. if (-e "$LAST_FILE.$id.$cvs_user") {
  587. $_ = &read_line("$LAST_FILE.$id.$cvs_user");
  588. $tmpfiles = $files[0];
  589. $tmpfiles =~ s,([^a-zA-Z0-9_/]),\\$1,g;
  590. if (! grep(/$tmpfiles$/, $_)) {
  591. print "More commits to come...\n";
  592. exit 0
  593. }
  594. }
  595. #
  596. # This is it. The commits are all finished. Lump everything together
  597. # into a single message, fire a copy off to the mailing list, and drop
  598. # it on the end of the Changes file.
  599. #
  600. $header = &build_header;
  601. #
  602. # Produce the final compilation of the log messages
  603. #
  604. @text = ();
  605. @mlist_list = ();
  606. push(@text, $header);
  607. push(@text, "");
  608. for ($i = 0; ; $i++) {
  609. last if (! -e "$LOG_FILE.$i.$id.$cvs_user");
  610. push(@text, &read_file("$BRANCH_FILE.$i.$id.$cvs_user", "Branch:"));
  611. push(@text, &read_file("$CHANGED_FILE.$i.$id.$cvs_user", "Modified:"));
  612. push(@text, &read_file("$ADDED_FILE.$i.$id.$cvs_user", "Added:"));
  613. push(@text, &read_file("$REMOVED_FILE.$i.$id.$cvs_user", "Removed:"));
  614. push(@text, " Log:");
  615. push(@text, &read_logfile("$LOG_FILE.$i.$id.$cvs_user", " "));
  616. push(@mlist_list, &read_file_lines("$MLIST_FILE.$i.$id.$cvs_user"));
  617. if ($rcsidinfo == 2) {
  618. if (-e "$SUMMARY_FILE.$i.$id.$cvs_user") {
  619. push(@text, " ");
  620. push(@text, " Revision Changes Path");
  621. push(@text, &read_logfile("$SUMMARY_FILE.$i.$id.$cvs_user", " "));
  622. }
  623. }
  624. push(@text, "");
  625. }
  626. #
  627. # Now generate the extra info for the mail message..
  628. #
  629. if ($rcsidinfo == 1) {
  630. $revhdr = 0;
  631. for ($i = 0; ; $i++) {
  632. last if (! -e "$LOG_FILE.$i.$id.$cvs_user");
  633. if (-e "$SUMMARY_FILE.$i.$id.$cvs_user") {
  634. if (!$revhdr++) {
  635. push(@text, "Revision Changes Path");
  636. }
  637. push(@text, &read_logfile("$SUMMARY_FILE.$i.$id.$cvs_user", ""));
  638. }
  639. }
  640. if ($revhdr) {
  641. push(@text, ""); # consistancy...
  642. }
  643. }
  644. %mlist_hash = ();
  645. foreach (@mlist_list) { $mlist_hash{ $_ } = 1; }
  646. #
  647. # Mail out the notification.
  648. #
  649. &mail_notification([ keys(%mlist_hash) ], @text);
  650. &cleanup_tmpfiles;
  651. exit 0;