]>
Commit | Line | Data |
---|---|---|
8b9b7edf | 1 | --- cvsspam.rb 2005-07-11 16:53:29.000000000 +0100 |
d0da94c0 ER |
2 | +++ cvsspam.rb 2007-09-21 11:08:17.000000000 +0100 |
3 | @@ -590,6 +590,42 @@ | |
4 | end | |
5 | end | |
6 | ||
7 | +# outputs commit log comment text supplied by LogReader as preformatted Text | |
8 | +class TextCommentHandler < LineConsumer | |
9 | + def initialize | |
10 | + @lastComment = nil | |
11 | + end | |
12 | + | |
13 | + def setup | |
14 | + @haveBlank = false | |
15 | + @comment = "" | |
16 | + end | |
17 | + | |
18 | + def consume(line) | |
19 | + if line =~ /^\s*$/ | |
20 | + @haveBlank = true | |
21 | + else | |
22 | + if @haveBlank | |
23 | + @comment += "\n" | |
24 | + @haveBlank = false | |
25 | + end | |
26 | + $mailSubject = line unless $mailSubject.length > 0 | |
27 | + @comment += line += "\n" | |
28 | + end | |
29 | + end | |
30 | + | |
31 | + def teardown | |
32 | + unless @comment == @lastComment | |
33 | + #println("<pre class=\"comment\">") | |
34 | + encoded = @comment | |
35 | + $commentEncoder.gsub!(encoded) | |
36 | + println(encoded) | |
37 | + #println("</pre>") | |
38 | + @lastComment = @comment | |
39 | + end | |
40 | + end | |
41 | +end | |
42 | + | |
43 | ||
44 | # Handle lines from LogReader that represent the name of the branch tag for | |
45 | # the next file in the log. When files are committed to the trunk, the log | |
46 | @@ -649,6 +685,31 @@ | |
47 | end | |
48 | end | |
49 | ||
50 | +# Reads a line giving the path and name of the current file being considered | |
51 | +# from our log of all files changed in this commit. Subclasses make different | |
52 | +# records depending on whether this commit adds, removes, or just modifies this | |
53 | +# file | |
54 | +class TextFileHandler < LineConsumer | |
55 | + def setTagHandler(handler) | |
56 | + @tagHandler = handler | |
57 | + end | |
58 | + | |
59 | + def consume(line) | |
60 | + $file = FileEntry.new(line) | |
61 | + if $diff_output_limiter.choose_to_limit? | |
62 | + $file.has_diff = false | |
63 | + end | |
64 | + #$fileEntries << $file | |
65 | + $file.tag = getTag | |
66 | + handleFile($file) | |
67 | + end | |
68 | + | |
69 | + protected | |
70 | + def getTag | |
71 | + @tagHandler.getLastTag | |
72 | + end | |
73 | +end | |
74 | + | |
75 | # A do-nothing superclass for objects that know how to create hyperlinks to | |
76 | # web CVS interfaces (e.g. CVSweb). Subclasses overide these methods to | |
77 | # wrap HTML link tags arround the text that this classes methods generate. | |
78 | @@ -659,6 +720,11 @@ | |
79 | htmlEncode(path) | |
80 | end | |
81 | ||
82 | + # text path | |
83 | + def textpath(path, tag) | |
84 | + path | |
85 | + end | |
86 | + | |
87 | # Just returns the value of the 'version' argument. Subclasses should change | |
88 | # this into a link to the given version of the file. | |
89 | def version(path, version) | |
90 | @@ -670,6 +736,11 @@ | |
91 | def diff(file) | |
92 | '->' | |
93 | end | |
94 | + | |
95 | + # text diff | |
96 | + def textdiff(file) | |
97 | + '->' | |
98 | + end | |
99 | end | |
100 | ||
101 | # Superclass for objects that can link to CVS frontends on the web (ViewCVS, | |
102 | @@ -810,6 +881,31 @@ | |
103 | end | |
104 | end | |
105 | ||
106 | +# Note when LogReader finds record of a file that was added in this commit | |
107 | +class TextAddedFileHandler < TextFileHandler | |
108 | + def handleFile(file) | |
109 | + file.type="A" | |
110 | + file.toVer=$toVer | |
111 | + end | |
112 | +end | |
113 | + | |
114 | +# Note when LogReader finds record of a file that was removed in this commit | |
115 | +class TextRemovedFileHandler < TextFileHandler | |
116 | + def handleFile(file) | |
117 | + file.type="R" | |
118 | + file.fromVer=$fromVer | |
119 | + end | |
120 | +end | |
121 | + | |
122 | +# Note when LogReader finds record of a file that was modified in this commit | |
123 | +class TextModifiedFileHandler < TextFileHandler | |
124 | + def handleFile(file) | |
125 | + file.type="M" | |
126 | + file.fromVer=$fromVer | |
127 | + file.toVer=$toVer | |
128 | + end | |
129 | +end | |
130 | + | |
131 | ||
132 | # Used by UnifiedDiffHandler to record the number of added and removed lines | |
133 | # appearing in a unidiff. | |
134 | @@ -1030,6 +1126,160 @@ | |
135 | end | |
136 | end | |
137 | ||
138 | +# Used by TextUnifiedDiffHandler to produce an Text | |
139 | +class TextUnifiedDiffColouriser < LineConsumer | |
140 | + def initialize | |
141 | + @currentState = "@" | |
142 | + @currentStyle = "info" | |
143 | + @lineJustDeleted = nil | |
144 | + @lineJustDeletedSuperlong = false | |
145 | + @truncatedLineCount = 0 | |
146 | + end | |
147 | + | |
148 | + def output=(io) | |
149 | + @emailIO = io | |
150 | + end | |
151 | + | |
152 | + def consume(line) | |
153 | + initial = line[0,1] | |
154 | + superlong_line = false | |
155 | + if $maxDiffLineLength && line.length > $maxDiffLineLength+1 | |
156 | + line = line[0, $maxDiffLineLength+1] | |
157 | + superlong_line = true | |
158 | + @truncatedLineCount += 1 | |
159 | + end | |
160 | + if initial != @currentState | |
161 | + prefixLen = 1 | |
162 | + suffixLen = 0 | |
163 | + if initial=="+" && @currentState=="-" && @lineJustDeleted!=nil | |
164 | + # may be an edit, try to highlight the changes part of the line | |
165 | + a = line[1,line.length-1] | |
166 | + b = @lineJustDeleted[1,@lineJustDeleted.length-1] | |
167 | + prefixLen = commonPrefixLength(a, b)+1 | |
168 | + suffixLen = commonPrefixLength(a.reverse, b.reverse) | |
169 | + # prevent prefix/suffux having overlap, | |
170 | + suffixLen = min(suffixLen, min(line.length,@lineJustDeleted.length)-prefixLen) | |
171 | + deleteInfixSize = @lineJustDeleted.length - (prefixLen+suffixLen) | |
172 | + addInfixSize = line.length - (prefixLen+suffixLen) | |
173 | + oversize_change = deleteInfixSize*100/@lineJustDeleted.length>33 || addInfixSize*100/line.length>33 | |
174 | + | |
175 | + if prefixLen==1 && suffixLen==0 || deleteInfixSize<=0 || oversize_change | |
176 | + print(@lineJustDeleted) | |
177 | + else | |
178 | + print(@lineJustDeleted[0,prefixLen]) | |
179 | + print(@lineJustDeleted[prefixLen,deleteInfixSize]) | |
180 | + print(@lineJustDeleted[@lineJustDeleted.length-suffixLen,suffixLen]) | |
181 | + end | |
182 | + if superlong_line | |
183 | + println("[...]") | |
184 | + else | |
185 | + println("") | |
186 | + end | |
187 | + @lineJustDeleted = nil | |
188 | + end | |
189 | + if initial=="-" | |
190 | + @lineJustDeleted=line | |
191 | + @lineJustDeletedSuperlong = superlong_line | |
192 | + shift(initial) | |
193 | + # we'll print it next time (fingers crossed) | |
194 | + return | |
195 | + elsif @lineJustDeleted!=nil | |
196 | + print(@lineJustDeleted) | |
197 | + if @lineJustDeletedSuperlong | |
198 | + println("[...]") | |
199 | + else | |
200 | + println("") | |
201 | + end | |
202 | + @lineJustDeleted = nil | |
203 | + end | |
204 | + shift(initial) | |
205 | + if prefixLen==1 && suffixLen==0 || addInfixSize<=0 || oversize_change | |
206 | + encoded = line | |
207 | + else | |
208 | + encoded = line[0,prefixLen] + | |
209 | + line[prefixLen,addInfixSize] + | |
210 | + line[line.length-suffixLen,suffixLen] | |
211 | + end | |
212 | + else | |
213 | + encoded = line | |
214 | + end | |
215 | + if initial=="-" | |
216 | + unless @lineJustDeleted==nil | |
217 | + print(@lineJustDeleted) | |
218 | + if @lineJustDeletedSuperlong | |
219 | + println("[...]") | |
220 | + else | |
221 | + println("") | |
222 | + end | |
223 | + @lineJustDeleted=nil | |
224 | + end | |
225 | + end | |
226 | + print(encoded) | |
227 | + if superlong_line | |
228 | + println("[...]") | |
229 | + else | |
230 | + println("") | |
231 | + end | |
232 | + end | |
233 | + | |
234 | + def teardown | |
235 | + unless @lineJustDeleted==nil | |
236 | + print(@lineJustDeleted) | |
237 | + if @lineJustDeletedSuperlong | |
238 | + println("[...]") | |
239 | + else | |
240 | + println("") | |
241 | + end | |
242 | + @lineJustDeleted = nil | |
243 | + end | |
244 | + shift(nil) | |
245 | + if @truncatedLineCount>0 | |
246 | + println("[Note: Some over-long lines of diff output only partialy shown]") | |
247 | + end | |
248 | + end | |
249 | + | |
250 | + # start the diff output, using the given lines as the 'preamble' bit | |
251 | + def start_output(*lines) | |
252 | + println("--------------------------------------------------------------------------------") | |
253 | + case $file.type | |
254 | + when "A" | |
255 | + print($frontend.textpath($file.basedir, $file.tag)) | |
256 | + println("\n") | |
257 | + println("#{$file.file} added at #{$frontend.version($file.path,$file.toVer)}") | |
258 | + when "R" | |
259 | + print($frontend.textpath($file.basedir, $file.tag)) | |
260 | + println("\n") | |
261 | + println("#{$file.file} removed after #{$frontend.version($file.path,$file.fromVer)}") | |
262 | + when "M" | |
263 | + print($frontend.textpath($file.basedir, $file.tag)) | |
264 | + println("\n") | |
265 | + println("#{$file.file} #{$frontend.version($file.path,$file.fromVer)} #{$frontend.textdiff($file)} #{$frontend.version($file.path,$file.toVer)}") | |
266 | + end | |
267 | + lines.each do |line| | |
268 | + println(line) | |
269 | + end | |
270 | + end | |
271 | + | |
272 | + private | |
273 | + | |
274 | + def formatChange(text) | |
275 | + return '^M' if text=="\r" | |
276 | + end | |
277 | + | |
278 | + def shift(nextState) | |
279 | + @currentState = nextState | |
280 | + end | |
281 | + | |
282 | + def commonPrefixLength(a, b) | |
283 | + length = 0 | |
284 | + a.each_byte do |char| | |
285 | + break unless b[length]==char | |
286 | + length = length + 1 | |
287 | + end | |
288 | + return length | |
289 | + end | |
290 | +end | |
291 | + | |
292 | ||
293 | # Handle lines from LogReader that are the output from 'cvs diff -u' for the | |
294 | # particular file under consideration | |
295 | @@ -1084,6 +1334,57 @@ | |
296 | end | |
297 | end | |
298 | ||
299 | +# Handle lines from LogReader that are the output from 'cvs diff -u' for the | |
300 | +# particular file under consideration for Text | |
301 | +class TextUnifiedDiffHandler < LineConsumer | |
302 | + def setup | |
303 | + @stats = UnifiedDiffStats.new | |
304 | + @colour = TextUnifiedDiffColouriser.new | |
305 | + @colour.output = @emailIO | |
306 | + @lookahead = nil | |
307 | + end | |
308 | + | |
309 | + def consume(line) | |
310 | + case lineno() | |
311 | + when 1 | |
312 | + @diffline = line | |
313 | + when 2 | |
314 | + @lookahead = line | |
315 | + when 3 | |
316 | + if $file.wants_diff_in_mail? | |
317 | + @colour.start_output(@diffline, @lookahead, line) | |
318 | + end | |
319 | + else | |
320 | + @stats.consume(line) | |
321 | + if $file.wants_diff_in_mail? | |
322 | + if $maxLinesPerDiff.nil? || @stats.diffLines < $maxLinesPerDiff | |
323 | + @colour.consume(line) | |
324 | + elsif @stats.diffLines == $maxLinesPerDiff | |
325 | + @colour.consume(line) | |
326 | + @colour.teardown | |
327 | + end | |
328 | + end | |
329 | + end | |
330 | + end | |
331 | + | |
332 | + def teardown | |
333 | + if @lookahead == nil | |
334 | + $file.isEmpty = true | |
335 | + elsif @lookahead =~ /Binary files .* and .* differ/ | |
336 | + $file.isBinary = true | |
337 | + else | |
338 | + if $file.wants_diff_in_mail? | |
339 | + if $maxLinesPerDiff && @stats.diffLines > $maxLinesPerDiff | |
340 | + println("[truncated at #{$maxLinesPerDiff} lines; #{@stats.diffLines-$maxLinesPerDiff} more skipped]") | |
341 | + else | |
342 | + @colour.teardown | |
343 | + end | |
344 | + $file.has_diff = true | |
345 | + end | |
346 | + end | |
347 | + end | |
348 | +end | |
349 | + | |
350 | ||
351 | # a filter that counts the number of characters output to the underlying object | |
352 | class OutputCounter | |
353 | @@ -1381,6 +1682,18 @@ | |
354 | $handlers["R"].setTagHandler(tagHandler) | |
355 | $handlers["M"].setTagHandler(tagHandler) | |
356 | ||
357 | +$texthandlers = Hash[">" => TextCommentHandler.new, | |
358 | + "U" => TextUnifiedDiffHandler.new, | |
359 | + "T" => tagHandler, | |
360 | + "A" => TextAddedFileHandler.new, | |
361 | + "R" => TextRemovedFileHandler.new, | |
362 | + "M" => TextModifiedFileHandler.new, | |
363 | + "V" => VersionHandler.new] | |
364 | + | |
365 | +$texthandlers["A"].setTagHandler(tagHandler) | |
366 | +$texthandlers["R"].setTagHandler(tagHandler) | |
367 | +$texthandlers["M"].setTagHandler(tagHandler) | |
368 | + | |
369 | $fileEntries = Array.new | |
370 | $task_list = Array.new | |
371 | $allTags = Hash.new | |
372 | @@ -1403,6 +1716,24 @@ | |
373 | ||
374 | end | |
375 | ||
376 | +File.open("#{$logfile}.emailtexttmp", File::RDWR|File::CREAT|File::TRUNC) do |mail| | |
377 | + | |
378 | + $diff_output_limiter = OutputSizeLimiter.new(mail, $mail_size_limit) | |
379 | + | |
380 | + File.open($logfile) do |log| | |
381 | + reader = LogReader.new(log) | |
382 | + | |
383 | + until reader.eof | |
384 | + handler = $texthandlers[reader.currentLineCode] | |
385 | + if handler == nil | |
386 | + raise "No handler file lines marked '##{reader.currentLineCode}'" | |
387 | + end | |
388 | + handler.handleLines(reader.getLines, $diff_output_limiter) | |
389 | + end | |
390 | + end | |
391 | + | |
392 | +end | |
393 | + | |
394 | if $subjectPrefix == nil | |
395 | $subjectPrefix = "[CVS #{Repository.array.join(',')}]" | |
396 | end | |
397 | @@ -1432,7 +1763,10 @@ | |
398 | ||
399 | # generate the email header (and footer) having already generated the diffs | |
400 | # for the email body to a temp file (which is simply included in the middle) | |
401 | -def make_html_email(mail) | |
402 | +def make_html_email(mail, boundary) | |
403 | + mail.puts("--#{boundary}") | |
404 | + mail.puts("Content-Type: text/html;" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) | |
405 | + mail.puts("Content-Disposition: inline\n\n"); | |
406 | mail.puts(<<HEAD) | |
407 | <html> | |
408 | <head> | |
409 | @@ -1660,7 +1994,7 @@ | |
410 | mail.puts("<center><small><a href=\"http://www.badgers-in-foil.co.uk/projects/cvsspam/\" title=\"commit -> email\">CVSspam</a> #{$version}</small></center>") | |
411 | ||
412 | mail.puts("</body></html>") | |
413 | - | |
414 | + mail.puts("\n\n--#{boundary}--\n\n") | |
415 | end | |
416 | ||
417 | # Tries to look up an 'alias' email address for the given string in the | |
418 | @@ -1818,11 +2152,188 @@ | |
419 | ||
420 | $from_address = sender_alias($from_address) unless $from_address.nil? | |
421 | ||
422 | +def rand_string(len) | |
423 | + chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a | |
424 | + newpass = "" | |
425 | + 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] } | |
426 | + return newpass | |
427 | +end | |
428 | + | |
429 | +def make_text_email(mail, boundary) | |
430 | + mail.puts(<<HEAD) | |
431 | +--#{boundary} | |
432 | +Content-Type: text/plain; charset=us-ascii | |
433 | +Content-Disposition: inline | |
434 | + | |
435 | +HEAD | |
436 | + | |
437 | + haveTags = false | |
438 | + Repository.each do |repository| | |
439 | + haveTags |= repository.has_multiple_tags | |
440 | + end | |
441 | + | |
442 | + filesAdded = 0 | |
443 | + filesRemoved = 0 | |
444 | + filesModified = 0 | |
445 | + totalLinesAdded = 0 | |
446 | + totalLinesRemoved = 0 | |
447 | + file_count = 0 | |
448 | + lastPath = "" | |
449 | + last_repository = nil | |
450 | + $fileEntries.each do |file| | |
451 | + unless file.repository == last_repository | |
452 | + last_repository = file.repository | |
453 | + if last_repository.has_multiple_tags | |
454 | + mail.print("Mixed-tag commit") | |
455 | + else | |
456 | + mail.print("Commit") | |
457 | + end | |
458 | + mail.print(" in #{last_repository.common_prefix}") | |
459 | + if last_repository.trunk_only? | |
460 | + mail.print(" on MAIN") | |
461 | + else | |
462 | + mail.print(" on ") | |
463 | + tagCount = 0 | |
464 | + last_repository.each_tag do |tag| | |
465 | + tagCount += 1 | |
466 | + if tagCount > 1 | |
467 | + mail.print tagCount<last_repository.tag_count ? ", " : " & " | |
468 | + end | |
469 | + mail.print tag ? tag : "MAIN" | |
470 | + end | |
471 | + end | |
472 | + mail.puts("\n") | |
473 | + end | |
474 | + file_count += 1 | |
475 | + if file.addition? | |
476 | + filesAdded += 1 | |
477 | + elsif file.removal? | |
478 | + filesRemoved += 1 | |
479 | + elsif file.modification? | |
480 | + filesModified += 1 | |
481 | + end | |
482 | + name = file.name_after_common_prefix | |
483 | + slashPos = name.rindex("/") | |
484 | + if slashPos==nil | |
485 | + prefix = "" | |
486 | + else | |
487 | + thisPath = name[0,slashPos] | |
488 | + name = name[slashPos+1,name.length] | |
489 | + if thisPath == lastPath | |
490 | + prefix = " "*(slashPos) + "/" | |
491 | + else | |
492 | + prefix = thisPath + "/" | |
493 | + end | |
494 | + lastPath = thisPath | |
495 | + end | |
496 | + if file.addition? | |
497 | + name = "#{name}" | |
498 | + elsif file.removal? | |
499 | + name = "#{name}" | |
500 | + end | |
501 | + if file.has_diff? | |
502 | + mail.print("#{prefix}#{name} ") | |
503 | + else | |
504 | + mail.print("#{prefix}#{name} ") | |
505 | + end | |
506 | + if file.isEmpty | |
507 | + mail.print("[empty] ") | |
508 | + elsif file.isBinary | |
509 | + mail.print("[binary] ") | |
510 | + else | |
511 | + if file.lineAdditions>0 | |
512 | + totalLinesAdded += file.lineAdditions | |
513 | + mail.print("+#{file.lineAdditions} ") | |
514 | + end | |
515 | + if file.lineRemovals>0 | |
516 | + totalLinesRemoved += file.lineRemovals | |
517 | + mail.print("-#{file.lineRemovals} ") | |
518 | + end | |
519 | + end | |
520 | + if last_repository.has_multiple_tags | |
521 | + if file.tag | |
522 | + mail.print("#{file.tag} ") | |
523 | + else | |
524 | + mail.print("MAIN ") | |
525 | + end | |
526 | + end | |
527 | + if file.addition? | |
528 | + mail.print("added #{$frontend.version(file.path,file.toVer)} ") | |
529 | + elsif file.removal? | |
530 | + mail.print("#{$frontend.version(file.path,file.fromVer)} removed ") | |
531 | + elsif file.modification? | |
532 | + mail.print("#{$frontend.version(file.path,file.fromVer)} #{$frontend.textdiff(file)} #{$frontend.version(file.path,file.toVer)} ") | |
533 | + end | |
534 | + | |
535 | + mail.puts("\n") | |
536 | + end | |
537 | + if $fileEntries.size>1 && (totalLinesAdded+totalLinesRemoved)>0 | |
538 | + if totalLinesAdded>0 | |
539 | + mail.print("+#{totalLinesAdded} ") | |
540 | + end | |
541 | + if totalLinesRemoved>0 | |
542 | + mail.print("-#{totalLinesRemoved} ") | |
543 | + end | |
544 | + mail.puts("\n") | |
545 | + end | |
546 | + | |
547 | + totalFilesChanged = filesAdded+filesRemoved+filesModified | |
548 | + if totalFilesChanged > 1 | |
549 | + changeKind = 0 | |
550 | + if filesAdded>0 | |
551 | + mail.print("#{filesAdded} added") | |
552 | + changeKind += 1 | |
553 | + end | |
554 | + if filesRemoved>0 | |
555 | + mail.print(" + ") if changeKind>0 | |
556 | + mail.print("#{filesRemoved} removed") | |
557 | + changeKind += 1 | |
558 | + end | |
559 | + if filesModified>0 | |
560 | + mail.print(" + ") if changeKind>0 | |
561 | + mail.print("#{filesModified} modified") | |
562 | + changeKind += 1 | |
563 | + end | |
564 | + mail.print(", total #{totalFilesChanged}") if changeKind > 1 | |
565 | + mail.puts(" files\n") | |
566 | + end | |
567 | + | |
568 | + if $task_list.size > 0 | |
569 | + task_count = 0 | |
570 | + $task_list.each do |item| | |
571 | + task_count += 1 | |
572 | + item = htmlEncode(item) | |
573 | + mail.puts("* #{item}\n") | |
574 | + end | |
575 | + end | |
576 | + | |
577 | + | |
578 | + File.open("#{$logfile}.emailtexttmp") do |input| | |
579 | + input.each do |line| | |
580 | + mail.puts(line.chomp) | |
581 | + end | |
582 | + end | |
583 | + if $diff_output_limiter.choose_to_limit? | |
584 | + mail.puts("[Reached #{$diff_output_limiter.written_count} bytes of diffs.") | |
585 | + mail.puts("Since the limit is about #{$mail_size_limit} bytes,") | |
586 | + mail.puts("a further #{$diff_output_limiter.total_count-$diff_output_limiter.written_count} were skipped.]") | |
587 | + end | |
588 | + if $debug | |
589 | + blah("leaving file #{$logfile}.emailtexttmp") | |
590 | + else | |
591 | + File.unlink("#{$logfile}.emailtexttmp") | |
592 | + end | |
593 | + | |
594 | + mail.puts("CVSspam #{$version}") | |
595 | +end | |
596 | + | |
597 | mailer.send($from_address, $recipients) do |mail| | |
598 | mail.header("Subject", mailSubject) | |
599 | inject_threading_headers(mail) | |
600 | mail.header("MIME-Version", "1.0") | |
601 | - mail.header("Content-Type", "text/html" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) | |
602 | + boundary = rand_string(32) | |
603 | + mail.header("Content-Type", "multipart/alternative; boundary=\"#{boundary}\"") | |
604 | + mail.header("Content-Disposition", "inline") | |
605 | if ENV['REMOTE_HOST'] | |
606 | # TODO: I think this will always be an IP address. If a hostname is | |
607 | # possible, it may need encoding of some kind, | |
608 | @@ -1836,6 +2347,7 @@ | |
609 | mail.header("X-Mailer", "CVSspam #{$version} <http://www.badgers-in-foil.co.uk/projects/cvsspam/>") | |
610 | ||
611 | mail.body do |body| | |
612 | - make_html_email(body) | |
613 | + make_text_email(body, boundary) | |
614 | + make_html_email(body, boundary) | |
615 | end | |
616 | end | |
8b9b7edf ER |
617 | --- cvsspam.rb 2009-03-05 02:14:14.149660640 +0200 |
618 | +++ cvsspam.rb 2009-03-05 02:06:57.409693131 +0200 | |
619 | @@ -1943,8 +1943,9 @@ | |
620 | # generate the email header (and footer) having already generated the diffs | |
621 | # for the email body to a temp file (which is simply included in the middle) | |
622 | def make_html_email(mail, boundary) | |
623 | + | |
624 | mail.puts("--#{boundary}") | |
625 | - mail.puts("Content-Type: text/html;" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) | |
626 | + mail.puts("Content-Type: text/html" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) | |
627 | mail.puts("Content-Disposition: inline\n\n"); | |
628 | mail.puts(<<HEAD) | |
629 | <html> | |
630 | @@ -2378,12 +2379,10 @@ | |
631 | end | |
632 | ||
633 | def make_text_email(mail, boundary) | |
634 | - mail.puts(<<HEAD) | |
635 | ---#{boundary} | |
636 | -Content-Type: text/plain; charset=us-ascii | |
637 | -Content-Disposition: inline | |
638 | - | |
639 | -HEAD | |
640 | + | |
641 | + mail.puts("--#{boundary}") | |
642 | + mail.puts("Content-Type: text/plain" + ($charset.nil? ? "" : "; charset=\"#{$charset}\"")) | |
643 | + mail.puts("Content-Disposition: inline\n\n"); | |
644 | ||
645 | haveTags = false | |
646 | Repository.each do |repository| | |
39d8f878 ER |
647 | --- cvsspam.rb 2009-03-05 02:40:37.616133405 +0200 |
648 | +++ cvsspam.rb 2009-03-05 02:38:55.616141228 +0200 | |
649 | @@ -1375,15 +1375,15 @@ | |
650 | when "A" | |
651 | print($frontend.textpath($file.basedir, $file.tag)) | |
652 | println("\n") | |
653 | - println("#{$file.file} added at #{$frontend.version($file.path,$file.toVer)}") | |
654 | + println("#{$file.file} added at #{$file.toVer}") | |
655 | when "R" | |
656 | print($frontend.textpath($file.basedir, $file.tag)) | |
657 | println("\n") | |
658 | - println("#{$file.file} removed after #{$frontend.version($file.path,$file.fromVer)}") | |
659 | + println("#{$file.file} removed after #{$file.fromVer}") | |
660 | when "M" | |
661 | print($frontend.textpath($file.basedir, $file.tag)) | |
662 | println("\n") | |
663 | - println("#{$file.file} #{$frontend.version($file.path,$file.fromVer)} #{$frontend.textdiff($file)} #{$frontend.version($file.path,$file.toVer)}") | |
664 | + println("#{$file.file} #{$file.fromVer} #{$frontend.textdiff($file)} #{$file.toVer}") | |
665 | end | |
666 | lines.each do |line| | |
667 | println(line) | |
668 | @@ -2475,11 +2475,11 @@ | |
669 | end | |
670 | end | |
671 | if file.addition? | |
672 | - mail.print("added #{$frontend.version(file.path,file.toVer)} ") | |
673 | + mail.print("added #{file.toVer} ") | |
674 | elsif file.removal? | |
675 | - mail.print("#{$frontend.version(file.path,file.fromVer)} removed ") | |
676 | + mail.print("#{file.fromVer} removed ") | |
677 | elsif file.modification? | |
678 | - mail.print("#{$frontend.version(file.path,file.fromVer)} #{$frontend.textdiff(file)} #{$frontend.version(file.path,file.toVer)} ") | |
679 | + mail.print("#{file.fromVer} #{$frontend.textdiff(file)} #{file.toVer} ") | |
680 | end | |
681 | ||
682 | mail.puts("\n") | |
f3fbd1ca ER |
683 | --- cvsspam.rb 2009-03-05 19:26:38.950116565 +0200 |
684 | +++ cvsspam.rb 2009-03-05 16:29:57.947827866 +0200 | |
685 | @@ -1862,12 +1862,16 @@ | |
686 | "T" => tagHandler, | |
687 | "A" => TextAddedFileHandler.new, | |
688 | "R" => TextRemovedFileHandler.new, | |
689 | + "C" => CopiedFileHandler.new, | |
690 | "M" => TextModifiedFileHandler.new, | |
691 | + "P" => ModifiedPropsFileHandler.new, | |
692 | "V" => VersionHandler.new] | |
693 | ||
694 | $texthandlers["A"].setTagHandler(tagHandler) | |
695 | $texthandlers["R"].setTagHandler(tagHandler) | |
696 | +$texthandlers["C"].setTagHandler(tagHandler) | |
697 | $texthandlers["M"].setTagHandler(tagHandler) | |
698 | +$texthandlers["P"].setTagHandler(tagHandler) | |
699 | ||
700 | $fileEntries = Array.new | |
701 | $task_list = Array.new |