svn logの結果を月別・人別に集計するperlスクリプト

svn log -q の結果を月別・人別に集計するperlスクリプトを書いたので公開します。

(既にCPANモジュールで同じようなのがあるかもしれませんが。。)

使い方

$ svn log -q . | perl sum_svnlog.pl

$ svn log -q svn://path/to/example | perl sum_svnlog.pl

出力結果

月別・人別にクロス集計されたものが出力されます。
タブ区切りなので、Excelなどにそのまま貼り付けられます。

(名前は小文字に変換されます)

	dqn	foo	bar
2008-09	0	0	0
2008-10	0	0	0
2008-11	78	59	0
2008-12	49	64	0
2009-01	209	42	0
2009-02	693	510	0
2009-03	119	646	0
2009-04	289	42	0
2009-05	214	64	0
2009-06	149	6	87
2009-07	103	3	35
2009-08	128	57	82
2009-09	302	174	111
2009-10	285	265	265
2009-11	230	39	156
2009-12	337	54	206
2010-01	293	59	199

ソースコード

#!/usr/bin/perl

#  svn log -q  の結果を集計するツール
#  使い方:
#  $ svn log -q .  | perl sum_svnlog.pl

use strict;
use warnings;
use Data::Dumper;

my $commits = parse_log();

my $count_by_author = count_by_author($commits);
my $count_by_month = count_by_month($commits);
my $table_month = get_table_by_month($count_by_month);
my $table_author = get_table_by_author($count_by_author);

my $count_by_month_and_auther = count_by_month_and_auther($commits);

my @authors = sort { $count_by_author->{$b} <=> $count_by_author->{$a}  } keys %$count_by_author;
my $table_month_author = get_table_by_month_and_author($count_by_month_and_auther, \@authors);


print join("\t", @$_)."\n"  for @$table_month_author;

sub get_table_by_month_and_author {
    my $count_by_month_and_auther = shift;
    my $authors = shift;

    my @lines;

    my @header = ('', @$authors);
    push @lines, \@header;

    for my $month  (sort keys %$count_by_month_and_auther) {

        my @items;

        push @items, $month;

        for my $author (@$authors) {
            my $count = ($count_by_month_and_auther->{$month}{$author} || 0);
            push @items, $count;
        }

        push @lines, \@items;
    }

    return \@lines;
}

sub get_table_by_author {
    my $count = shift;

    my @lines;
    for (sort keys %$count) {
        my @items = ($_,  $count->{$_});
        push @lines, \@items;
    }

    return \@lines;
}


sub get_table_by_month {
    my $count_by_months = shift;

    my @lines;
    for (sort keys %$count_by_months) {
        my @items = ($_,  $count_by_months->{$_});
        push @lines, \@items;
    }

    return \@lines;
}

sub count_by_month_and_auther {
    my $commits = shift;
    my %count_by_month_and_auther;

    for (@$commits) {
        $count_by_month_and_auther{$_->{yearmonth}}{$_->{author}}++;
    }

    return \%count_by_month_and_auther;
}


sub count_by_author {
    my $commits = shift;
    my %count_by_months;
    for (@$commits) {
        $count_by_months{$_->{author}}++ ;
    }
    return \%count_by_months;
}


sub count_by_month {
    my $commits = shift;
    my %count_by_months;
    for (@$commits) {
        $count_by_months{$_->{yearmonth}}++ ;
    }
    return \%count_by_months;
}

# return [
#           { rev => 'r1234',
#             author => 'dqn' ,
#             date => '2011-01-01',
#             yearmonth => '2011-01',
#            },
#           ...
#        ]
sub parse_log {

    my @all_lines;

    while(<>) {
        push @all_lines, $_  if /^r/;
    }

    my @commits;

    for (@all_lines) {

        s/\|//g;  # remove '\'
        my ($rev, $author, $date) = split;
        my $yearmonth = substr($date, 0,7);

        $author = lc $author;
        
        push @commits, {
            rev => $rev,
            author => $author,
            date => $date,
            yearmonth => $yearmonth,
        };
    }

    return \@commits;
}
オブジェクト指向じゃなくてすいません。
カテゴリ: