tools/git/git_merge_log.pl (94 lines of code) (raw):

#!/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"; } }