Warning, /sdk/kde-dev-scripts/cvsblame is written in an unsupported language. File is not indexed.

0001 #! /usr/bin/env perl
0002 
0003 # cvs blame inspired by Bonsai
0004 # Author: Bernd Gehrmann <bernd@physik.hu-berlin.de>
0005 
0006 =head1 NAME
0007 
0008 cvsblame - Shows a blame-annotated representation of a CVS controlled file in Konqueror.
0009 
0010 =head1 SYNOPSIS
0011 
0012 cvsblame <filename>
0013 
0014 =head1 DESCRIPTION
0015 
0016 cvsblame opens Konqueror to display the output of cvs annotate of
0017 a cvs controlled file. When the mouse is on a revision number shown
0018 in the second column, a popup with the respective log message
0019 appears. 
0020 
0021 In the popup, a proper mailto: link to the author of a revision
0022 can be created as follows: In your home directory, make a file
0023 .cvsblame. In that file, enter for each repository you are working
0024 with a line like
0025 
0026       accounts :pserver:gehrmab@cvs.kde.org:/home/kde /home/bernd/.kdeaccounts
0027 
0028 where the accounts file contains a simple list of cvs usernames in
0029 the first column and the respective mail address in the second.
0030 
0031 =head1 BUGS
0032 
0033 =over 4
0034 
0035 =item Does not really work for filenames which are not in the current directory
0036 
0037 =item Is a hack. Really.
0038 
0039 =back 
0040 
0041 =head1 AUTHOR
0042 
0043 Bernd Gehrmann <bernd@physik.hu-berlin.de>
0044 
0045 =cut
0046 
0047 $file = $ARGV[0];
0048 $outputfile = `kde4-config --path tmp` || './#'; # if we put the file in the cwd, then we keep a '#' at the beggining to help CVS ignore it
0049 ($outputfile) = split(/:/,$outputfile);
0050 chomp $outputfile;
0051 $outputfile .= "cvsblame.$$.html";
0052 $configfile = $ENV{HOME}. "/.cvsblame";
0053 $rootfile = "`pwd`/CVS/Root";
0054 $cvsroot = `cat "$rootfile"`;
0055 chop $cvsroot;
0056 
0057 #
0058 # Look for a username -> mail address mapping
0059 #
0060 
0061 if (open(CONFIG, $configfile)) {
0062     while (<CONFIG>) {
0063         if (/accounts\s*([^\s]*)\s+([^\s]*)/) {
0064             if ($1 eq $cvsroot) {
0065                 $accountfile = $2;
0066             }
0067         }
0068     }
0069     close CONFIG;
0070 }
0071 if ($accountfile) {
0072     open(ACCOUNTS, $accountfile) || die "Account file not found: $accountfile";
0073     while (<ACCOUNTS>) {
0074         if (/([^\s]*)\s+([^\s].*[^\s])\s+([^\s]+)/) {
0075             $mail{$1} = "$2 &lt;$3&gt;";
0076         }
0077         elsif (/([^\s]*)\s+([^\s]*)/) {
0078             $mail{$1} = $2;
0079         }
0080     }
0081 }
0082 
0083 
0084 #
0085 # The real work, first the html header
0086 #
0087 
0088 
0089 open(OUTPUT, ">$outputfile");
0090 print OUTPUT <<EOF;
0091 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
0092 <html>
0093   <head>
0094     <title>Blame annotation for $file</title>
0095   </head>
0096   <script type="text/javascript">
0097     function hidelog(event) {
0098       var target = event.relatedTarget;
0099       while (target && target.id != "popup")
0100         target = target.offsetParent;
0101       if (target)
0102         return;
0103       target = event.target;
0104       while (target.id != "popup")
0105         target = target.offsetParent;
0106       target.style.visibility = "hidden";
0107     }
0108     function init() {
0109       document.getElementById("popup").addEventListener("mouseout", hidelog, false);
0110     }
0111     function poplog(target, rev) {
0112       var popup = document.getElementById("popup");
0113       var x = 120, y = 0;
0114       while (target && target != document)
0115       {
0116           x += target.offsetLeft;
0117           y += target.offsetTop;
0118           target = target.offsetParent;
0119       }
0120       popup.style.pixelLeft = x;
0121       popup.style.pixelTop = y;
0122       popup.innerHTML = rev;
0123       popup.style.visibility = "visible";
0124       return true;
0125     }
0126 EOF
0127 
0128 #
0129 # Translate information from cvs log in javascript stuff
0130 #
0131 
0132 $revision = "";
0133 open (LOG, "cvs log \"$file\"|");
0134 while (<LOG>) {
0135       chop;
0136       $line = $_;
0137       if ($line =~ /^revision (.*)/) {
0138              $revision = $1;
0139              $revstr = "log$revision";
0140              $revstr =~ s/\./_/g;
0141       } elsif ($line =~ /date: ([^;]*);\s*author: ([^;]*);.*/) {
0142              $date = $1;
0143              $author = $2;
0144              if ($mail{$author}) {
0145                  $author = "<a href=\\\"mailto:$mail{$author}\\\">$author</a>";
0146              }
0147              $content = "<b>$revision</b>&nbsp;&nbsp;$author&nbsp;&nbsp;<b>$date<b>";
0148       } elsif ($line eq "----------------------------" && !($revision eq "")) {
0149              print OUTPUT "var $revstr = \"$content\";\n";
0150       } elsif ($line eq "=============================================================================" && !($revision eq "")) {
0151              print OUTPUT "var $revstr = \"$content\";\n";
0152       } else {
0153              $line =~ s/\"/\\\"/g;
0154              $line =~ s/&/&amp;/g;
0155              $line =~ s/</&lt;/g;
0156              $line =~ s/>/&gt;/g;
0157              $content = "$content<br>$line";
0158       }
0159 }
0160 close LOG;
0161 
0162 print OUTPUT <<EOF;
0163   </script>
0164   <style type="text/css">
0165         body {
0166             background: #eeeee0;
0167         }
0168         #popup {
0169             position: absolute;
0170             background: #ffcc99;
0171             border: 1px solid #80664D;
0172             padding: 2px;
0173          }
0174          a:link {
0175             text-decoration: none;
0176          }
0177          a:hover {
0178             text-decoration: underline;
0179          }
0180   </style>
0181   <body text="#000000" onload="init()">
0182     <h1>$file</h1>
0183     <table border=0 cellpadding=0 cellspacing=0 width="100%">
0184 EOF
0185 
0186 #
0187 # Information from cvs annotate
0188 #
0189 
0190 $color = 1;
0191 $lineno = 1;
0192 $oldrevision = "";
0193 $oldlineno = "";
0194 $oldrevstr = "";
0195 open (ANNOTATE, "cvs annotate \"$file\" 2>/dev/null|");
0196 while (<ANNOTATE>) {
0197       chop;
0198       $line = $_;
0199       $revision = substr $line, 0, 13;
0200       $revision =~ s/\s//g;
0201       $author = substr $line, 14, 9;
0202       $author =~ s/\s//g;
0203       $date = substr $line, 23, 9;
0204       $content = substr $line, 35;
0205       $content =~ s/\&/&amp;/g;
0206       $content =~ s/\</&lt;/g;
0207       $content =~ s/\>/&gt;/g;
0208       $revstr = "log$revision";
0209       $revstr =~ s/\./_/g;
0210       if ($revision eq $oldrevision) {
0211           if ($lineno == $oldlineno+20) {
0212               $linkstr = "<span onmouseover=\"return poplog(this, $revstr)\"'>";
0213               $linkendstr = "</span>";
0214               $revauthor = "$author $revision";
0215               $oldlineno = $lineno;
0216           } else {
0217               $linkstr = "";
0218               $linkendstr = "";
0219               $revauthor = "";
0220           }
0221       } else {
0222           $color = ($color == 0)? 1 : 0;
0223           $linkstr = "<span onmouseover=\"return poplog(this, $revstr)\"'>";
0224           $linkendstr = "</span>";
0225           $revauthor = "$author $revision";
0226           $oldlineno = $lineno;
0227           $oldrevision = $revision;
0228       }
0229       print OUTPUT "<tr><td nowrap style=\"background: ", ($color==1)? "#EEEEE0" : "#FFFFCC", "\"><pre>";
0230 
0231       print OUTPUT sprintf '%-5i%s%-14s%s%s', $lineno, $linkstr, $revauthor,$linkendstr, $content;
0232       print OUTPUT "</pre></td></tr>\n";
0233       $lineno++;
0234 }
0235 close ANNOTATE;
0236 
0237 # 
0238 # Finally, the html footer
0239 #
0240 
0241 print OUTPUT <<EOF;
0242     </table>
0243     <div id="popup" style="visibility: hidden"></div>
0244   </body>
0245 </html>
0246 EOF
0247 
0248 close OUTPUT;
0249 
0250 system("kfmclient openProfile webbrowsing $outputfile");
0251 
0252 exit 0;