blob: 4ae1abb2badeab09c9359c50cd01d454452e9e98 [file] [log] [blame]
#!/usr/bin/perl
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
use strict;
use warnings;
use Getopt::Std;
sub usage() {
print "USAGE: git_merge_log.pl -b local_branch -r remote_branch -m remote_master_branch\n";
print "\tgit_merge_log.pl -b 8.0.x -r apache/8.0.x -m apache/master\n";
exit(1);
}
sub git_status($$) {
my($remote_branch, $local_branch) = @_;
my %status;
my @commits;
my @lines = `git log --no-merges --cherry-mark --right-only $remote_branch...$local_branch --pretty=format:'%m~%an~%cn~%aD~%h~%s'`;
foreach my $line (@lines) {
#print $line;
chomp $line;
my @array = split('~', $line);
$status{$array[4]} = \@array;
push(@commits, $array[4]);
}
return \%status, \@commits;
}
{
my %opts;
getopts("b:r:m:", \%opts);
usage() if (! defined $opts{b} || ! defined $opts{r} || ! defined $opts{m});
my $remote_branch = $opts{r};
my $local_branch = $opts{b};
my $remote_master = $opts{m};
my($status_branch, $commits) = git_status($remote_branch, $local_branch);
my($status_master) = git_status($remote_master, $local_branch);
my $total = scalar(keys %$status_branch);
my $count = 0;
foreach my $hash (keys %$status_branch) {
++$count;
print STDERR "\r[$count / $total] hash: $hash";
# different status and if they are found
my $cherry_mark_master = 0;
my $cherry_mark_branch = 0;
my $cherry_pick_hash_master = 0;
my $cherry_pick_hash_branch = 0;
# set the cherry mark status
$cherry_mark_master = 1 if ($status_master->{$hash}[0] eq '=');
$cherry_mark_branch = 1 if ($status_branch->{$hash}[0] eq '=');
# valdiate to see if the status is = or >
die if ($status_master->{$hash}[0] ne '=' && $status_master->{$hash}[0] ne '>');
die if ($status_branch->{$hash}[0] ne '=' && $status_branch->{$hash}[0] ne '>');
# remove the cherry mark status
shift(@{$status_branch->{$hash}});
# find the cherry pick hash value
my @show = `git show $hash`;
my $hash_in_comment = 0;
my $cherrypick_hash;
foreach my $show_line (@show) {
if ($show_line =~ m|cherry picked from commit (\w+)|) {
$hash_in_comment++;
$cherrypick_hash = $1;
my @out = `git log $remote_master | grep "$cherrypick_hash"`;
$cherry_pick_hash_master = 1 if $? == 0;
@out = `git log $remote_branch | grep "$cherrypick_hash"`;
$cherry_pick_hash_branch = 1 if $? == 0;
}
}
# add cherry pick hash to the commit status
if ($hash_in_comment == 0) {
unshift(@{$status_branch->{$hash}}, 'no hash');
} elsif ($hash_in_comment == 1) {
unshift(@{$status_branch->{$hash}}, $cherrypick_hash);
} elsif ($hash_in_comment > 1) {
unshift(@{$status_branch->{$hash}}, 'multiple hashes');
} else {
die;
}
# put the status of the cherry pick hash on the commit status
if ($cherry_pick_hash_branch == 1) {
unshift(@{$status_branch->{$hash}}, 'found');
} else {
unshift(@{$status_branch->{$hash}}, 'not found');
}
if ($cherry_pick_hash_master == 1) {
unshift(@{$status_branch->{$hash}}, 'found');
} else {
unshift(@{$status_branch->{$hash}}, 'not found');
}
# put the status of the cherry mark on the commit status
if ($cherry_mark_branch == 1) {
unshift(@{$status_branch->{$hash}}, 'found');
} else {
unshift(@{$status_branch->{$hash}}, 'not found');
}
if ($cherry_mark_master == 1) {
unshift(@{$status_branch->{$hash}}, 'found');
} else {
unshift(@{$status_branch->{$hash}}, 'not found');
}
}
print "\n";
print join("\t", ('Cherry Mark Master', 'Cherry Mark Branch', 'Cherry Pick Master', 'Cherry Pick Branch',
'Cherry Pick Hash', 'Author', 'Committer', 'Date', 'Local Hash', 'Commit Comment')), "\n";
foreach my $hash (@$commits) {
print join("\t", @{$status_branch->{$hash}}), "\n";
}
}