1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#!/usr/bin/perl -w
#
# Generate a nice changelist by querying perforce.
#
# Each change is described with the change number, description,
# which branch the change happened in, files modified,
# and who was responsible for entering the change.
#
# Can be called with a list of change numbers or a range of the
# form "12..42". Changelog will be printed from highest number
# to lowest.
#
# Outputs the changelist to stdout.
#
# Gurusamy Sarathy <gsar@activestate.com>
#
use Text::Wrap;
$0 =~ s|^.*/||;
unless (@ARGV) {
die <<USAGE;
$0 [-p \$P4PORT] [-bi branch_include] [-be branch_exclude] <change numbers or from..to>
USAGE
}
my @changes;
my %editkind;
@editkind{ qw( add edit delete integrate branch )}
= qw( + ! - !> +> );
my $p4port = $ENV{P4PORT} || 'localhost:1666';
my @branch_include;
my @branch_exclude;
my %branch_include;
my %branch_exclude;
while (@ARGV) {
$_ = shift;
if (/^(\d+)\.\.(\d+)?$/) {
push @changes, $1 .. ($2 || (split(' ', `p4 changes -m 1`))[1]);
}
elsif (/^\d+$/) {
push @changes, $_;
}
elsif (/^-p(.*)$/) {
$p4port = $1 || shift;
}
elsif (/^-bi(.*)$/) {
push @branch_include, $1 || shift;
}
elsif (/^-be(.*)$/) {
push @branch_exclude, $1 || shift;
}
else {
warn "Arguments must be change numbers, ignoring `$_'\n";
}
}
@changes = sort { $b <=> $a } @changes;
@branch_include{@branch_include} = @branch_include if @branch_include;
@branch_exclude{@branch_exclude} = @branch_exclude if @branch_exclude;
my @desc = `p4 -p $p4port describe -s @changes`;
if ($?) {
die "$0: `p4 -p $p4port describe -s @changes` failed, status[$?]\n";
}
else {
chomp @desc;
while (@desc) {
my ($change,$who,$date,$time,@log,$branch,$file,$type,%files);
my $skip = 0;
my $nbranch = 0;
$_ = shift @desc;
if (/^Change (\d+) by (\w+)\@.+ on (\S+) (\S+)\s*$/) {
($change, $who, $date, $time) = ($1,$2,$3,$4);
$_ = shift @desc; # get rid of empty line
while (@desc) {
$_ = shift @desc;
last if /^Affected/;
push @log, $_;
}
if (/^Affected/) {
$_ = shift @desc; # get rid of empty line
while ($_ = shift @desc) {
last unless /^\.\.\./;
if (m{^\.\.\. //depot/(.*?perl|[^/]*)/([^#]+)#\d+ (\w+)\s*$}) {
($branch,$file,$type) = ($1,$2,$3);
$nbranch++;
if (exists $branch_exclude{$branch} or
@branch_include and
not exists $branch_include{$branch}) {
$skip++;
}
$files{$branch} = {} unless exists $files{$branch};
$files{$branch}{$type} = [] unless exists $files{$branch}{$type};
push @{$files{$branch}{$type}}, $file;
}
else {
warn "Unknown line [$_], ignoring\n";
}
}
}
}
next if ((not $change) or $skip);
print "_" x 76, "\n";
printf <<EOT, $change, $who, $date, $time;
[%6s] By: %-25s on %9s %9s
EOT
print " Log: ";
my $i = 0;
while (@log) {
$_ = shift @log;
s/^\s*//;
s/^\[.*\]\s*// unless $i ;
# don't print last empty line
if ($_ or @log) {
print " " if $i++;
print "$_\n";
}
}
for my $branch (sort keys %files) {
printf "%11s: $branch\n", 'Branch';
for my $kind (sort keys %{$files{$branch}}) {
warn("### $kind ###\n"), next unless exists $editkind{$kind};
my $files = $files{$branch}{$kind};
# don't show large branches and integrations
$files = ["($kind " . scalar(@$files) . ' files)']
if (@$files > 25 && ($kind eq 'integrate'
|| $kind eq 'branch'))
|| @$files > 100;
print wrap(sprintf("%12s ", $editkind{$kind}),
sprintf("%12s ", $editkind{$kind}),
"@$files\n");
}
}
}
}
|