|
Michal Marek |
9bee79 |
#!/usr/bin/env perl
|
|
Michal Marek |
0a417c |
#############################################################################
|
|
Michal Marek |
0a417c |
# Copyright (c) 2008,2009 Novell, Inc.
|
|
Michal Marek |
0a417c |
# All Rights Reserved.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# This program is free software; you can redistribute it and/or
|
|
Michal Marek |
0a417c |
# modify it under the terms of version 2 of the GNU General Public License as
|
|
Michal Marek |
0a417c |
# published by the Free Software Foundation.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# This program is distributed in the hope that it will be useful,
|
|
Michal Marek |
0a417c |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Michal Marek |
0a417c |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Michal Marek |
0a417c |
# GNU General Public License for more details.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# You should have received a copy of the GNU General Public License
|
|
Michal Marek |
0a417c |
# along with this program; if not, contact Novell, Inc.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# To contact Novell about this file by physical or electronic mail,
|
|
Michal Marek |
0a417c |
# you may find current contact information at www.novell.com
|
|
Michal Marek |
0a417c |
#############################################################################
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
9bee79 |
# script to merge changes done to *.changes files
|
|
Michal Marek |
9bee79 |
#
|
|
Michal Marek |
9bee79 |
# To install the script as a git merge driver:
|
|
Michal Marek |
9bee79 |
#
|
|
Michal Marek |
9bee79 |
# git config merge.rpm-changes.name "*.changes merge driver"
|
|
Michal Marek |
9bee79 |
# git config merge.rpm-changes.driver "scripts/rpm-changes-merge.pl %A %O %B"
|
|
Michal Marek |
9bee79 |
# echo '*.changes merge=rpm-changes' >>.git/info/attributes
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
use strict;
|
|
Michal Marek |
9bee79 |
use warnings;
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
BEGIN {
|
|
Michal Marek |
9bee79 |
if ($0 =~ /^(.*)\/[^\/]*/) {
|
|
Michal Marek |
9bee79 |
unshift @INC, "$1/lib";
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
unshift @INC, "./lib";
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
use Time::Zone;
|
|
Michal Marek |
9bee79 |
use Getopt::Std;
|
|
Michal Marek |
9bee79 |
use POSIX qw(mktime);
|
|
Michal Marek |
9bee79 |
use File::Temp qw(tempfile);
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
my $conflicts = 0;
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
sub usage {
|
|
Michal Marek |
9bee79 |
print STDERR
|
|
Michal Marek |
9bee79 |
"Usage:
|
|
Michal Marek |
9bee79 |
Three-way merge:
|
|
Michal Marek |
9bee79 |
$0 [-p] my.changes orig.changes their.changes
|
|
Michal Marek |
9bee79 |
Two-way merge:
|
|
Michal Marek |
9bee79 |
$0 [-p] -2 my.changes their.changes
|
|
Michal Marek |
9bee79 |
Fixup mode:
|
|
Michal Marek |
9bee79 |
$0 [-p] -1 my.changes
|
|
Michal Marek |
9bee79 |
";
|
|
Michal Marek |
9bee79 |
exit 1;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
sub main {
|
|
Michal Marek |
9bee79 |
$ENV{'TZ'} = "UTC";
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
our ($opt_p, $opt_1, $opt_2, $opt_3) = (0, 0, 0, 0);
|
|
Michal Marek |
9bee79 |
my (%O, %A, %B, $out);
|
|
Michal Marek |
9bee79 |
if (!getopts('p123') || $opt_1 + $opt_2 + $opt_3 > 1) {
|
|
Michal Marek |
9bee79 |
usage();
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
if ($opt_1) {
|
|
Michal Marek |
9bee79 |
usage() if @ARGV != 1;
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[0], \%A);
|
|
Michal Marek |
9bee79 |
} elsif ($opt_2) {
|
|
Michal Marek |
9bee79 |
usage() if @ARGV != 2;
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[0], \%A);
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[1], \%B);
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
usage() if @ARGV != 3;
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[0], \%A);
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[1], \%O);
|
|
Michal Marek |
9bee79 |
loadchanges($ARGV[2], \%B);
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
if ($opt_p) {
|
|
Michal Marek |
9bee79 |
$out = \*STDOUT;
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
open($out, '>', $ARGV[0]) or die "$ARGV[0]: $!\n";
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
my %seen;
|
|
Michal Marek |
9bee79 |
for my $key (reverse(sort(keys(%A), keys(%O), keys(%B)))) {
|
|
Michal Marek |
9bee79 |
next if $seen{$key};
|
|
Michal Marek |
9bee79 |
$seen{$key} = 1;
|
|
Michal Marek |
9bee79 |
print $out merge($A{$key}, $O{$key}, $B{$key});
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
exit $conflicts;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
sub merge {
|
|
Michal Marek |
9bee79 |
my ($a, $o, $b) = @_;
|
|
Michal Marek |
9bee79 |
$a = "" unless defined $a;
|
|
Michal Marek |
9bee79 |
$o = "" unless defined $o;
|
|
Michal Marek |
9bee79 |
$b = "" unless defined $b;
|
|
Michal Marek |
9bee79 |
return $a if $a eq $b;
|
|
Michal Marek |
9bee79 |
return $a if $o eq $b;
|
|
Michal Marek |
9bee79 |
return $b if $o eq $a;
|
|
Michal Marek |
9bee79 |
return rcs_merge($a, $o, $b);
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
my $have_rcs_merge = 1;
|
|
Michal Marek |
9bee79 |
sub rcs_merge {
|
|
Michal Marek |
9bee79 |
my @texts = @_;
|
|
Michal Marek |
9bee79 |
my $res;
|
|
Michal Marek |
9bee79 |
if ($have_rcs_merge) {
|
|
Michal Marek |
9bee79 |
my @fh;
|
|
Michal Marek |
9bee79 |
my @fn;
|
|
Michal Marek |
9bee79 |
for my $i (0..2) {
|
|
Michal Marek |
9bee79 |
($fh[$i], $fn[$i]) = tempfile();
|
|
Michal Marek |
9bee79 |
my $fh = $fh[$i];
|
|
Michal Marek |
9bee79 |
print $fh $texts[$i];
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
$res = `merge -p $fn[0] $fn[1] $fn[2]`;
|
|
Michal Marek |
9bee79 |
for my $i (0..2) {
|
|
Michal Marek |
9bee79 |
close($fh[$i]);
|
|
Michal Marek |
9bee79 |
unlink($fn[$i]);
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
if ($? == 0) {
|
|
Michal Marek |
9bee79 |
return $res;
|
|
Michal Marek |
9bee79 |
} elsif ($? >> 8 == 1) {
|
|
Michal Marek |
9bee79 |
$conflicts = 1;
|
|
Michal Marek |
9bee79 |
return $res;
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
print STDERR "merge(1) not found, using DumbMerge(TM) instead.\n";
|
|
Michal Marek |
9bee79 |
print STDERR "Install the rcs package for better merge results.\n";
|
|
Michal Marek |
9bee79 |
$have_rcs_merge = 0;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
return "<<<<<<< $ARGV[0]\n" . $texts[0] . "=======\n" . $texts[2] . ">>>>>>> $ARGV[2]\n";
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
sub loadchanges {
|
|
Michal Marek |
9bee79 |
my ($file, $res) = @_;
|
|
Michal Marek |
9bee79 |
open(my $fh, '<', $file) or die "$file: $!\n";
|
|
Michal Marek |
9bee79 |
my $l;
|
|
Michal Marek |
9bee79 |
my $date = 1<<32;
|
|
Michal Marek |
9bee79 |
my $email = "";
|
|
Michal Marek |
9bee79 |
my $expect_date = 0;
|
|
Michal Marek |
9bee79 |
my $text;
|
|
Michal Marek |
9bee79 |
while ($l = <$fh>) {
|
|
Michal Marek |
9bee79 |
if ($expect_date) {
|
|
Michal Marek |
9bee79 |
(my $dt, $email) = parse_date($l);
|
|
Michal Marek |
9bee79 |
if (defined $dt) {
|
|
Michal Marek |
9bee79 |
$date = $dt;
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
print STDERR "$file:$.: invalid date: $l";
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
$expect_date = 0;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
if ($l =~ /^-{50}-*$/ || eof($fh)) {
|
|
Michal Marek |
9bee79 |
if (eof($fh)) {
|
|
Michal Marek |
9bee79 |
$text .= $l;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
if (defined $text) {
|
|
Michal Marek |
9bee79 |
my $key = sprintf("%010d %s", $date, $email);
|
|
Michal Marek |
9bee79 |
if (defined $res->{$key}) {
|
|
Michal Marek |
9bee79 |
$res->{$key} .= $text;
|
|
Michal Marek |
9bee79 |
} else {
|
|
Michal Marek |
9bee79 |
$res->{$key} = $text
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
undef $text;
|
|
Michal Marek |
9bee79 |
$date--;
|
|
Michal Marek |
9bee79 |
$expect_date = 1;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
$text .= $l;
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
close($fh)
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
my %monthnum = (
|
|
Michal Marek |
9bee79 |
jan => 0,
|
|
Michal Marek |
9bee79 |
feb => 1,
|
|
Michal Marek |
9bee79 |
mar => 2,
|
|
Michal Marek |
9bee79 |
apr => 3,
|
|
Michal Marek |
9bee79 |
may => 4,
|
|
Michal Marek |
9bee79 |
jun => 5,
|
|
Michal Marek |
9bee79 |
jul => 6,
|
|
Michal Marek |
9bee79 |
aug => 7,
|
|
Michal Marek |
9bee79 |
sep => 8,
|
|
Michal Marek |
9bee79 |
oct => 9,
|
|
Michal Marek |
9bee79 |
nov => 10,
|
|
Michal Marek |
9bee79 |
dec => 11,
|
|
Michal Marek |
9bee79 |
);
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
sub parse_date {
|
|
Michal Marek |
9bee79 |
my $l = shift;
|
|
Michal Marek |
9bee79 |
if ($l !~ /^(?:mon|tue|wed|thu|fri|sat|sun) +(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) +(\d+) +(\d\d):(\d\d):(\d\d) +([A-Z]+) +(\d\d\d\d) +- +([^ ]*) *$/i) {
|
|
Michal Marek |
9bee79 |
return (undef, "");
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
my ($b, $d, $H, $M, $S, $Z, $Y, $email) = ($1, $2, $3, $4, $5, $6, $7, $8);
|
|
Michal Marek |
9bee79 |
my $date = mktime($S, $M, $H, $d, $monthnum{lc $b}, $Y - 1900);
|
|
Michal Marek |
9bee79 |
return (undef, "") unless defined $date;
|
|
Michal Marek |
9bee79 |
my $offset = tz_offset($Z);
|
|
Michal Marek |
9bee79 |
return (undef, "") unless defined $offset;
|
|
Michal Marek |
9bee79 |
chomp $email;
|
|
Michal Marek |
9bee79 |
return ($date - $offset, $email);
|
|
Michal Marek |
9bee79 |
}
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
main();
|
|
Michal Marek |
9bee79 |
|
|
Michal Marek |
9bee79 |
# vim: sw=4:et
|