summaryrefslogtreecommitdiff
path: root/Porting/genlog
blob: 610e9762a1432a5622443b9b019408d4afa245e2 (plain)
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
142
143
144
#!/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;
use Text::Tabs;

$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 {
    tr/\r/\n/ foreach @desc;
    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);
	my $output = ("_" x 76) . "\n";
	$output .= sprintf <<EOT, $change, $who, $date, $time;
[%6s] By: %-25s             on %9s %9s
EOT
	$output .= "        Log: ";
	my $i = 0;
	while (@log) {
	    $_ = shift @log;
	    s/^\s*//;
	    s/^\[.*\]\s*// unless $i ;
            # don't print last empty line
	    if ($_ or @log) {
	        $output .= "             " if $i++;
	        $output .= "$_\n";
	    }
	}
	for my $branch (sort keys %files) {
	    $output .= sprintf "%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;
	        $output .= wrap(sprintf("%12s ", $editkind{$kind}),
				sprintf("%12s ", $editkind{$kind}),
				"@$files\n");
            }
	}
	print unexpand($output);
    }
}