cvs commit: www/scripts svn2html2.pl update-website.sh

lizardo at linuxfromscratch.org lizardo at linuxfromscratch.org
Sun Jul 11 16:01:03 PDT 2004


lizardo     04/07/11 17:01:03

  Modified:    scripts  update-website.sh
  Added:       scripts  svn2html2.pl
  Log:
  Added new version of svn2html.pl, contributed by Kevin P. Fleming
  
  Revision  Changes    Path
  1.24      +2 -1      www/scripts/update-website.sh
  
  Index: update-website.sh
  ===================================================================
  RCS file: /home/cvsroot/www/scripts/update-website.sh,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- update-website.sh	10 Jul 2004 01:51:00 -0000	1.23
  +++ update-website.sh	11 Jul 2004 23:01:03 -0000	1.24
  @@ -44,6 +44,7 @@
   CL2HTML="$SCRIPTS/cl2html.pl"
   MANAGE_NEWS="$SCRIPTS/manage_news.pl"
   SVN2HTML="$SCRIPTS/svn2html.pl"
  +SVN2HTML2="$SCRIPTS/svn2html2.pl"
   SVNLOG="svn log --verbose --xml"
   TEMPLATES="$NEWSITE/templates"
   YEAR=`date +%Y`
  @@ -124,7 +125,7 @@
   cp $TEMPLATES/alfs/news-top.html news.html
   $MANAGE_NEWS -i news-$YEAR.txt >> news.html
   $MANAGE_NEWS -i ../news-$YEAR.txt >> news.html
  -$SVNLOG $SVN/ALFS 2>/dev/null | $SVN2HTML --with-branchname >> news.html
  +$SVN2HTML2 --project ALFS --with-branchname >> news.html
   cat $TEMPLATES/alfs/news-bottom.html >> news.html
   
   ##########################################
  
  
  
  1.1                  www/scripts/svn2html2.pl
  
  Index: svn2html2.pl
  ===================================================================
  #!/usr/bin/perl
  # svn2html2.pl - Convert the XML output of "svn log" to (X)HTML
  
  # Copyright (C) 2004 Anderson Lizardo <lizardo at linuxfromscratch.org>
  #                    Kevin P. Fleming <kpfleming at linuxfromscratch.org>
  # 
  # This program is free software; you can redistribute it and/or modify
  # it under the terms of the GNU General Public License as published by
  # the Free Software Foundation; either version 2 of the License, or
  # (at your option) any later version.
  #
  # This program is distributed in the hope that it will be useful,
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  # GNU General Public License for more details.
  #
  # You should have received a copy of the GNU General Public License
  # along with this program; if not, write to the Free Software
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  
  use strict;
  use warnings;
  
  use Getopt::Long;
  use Pod::Usage;
  use POSIX qw(strftime);
  use XML::Parser;
  
  # Commit messages may be in Unicode, so we need to tell Perl about it
  binmode(STDOUT, ":utf8");
  
  # Output only the latest $entries_limit author(s) commits
  my $entries_limit = 10;
  
  my $help = 0;
  my $man = 0;
  my $infile = "";
  my $project = "";
  my $with_filename = 0;
  my $with_branchname = 0;
  
  GetOptions(
      "help" => \$help,
      "man" => \$man,
      "infile=s" => \$infile,
      "with-filename", \$with_filename,
      "with-branchname", \$with_branchname,
      "project=s" => \$project,
  ) or pod2usage(1);
  
  pod2usage(1) if $help;
  pod2usage(1) unless $project;
  pod2usage(-exitstatus => 0, -verbose => 2) if $man;
  
  my $svnproject = "svn://svn.linuxfromscratch.org/$project";
  
  my $date = "";     # Current date
  my $buffer = "";   # Current text in buffer
  my $author = "";   # Current author
  my %messages;      # Commit messages, hashed by project/date/author
  my %files;         # Files affected by commit, hashed by branch/tag
  
  my $entry_count = 0;
  
  my %users = load_mapfile(); # user <-> Full Name conversion map
  
  my %projects = load_projectmap();
  
  my $parser = new XML::Parser(
      Handlers => {
          Start => \&handle_StartTag,
          End => \&handle_EndTag,
          Char => \&handle_Text,
      },
  );
  
  if ($infile) {
      eval { $parser->parsefile($infile) } or pod2usage("$0: $@");
  }
  else {
      open(LOG, "svn log --verbose --xml $svnproject |");
      $parser->parse(\*LOG);
      close LOG;
  }
  
  sub handle_StartTag {
      $buffer = "";
  }
  
  sub handle_EndTag {
      my (undef, $tag) = @_;
  
      if ($tag eq "author") {
  	$author = $users{$buffer} ? $users{$buffer} : $buffer;
      }
      elsif ($tag eq "date" and $buffer =~ /^(\d{4}-\d{2}-\d{2})T/) {
          # Flush buffer if date has changed
          # print_log() if ($date and $1 ne $date);
          $date = $1;
      }
      elsif ($tag eq "path") {
  	my $project;
  
  	# sort the project keys in descending order by length,
  	# to ensure that subproject entries are not assigned
  	# to their parent project
  	foreach (sort { length $b <=> length $a } (keys %projects)) {
  	    if ($buffer =~ /^\/$_/) {
  		$project = $_;
  		last;
  	    }
  	}
  	if ($project) {
  	    $buffer =~ s/^\/$project\/*//;
  	    my @path = split('/', $buffer);
  		my $fileskey = "root";
  		my $subdir = shift @path;
  		if ($subdir) {
  		    if (($subdir eq "branches") or ($subdir eq "tags")) {
  			# check if this path is for an item within the branch/tag, or
  			# for the branch/tag itself
  			if ($#path >= 1) {
  			    $fileskey = $subdir . "/" . shift @path;
  			}
  			else {
  			    unshift @path, $subdir;
  			    $fileskey = "root";
  			}
  		    }
  		    elsif ($subdir eq "trunk") {
  			# check if this path is for an item within the subdir, or
  			# for the subdir itself
  			if ($#path >= 0) {
  			    $fileskey = $subdir;
  			}
  			else {
  			    unshift @path, $subdir;
  			    $fileskey = "root";
  			}
  		    }
  		    else {
  			unshift @path, $subdir;
  		    }
  		}
  		unshift @{$files{$project}{$fileskey}}, File::Spec->catdir(join('/', @path));
  	}
      }
      elsif ($tag eq "msg") {
  	my $message;
  
  	# Remove ASCII "bullets" ("* like this") from commit messages
  	$buffer =~ s/^\s*\*\s+//;
  	chomp $buffer;
  
  	foreach my $project (keys %files) {
  	    $message = $buffer;
  
  	    if ($with_filename and $with_branchname) {
  		my $files;
  		my $msg;
  
  		foreach my $branch (keys %{$files{$project}}) {
  		    $msg = $branch . ": ";
  
  		    $files = join(", ", @{$files{$project}{$branch}});
  		    $files =~ s/, $//;
  		    $msg .= "(" . $files . ") ";
  
  		    $msg .= $message;
  
  		    chomp $message;
  		    unshift @{$messages{$project}{$date}{$author}}, $msg;
  		}
  	    }
  	    elsif ($with_branchname) {
  		my $branches;
  
  		foreach (keys %{$files{$project}}) {
  		    $branches .= $_ . ", ";
  		}
  		$branches =~ s/, $/: /;
  		$message = $branches . $message;
  		unshift @{$messages{$project}{$date}{$author}}, $message;
  	    }
  	    elsif ($with_filename) {
  		my $files;
  
  		foreach my $parent (keys %{$files{$project}}) {
  		    foreach my $file (@{$files{$project}{$parent}}) {
  			if ($parent eq "root") {
  			    $files .= $file;
  			}
  			else {
  			    $files .= $parent . "/" . $file;
  			}
  			$files .= ", ";
  		    }
  		}
  		$files =~ s/, $/: /;
  		$message = $files . $message;
  		unshift @{$messages{$project}{$date}{$author}}, $message;
  	    }
  	    else {
  		unshift @{$messages{$project}{$date}{$author}}, $message;
  	    }
  	}
  	undef %files;
      }
      elsif ($tag eq "log") {
  	print_log();
      }
  }
  
  sub handle_Text {
      my (undef , $text) = @_;
  
      # Encode "special" entities
      $text =~ s/\&/\&/g;
      $text =~ s/</\</g;
      $text =~ s/>/\>/g;
      #$text =~ s/\"/\"/g;
      #$text =~ s/\'/\'/g;
  
      # Add current text to the buffer
      $buffer .= $text;
  }
  
  # Convert ISO 8601 date (yyyy-mm-dd) to the specified format
  sub isodate2any {
      my ($date, $format) = @_;
      if ($date =~ /(\d{4})-(\d{2})-(\d{2})/) {
          return strftime($format, 0, 0, 0, $3, $2 - 1, $1 - 1900);
      }
      else {
          return undef;
      }
  }
  
  sub print_log {
      print "<ul>\n";
      # loop "by project"
      foreach my $project (sort (keys %messages)) {
  	$entry_count = 0;
  	print "\t<li>\n\t\t<h3>" . $projects{$project} . "</h3>\n";
  	print "\t\t<ul>\n";
  	# loop "by date"
  	foreach my $date (sort (keys %{$messages{$project}})) {
  	    last if $entry_count++ == $entries_limit;
  	    # loop "by author"
  	    foreach (sort (keys %{$messages{$project}{$date}})) {
  		print "\t\t\t<li>\n\t\t\t<h4>" . $_ . " - " . isodate2any($date, '%Y/%m/%d') . "</h4>\n";
  		print "\t\t\t<ul>\n";
  		foreach (@{$messages{$project}{$date}{$_}}) {
  		    print "\t\t\t<li>" . $_ . "</li>\n";
  		}
  		print "\t\t\t</ul>\n";
  		print "\t\t\t</li>\n";
  	    }
  	}
  	print "\t\t</ul>\n";
  	print "\t</li>\n";
      }
      print "</ul>\n";
      undef %messages;
  }
  
  sub load_mapfile {
  	my %map;
  	my $map_file = '/etc/passwd';
  
  	open(PASSWD, $map_file) || die "Could not open $map_file\: $!";
  	while (<PASSWD>) {
  		chomp;
  		my @user = split ':';
  		my $login = $user[0];
  		my ($fn) = split(',', $user[4]);
  		$map{$login} = $fn;
  	}
  	close PASSWD;
  	return %map;
  }
  
  sub load_projectmap {
      my %map;
      my $parent;
      my $current;
      my $desc;
  
      open(LEVEL1, "svn list $svnproject |");
      while (<LEVEL1>) {
  	chomp;
  	chop;
  	$desc = qx!svn propget project_desc $svnproject/$_!;
  	chomp $desc;
  	if ($desc) {
  	    $map{$_} = $desc;
  	}
  	else {
  	    my $level1 = $_;
  
  	    open(LEVEL2, "svn list $svnproject/$level1 |");
  	    while (<LEVEL2>) {
  		chomp;
  		chop;
  		$desc = qx!svn propget project_desc $svnproject/$level1/$_!;
  		chomp $desc;
  		if ($desc) {
  		    $map{$level1 . "/" . $_} = $desc;
  		}
  	    }
  	    close LEVEL2;
  	}
      }
      close LEVEL1;
      return %map;
  }
  
  __END__
  
  =head1 NAME
  
  svn2html2.pl - convert the XML output of "svn log" to (X)HTML
  
  =head1 SYNOPSIS
  
  svn2html2.pl --project project_name [--help|--man] [--with-filename] [--with-branchname] [--infile xml_file]
  
      Options:
          --project         Specifies the top-level project name to process
          --infile          Parse XML from a file
          --with-branchname Prepend branch names to commit messages
          --with-filename   Prepend filenames to commit messages
          --help            Show brief help message
          --man             Full documentation
  
  =head1 DESCRIPTION
  
  B<svn2html2.pl> converts the XML code produced by "svn log --xml" to
  HTML or XHTML code.
  
  =head1 OPTIONS
  
  =over
  
  =item B<--project project_name>
  
  Specifies the top-level project to process from the Subversion repository. This
  program will scan all first- and second-level directories in that project for
  svn properties called "project_desc"; any directory found with that property
  will have its log messages processed and grouped together, and the value of that
  property will be used the as description of the project in the resulting HTML.
  
  =item B<--infile xml_file>
  
  Specify which XML file to parse. This file must be the output of "svn log --xml".
  By default, B<svn2html2.pl> reads XML code from standard input.
  
  =item B<--with-branchname>
  
  This option prepends branch names to each commit message.
  
  =item B<--with-filename>
  
  This option prepends filenames to each commit message.
  
  =item B<--help>
  
  Print a brief help message and exits.
  
  =item B<--man>
  
  Print the manual page and exits.
  
  =back
  
  =head1 AUTHOR
  
  Copyright (C) 2004 Anderson Lizardo <lizardo at linuxfromscratch.org>
                     Kevin P. Fleming <kpfleming at linuxfromscratch.org>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.
  
  =cut
  
  
  



More information about the website mailing list