#!/usr/bin/env perl # Usage: svn2log [args] # Special options: # -c : clean up output (remove trailing whitespace and # newlines from individual log messages) # -v : verbose (print paths) # -w : warn in case of trailing whitespace or newline # --author arg : select revisions committed by # --color val : colorize the output; = 4 comma-separated colors, # e.g. ',bright_green,cyan,yellow' # 1. log message # 2. date, revision and author # 3. changed paths # 4. "Changed paths:" text # Copyright 2003-2023 Vincent Lefevre . # 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, see . use strict; my ($proc) = '$Id: svn2log 171413 2024-09-01 12:25:23Z vinc17/qaa $' =~ /^.Id: (\S+) \d+ / or die; my $auth = qr/\S*|\(no author\)/; my $date = qr/\d{4}-\d\d-\d\d \d\d:\d\d:\d\d/; my ($author,$cleanup,$verbose,$print,$reset,$warn,@color,@svnarg); sub out ($@) { $print or return; my $color = shift; # Let's set the color at each line for compatibility with "less". foreach (@_) { print $color ne '' ? $color.$_.$reset : $_, "\n"; } } sub getcolors ($) { require Term::ANSIColor; ($reset,@color) = map { /\S/ ? Term::ANSIColor::color $_ : '' } 'reset', split(/,/, $_[0]); } for (my $i = 0; $i <= $#ARGV; $i++) { $ARGV[$i] eq '--author' and $author = $ARGV[++$i], next; $ARGV[$i] eq '--color' and getcolors($ARGV[++$i]), next; $ARGV[$i] eq '-c' and $cleanup = 1, next; $ARGV[$i] eq '-w' and $warn = 7, next; $ARGV[$i] eq '-v' and $verbose = 1; push @svnarg, $ARGV[$i]; } # To run svn with untranslated messages and the current charmap... my $ctype = $ENV{LC_ALL} || $ENV{LC_CTYPE} || $ENV{LANG}; $| = 1; $ENV{TZ} = 'UTC0'; open SVNLOG, '-|', 'env', "LC_CTYPE=$ctype", qw(LC_ALL= LC_MESSAGES=C svn log -rHEAD:1), @svnarg or die "$0: can't exec svn: $!"; my $status = 0; my @msg; while () { if (!defined $status) { my ($r,$u,$d,$l) = /^r(\d+) +\| +($auth) +\| ($date) \+0000 \(.*?\) \| (\d+) lines?$/ or chomp, die "$0: bad log format ($_)"; $u =~ s:.*/emailAddress=::; $print = $author eq '' || $u =~ /\A$author\z/; $u = $u eq '' || $u eq '(no author)' ? '' : ", $u"; out $color[1], "$d (rev $r$u)"; $status = $l; @msg = (); $_ = ; if ($verbose && $_ eq "Changed paths:\n") { my @cp; while (($_ = ) ne "\n") { chomp; push @cp, $_; } if (@cp) { out '', ''; out $color[3], " Changed paths:"; foreach my $c (@cp) { out $color[2], $c } } } else { $_ eq "\n" or die "$0: bad log format"; } out '', ''; } elsif ($status--) { chomp; ($warn & 4) && /\t/ and $warn &= ~4, warn "$proc: tab character\n"; ($warn & 1) && /[\t ]$/ and $warn &= ~1, warn "$proc: trailing whitespace\n"; if ($cleanup) { s/[\t ]*$//; if (/\t/) { require Text::Tabs; $_ = Text::Tabs::expand($_); } } push @msg, $_ eq "" ? "" : " $_"; next if $status; ($warn & 2) && $msg[$#msg] eq "" and $warn &= ~2, warn "$proc: trailing newline\n"; while ($cleanup && @msg && $msg[$#msg] eq "") { pop @msg } if (@msg) { out $color[0], @msg; out '', ''; } } else { /^-+$/ or die "$0: bad log format"; undef $status; } } close SVNLOG or die; defined $status and die "$0: bad log format"; print "\x24Id\x24\n";