chiark / gitweb /
fix a few bugs in THEORY
[topbloke.git] / topbloke-merge-lists
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use IO::Handle;
6
7 our %flag;
8 our (@order, @order_final_maybe);
9 our $verbose=0;
10 our $propsmode=0;
11 our $marker=5;
12
13 # we don't use Getopt::Long because we want to be quick to start up
14 # and we're not really a very user-facing utility
15
16 while (@ARGV && $ARGV[0] =~ m/^\-/) {
17     $_ = shift @ARGV;
18     if (s/^-U//) {
19         $flag{$_}{ForceResult} = 1;
20         $flag{$_}{Result} = undef;
21         push @order_final_maybe, $_;
22     } elsif (s/^-D//) {
23         $flag{$_}{ForceResult} = 1;
24         $flag{$_}{Result} = '';
25         push @order_final_maybe, $_;
26     } elsif (m/^-v$/) {
27         $verbose = 1;
28     } elsif (m/^-P$/) {
29         $propsmode = 1;
30     } elsif (m/^-M(\d+)$/) {
31         $marker = $1;
32     } elsif (m/^--$/) {
33         last;
34     } else {
35         die "$0: bad option\n";
36     }
37 }
38
39 @ARGV==3 or die "$0: bad usage\n";
40
41 foreach my $ix (qw(0 1 2)) {
42     open F, '<', $ARGV[$ix] or die "$ix $!";
43     while (<F>) {
44         chomp or die;
45         ($propsmode && m/ /) or m/$/;
46         $flag{$`}{Input}[$ix] = $'; #';
47         push @order, $` unless $flag{$`}{InOrder}++;
48     }
49     F->error and die $!;
50     close F or die $!;
51 }
52
53 foreach $_ (@order_final_maybe) {
54     push @order, $_ unless $flag{$_}{InOrder}++;
55 }
56
57 my $current = $ARGV[0];
58
59 open O, '>', "$current.tmp" or die "$current.tmp $!";
60
61 sub prmark ($) { 
62     print O $_[0] x $marker, "\n" or die $!;
63  }
64 sub prval ($) {
65     my $v = @_;
66     print O $v,"\n" or die $! if defined $v;
67 }
68
69 our $f;
70
71 if ($verbose) {
72     sub verb ($) { print STDERR "MERGE_LISTS $f @_\n" or die $!; }
73 } else {
74     sub verb { }
75 }
76
77 our $conflicts = 0;
78
79 foreach $f (@order) {
80     my $ff = $flag{$f};
81     verb("BEGIN");
82     if (defined $ff->{ForceResult}) {
83         verb("FORCE");
84     } else {
85         my @in = @{ $ff->{Input} };
86         verb(defined ? "DEF $_": "U") foreach @in;
87         if (iseq($in[0], $in[2])) {
88             verb("SAME");
89             $ff->{Result} = [0];
90         } elsif (iseq($in[0], $in[1])) {
91             verb("THEIRS");
92             $ff->{Result} = $in[2];
93         } elsif (iseq($in[2], $in[1])) {
94             verb("OURS");
95             $ff->{Result} = $in[0];
96         } else {
97             $conflicts++;
98             verb("CONFLICT");
99             prmark('<');
100             prval($in[0]);
101             prmark('=');
102             prval($in[2]);
103             prmark('>');
104             next;
105         }
106     }
107     prval($ff->{Result});
108 }
109
110 close O or die $!;
111 rename "$current.tmp", "$current" or die "$current $!";
112 exit $conficts ? 1 :0;