#!/usr/bin/perl use strict; use warnings; use IO::Handle; our %flag; our (@order, @order_final_maybe); our $verbose=0; our $propsmode=0; our $marker=5; # we don't use Getopt::Long because we want to be quick to start up # and we're not really a very user-facing utility while (@ARGV && $ARGV[0] =~ m/^\-/) { $_ = shift @ARGV; if (s/^-U//) { $flag{$_}{ForceResult} = 1; $flag{$_}{Result} = undef; push @order_final_maybe, $_; } elsif (s/^-D//) { $flag{$_}{ForceResult} = 1; $flag{$_}{Result} = ''; push @order_final_maybe, $_; } elsif (m/^-v$/) { $verbose = 1; } elsif (m/^-P$/) { $propsmode = 1; } elsif (m/^-M(\d+)$/) { $marker = $1; } elsif (m/^--$/) { last; } else { die "$0: bad option\n"; } } @ARGV==3 or die "$0: bad usage\n"; foreach my $ix (qw(0 1 2)) { open F, '<', $ARGV[$ix] or die "$ix $!"; while () { chomp or die; ($propsmode && m/ /) or m/$/; $flag{$`}{Input}[$ix] = $'; #'; push @order, $` unless $flag{$`}{InOrder}++; } F->error and die $!; close F or die $!; } foreach $_ (@order_final_maybe) { push @order, $_ unless $flag{$_}{InOrder}++; } my $current = $ARGV[0]; open O, '>', "$current.tmp" or die "$current.tmp $!"; sub prmark ($) { print O $_[0] x $marker, "\n" or die $!; } sub prval ($) { my $v = @_; print O $v,"\n" or die $! if defined $v; } our $f; if ($verbose) { sub verb ($) { print STDERR "MERGE_LISTS $f @_\n" or die $!; } } else { sub verb { } } our $conflicts = 0; foreach $f (@order) { my $ff = $flag{$f}; verb("BEGIN"); if (defined $ff->{ForceResult}) { verb("FORCE"); } else { my @in = @{ $ff->{Input} }; verb(defined ? "DEF $_": "U") foreach @in; if (iseq($in[0], $in[2])) { verb("SAME"); $ff->{Result} = [0]; } elsif (iseq($in[0], $in[1])) { verb("THEIRS"); $ff->{Result} = $in[2]; } elsif (iseq($in[2], $in[1])) { verb("OURS"); $ff->{Result} = $in[0]; } else { $conflicts++; verb("CONFLICT"); prmark('<'); prval($in[0]); prmark('='); prval($in[2]); prmark('>'); next; } } prval($ff->{Result}); } close O or die $!; rename "$current.tmp", "$current" or die "$current $!"; exit $conficts ? 1 :0;