1 | #!/usr/athena/bin/perl |
---|
2 | |
---|
3 | # In commitinfo, put: |
---|
4 | # ALL $CVSROOT/CVSROOT/record.pl $CVSROOT |
---|
5 | # In loginfo, put: |
---|
6 | # ALL $CVSROOT/CVSROOT/logfilter.pl %{sVv} commit-address diff-adddress |
---|
7 | |
---|
8 | # Mails the CVS commit logs to commit-address. Also mails the commit |
---|
9 | # logs to diff-address, followed by context diffs of the modified |
---|
10 | # files. |
---|
11 | |
---|
12 | use strict; |
---|
13 | use File::Compare; |
---|
14 | use File::Path; |
---|
15 | use File::Spec::Functions ':ALL'; |
---|
16 | use File::stat; |
---|
17 | use Fcntl ':mode'; |
---|
18 | |
---|
19 | my ($sendmail, $dir, @files, $commit_addr, $diff_addr, $tmpdir, $sb); |
---|
20 | my ($filename, $firstdir, $lastdir, $repdir, $old, $new, $file); |
---|
21 | my (@d1, @d2, $i, $subject, $cmd); |
---|
22 | |
---|
23 | $sendmail = ( -x "/usr/sbin/sendmail") ? "/usr/sbin/sendmail" |
---|
24 | : "/usr/lib/sendmail"; |
---|
25 | |
---|
26 | # $ARGV[0] is of the form "dir filename,oldrev,newrev ...". |
---|
27 | ($dir, @files) = split(/ /, $ARGV[0]); |
---|
28 | $commit_addr = $ARGV[1]; |
---|
29 | $diff_addr = $ARGV[2]; |
---|
30 | |
---|
31 | if ($files[0] eq "-") { |
---|
32 | # This is a new directory or import notification. There's no |
---|
33 | # commitinfo step for these operations, so just pass on the |
---|
34 | # supplied log message. |
---|
35 | |
---|
36 | open(COMMITMAIL, "| $sendmail $commit_addr"); |
---|
37 | print COMMITMAIL "To: $commit_addr\n"; |
---|
38 | print COMMITMAIL "Subject: $ARGV[0]\n\n"; |
---|
39 | |
---|
40 | open(DIFFMAIL, "| $sendmail $diff_addr"); |
---|
41 | print DIFFMAIL "To: $diff_addr\n"; |
---|
42 | print DIFFMAIL "Subject: $ARGV[0]\n\n"; |
---|
43 | |
---|
44 | while (<STDIN>) { |
---|
45 | print COMMITMAIL; |
---|
46 | print DIFFMAIL; |
---|
47 | } |
---|
48 | close(COMMITMAIL); |
---|
49 | close(DIFFMAIL); |
---|
50 | |
---|
51 | exit 0; |
---|
52 | } |
---|
53 | |
---|
54 | # Make sure our temporary directory exists and is kosher. |
---|
55 | $tmpdir = "/tmp/athena-cvs-" . getpgrp(); |
---|
56 | $sb = lstat($tmpdir) || die "Can't stat $tmpdir: $!\n"; |
---|
57 | if (!S_ISDIR($sb->mode) || ($sb->mode & (S_IWGRP|S_IWOTH)) || $sb->uid != $>) { |
---|
58 | die "Problem with temporary directory\n"; |
---|
59 | } |
---|
60 | |
---|
61 | # Read the first committed directory (recorded from commitinfo by record.pl). |
---|
62 | $filename = catfile($tmpdir, "firstdir"); |
---|
63 | open(FILE, "< $filename") || die "Can't open $filename for reading: $!\n"; |
---|
64 | $firstdir = <FILE> || die "Can't read $filename: $!\n"; |
---|
65 | chomp $firstdir; |
---|
66 | close(FILE); |
---|
67 | |
---|
68 | # Read the last committed directory (recorded from commitinfo by record.pl). |
---|
69 | $filename = catfile($tmpdir, "lastdir"); |
---|
70 | open(FILE, "< $filename") || die "Can't open $filename for reading: $!\n"; |
---|
71 | $lastdir = <FILE> || die "Can't read $filename: $!\n"; |
---|
72 | chomp $lastdir; |
---|
73 | close(FILE); |
---|
74 | |
---|
75 | # Write out the log message to a file. |
---|
76 | $filename = catfile($tmpdir, "logs"); |
---|
77 | open(FILE, ">> $filename") || die "Can't open $filename for writing: $!\n"; |
---|
78 | while (<STDIN>) { |
---|
79 | if (/^Update of (.*)$/) { |
---|
80 | # Remember the repository directory for the diffs. |
---|
81 | $repdir = $1; |
---|
82 | } |
---|
83 | print FILE; |
---|
84 | } |
---|
85 | close(FILE); |
---|
86 | |
---|
87 | $filename = catfile($tmpdir, "diffs"); |
---|
88 | open(FILE, ">> $filename") || die "Can't open $filename for append: $!\n"; |
---|
89 | # Write out the diffs. |
---|
90 | foreach (@files) { |
---|
91 | ($file, $old, $new) = split(/,/); |
---|
92 | next if ($new eq "NONE"); |
---|
93 | print FILE "\n"; |
---|
94 | print FILE "==================================================\n"; |
---|
95 | if ($old eq "NONE") { |
---|
96 | print FILE "Initial contents of new file $file\n"; |
---|
97 | $cmd = "diff -c /dev/null $file"; |
---|
98 | } else { |
---|
99 | print FILE "Differences for $file (revision $old -> $new)\n"; |
---|
100 | $cmd ="rcsdiff -c -kk -r$old -r$new $repdir/$file 2>/dev/null"; |
---|
101 | } |
---|
102 | print FILE "==================================================\n"; |
---|
103 | open(DIFF, "$cmd|"); |
---|
104 | print FILE while (<DIFF>); |
---|
105 | close(DIFF); |
---|
106 | } |
---|
107 | close(FILE); |
---|
108 | |
---|
109 | if ($dir eq $lastdir) { |
---|
110 | # All the logs are in. Fire off the mail messages. But first, |
---|
111 | # find the common initial sequence of the first and last |
---|
112 | # directories for the subject line. |
---|
113 | @d1 = splitdir($firstdir); |
---|
114 | @d2 = splitdir($lastdir); |
---|
115 | for ($i = 0; $i < scalar @d1; $i++) { |
---|
116 | last if ($d1[$i] ne $d2[$i]); |
---|
117 | } |
---|
118 | $subject = catdir(@d1[0..($i - 1)]); |
---|
119 | |
---|
120 | open(COMMITMAIL, "| $sendmail $commit_addr"); |
---|
121 | print COMMITMAIL "To: $commit_addr\n"; |
---|
122 | print COMMITMAIL "Subject: $subject\n\n"; |
---|
123 | |
---|
124 | open(DIFFMAIL, "| $sendmail $diff_addr"); |
---|
125 | print DIFFMAIL "To: $diff_addr\n"; |
---|
126 | print DIFFMAIL "Subject: $subject\n\n"; |
---|
127 | |
---|
128 | $filename = catfile($tmpdir, "logs"); |
---|
129 | open(FILE, "< $filename") || die "Can't open $filename for reading: $!\n"; |
---|
130 | while (<FILE>) { |
---|
131 | print COMMITMAIL; |
---|
132 | print DIFFMAIL; |
---|
133 | } |
---|
134 | close(FILE); |
---|
135 | close(COMMITMAIL); |
---|
136 | |
---|
137 | $filename = catfile($tmpdir, "diffs"); |
---|
138 | open(FILE, "< $filename") || die "Can't open $filename for reading: $!\n"; |
---|
139 | print DIFFMAIL while (<FILE>); |
---|
140 | close(FILE); |
---|
141 | close(DIFFMAIL); |
---|
142 | |
---|
143 | rmtree($tmpdir); |
---|
144 | } |
---|