Jump to content

WikiSVN

From Wikitech
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
This page contains historical information. It may be outdated or unreliable.
#!/usr/bin/perl -w

# Script to pull bug info from SVN and dump them
# to a log to be used for IRC bot.

# Original version by AzaToth 2006-12-23

use strict;
use utf8;

my $TYPES = {
	'Log Message'		=> 'msg',
	'Property Changed'	=> 'prop',
	'Modified Paths'	=> 'mod',
	'Added Paths'		=> 'add',
	'Deleted Paths'		=> 'del',
};

my $FILES = {
	'mod'	=> 'modified',
	'add'	=> 'added',
	'del'	=> 'deleted',
	'prop'	=> 'changed property on',

}; # will contain list of files

my $MAX_COMMENT_LENGTH = 300;
my $LINE_LENGTH = 130;
my $MAX_ONELINE_MODIFIER = 1.5;
my $VIEWVC_URL = "http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=";

$/ = undef;

my $output;
my $filelist = '';
my @allfiles;
my %fields;

my ($author, $rev, $date, $path);

my $contents = <STDIN>;

$contents =~ s/\r\n/\n/g;

if ($contents =~ /^Content-Transfer-Encoding: base64/m) {
	use MIME::Base64;
	$contents =~ s/.*?\n([\S\n]+)\s*$/$1/sg;
	$contents = decode_base64($contents);
	$contents =~ s/\w+[^\n]*?\n={20,}.*//s;
} else {
	$contents =~ s/^\s*.*?\n{2,}(.*?)\w+[^\n]*?\n={20,}.*/$1/s;
}

$contents =~ s/^Author:\s+(\S+)\n//m	and $author = $1 or $author = 'none';
$contents =~ s/^Revision:\s+(\d+)\n//m	and $rev = $1 or $rev = '0';
$contents =~ s/^Date:\s+(.*?)\n\n//m	and $date = $1 or $date = 'now';
chomp($contents);
use Data::Dumper;

my @field = split /\s*\n*(\w+\s\w+):\n-{5,}\n\s*/s, $contents;
shift @field;
foreach (my $i=0; $i <= $#field; $i += 2) {
	my $type = $TYPES->{$field[$i]};
	if(defined $FILES->{$type}) {
		my $file_list = $field[$i + 1];
		my @files = split /\s+/, $file_list;
		$fields{$type} = \@files;

	} else {
		$fields{$type} = $field[$i + 1];
	}
}

foreach my $key(keys %{$FILES}) {
	foreach my $file(@{$fields{$key}}) {
		push @allfiles, [split /\//, $file];
	}
}

my $nbr_of_files = $#allfiles + 1;

my @base = @{ shift @allfiles };
foreach my $file (@allfiles) {
	for my $i(0..$#base) {
		pop	@base if defined $base[$i] and $$file[$i] ne $base[$i];
	}
}

$path = join '/', @base;


my %alldirs;
foreach my $file (@allfiles) {
	my @f = @$file;
	pop @f;
	my $key = join '/', @f;
	next if length $key <= length $path;
	$key = substr ($key, (length $path)+1);
	$alldirs{$key} = 1;
}

my @alldirs = keys %alldirs;
my $nbr_of_dirs = $#alldirs + 1;
$nbr_of_dirs = 1 if $nbr_of_dirs < 1;

if ($nbr_of_files <= 3 and $nbr_of_files > 1) {
	my @extra_files;
	foreach my $file(@allfiles) {
		my $nfile = substr(join('/', @{$file}), (length $path)+1);
		$nfile =~ s/\n//g;
		push @extra_files, $nfile;
	}
	$path .= " (" . join( ', ', @extra_files). ")";
} elsif($nbr_of_files > 1) {
	$path .= " ($nbr_of_files file".($nbr_of_files>1?'s':'')." in $nbr_of_dirs dir".($nbr_of_dirs>1?'s':'').")";
}


$path = 'strange places' if $path eq '';


my @files;
if( $nbr_of_files > 0 ) {
	foreach my $key(keys %{$FILES}) {
		if(defined $fields{$key} and $#{$fields{$key}} +1 > 0) {
			push @files, "$FILES->{$key} \002".($#{$fields{$key}}+1)."\002";
		}
	}
	$filelist = join( ', ' , @files) . ' ' . ( $nbr_of_files > 1 ? 'files' : 'file');
}

$output = "\002SVN\002 (\00303r$rev\003): \00302$author\003 in \00303$path\003 $filelist";

$fields{'msg'} =~ s/([^\n]{$LINE_LENGTH,}?)\s/$1\n/g;
my $submsg = substr ($fields{'msg'}, 0 , $MAX_COMMENT_LENGTH);
if(length $fields{'msg'} > length $submsg) {
	substr( $submsg, -3) = '...';
}

if(length ($output) + length ($submsg) <= $LINE_LENGTH * $MAX_ONELINE_MODIFIER) {
	$output .= ": $submsg\n";
} else {
	$output .= ":\n". join ("\n", map { $_ = "\002|\002 $_"} split /\n/, $submsg) ."\n";
}

$output .= "$VIEWVC_URL$rev\n";

if ($output)
{
	open (OUT, ">>/var/wikisvn/wikisvn.log");
	print $output;
	#print OUT $output;
	close OUT;
}