181404Speter#! @PERL@ 281404Speter 3175261Sobrien# Copyright (C) 1995-2005 The Free Software Foundation, Inc. 4175261Sobrien 5175261Sobrien# This program is free software; you can redistribute it and/or modify 6175261Sobrien# it under the terms of the GNU General Public License as published by 7175261Sobrien# the Free Software Foundation; either version 2, or (at your option) 8175261Sobrien# any later version. 9175261Sobrien# 10175261Sobrien# This program is distributed in the hope that it will be useful, 11175261Sobrien# but WITHOUT ANY WARRANTY; without even the implied warranty of 12175261Sobrien# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13175261Sobrien# GNU General Public License for more details. 14175261Sobrien 1581404Speter# Merge conflicted ChangeLogs 1681404Speter# tromey Mon Aug 15 1994 1781404Speter 1881404Speter# Usage is: 1981404Speter# 2081404Speter# cl-merge [-i] file ... 2181404Speter# 2281404Speter# With -i, it works in place (backups put in a ~ file). Otherwise the 2381404Speter# merged ChangeLog is printed to stdout. 2481404Speter 2581404Speter# Please report any bugs to me. I wrote this yesterday, so there are no 2681404Speter# guarantees about its performance. I recommend checking its output 2781404Speter# carefully. If you do send a bug report, please include the failing 2881404Speter# ChangeLog, so I can include it in my test suite. 2981404Speter# 3081404Speter# Tom 3181404Speter# --- 3281404Speter# tromey@busco.lanl.gov Member, League for Programming Freedom 3381404Speter# Sadism and farce are always inexplicably linked. 3481404Speter# -- Alexander Theroux 3581404Speter 3681404Speter 3781404Speter# Month->number mapping. Used for sorting. 3881404Speter%months = ('Jan', 0, 3981404Speter 'Feb', 1, 4081404Speter 'Mar', 2, 4181404Speter 'Apr', 3, 4281404Speter 'May', 4, 4381404Speter 'Jun', 5, 4481404Speter 'Jul', 6, 4581404Speter 'Aug', 7, 4681404Speter 'Sep', 8, 4781404Speter 'Oct', 9, 4881404Speter 'Nov', 10, 4981404Speter 'Dec', 11); 5081404Speter 5181404Speter# If '-i' is given, do it in-place. 5281404Speterif ($ARGV[0] eq '-i') { 5381404Speter shift (@ARGV); 5481404Speter $^I = '~'; 5581404Speter} 5681404Speter 5781404Speter$lastkey = ''; 5881404Speter$lastval = ''; 5981404Speter$conf = 0; 6081404Speter%conflist = (); 6181404Speter 6281404Speter$tjd = 0; 6381404Speter 6481404Speter# Simple state machine. The states: 6581404Speter# 6681404Speter# 0 Not in conflict. Just copy input to output. 6781404Speter# 1 Beginning an entry. Next non-blank line is key. 6881404Speter# 2 In entry. Entry beginner transitions to state 1. 6981404Speterwhile (<>) { 7081404Speter if (/^<<<</ || /^====/) { 7181404Speter # Start of a conflict. 7281404Speter 7381404Speter # Copy last key into array. 7481404Speter if ($lastkey ne '') { 7581404Speter $conflist{$lastkey} = $lastval; 7681404Speter 7781404Speter $lastkey = ''; 7881404Speter $lastval = ''; 7981404Speter } 8081404Speter 8181404Speter $conf = 1; 8281404Speter } elsif (/^>>>>/) { 8381404Speter # End of conflict. Output. 8481404Speter 8581404Speter # Copy last key into array. 8681404Speter if ($lastkey ne '') { 8781404Speter $conflist{$lastkey} = $lastval; 8881404Speter 8981404Speter $lastkey = ''; 9081404Speter $lastval = ''; 9181404Speter } 9281404Speter 9381404Speter foreach (reverse sort clcmp keys %conflist) { 9481404Speter print STDERR "doing $_" if $tjd; 9581404Speter print $_; 9681404Speter print $conflist{$_}; 9781404Speter } 9881404Speter 9981404Speter $lastkey = ''; 10081404Speter $lastval = ''; 10181404Speter $conf = 0; 10281404Speter %conflist = (); 10381404Speter } elsif ($conf == 1) { 10481404Speter # Beginning an entry. Skip empty lines. Error if not a real 10581404Speter # beginner. 10681404Speter if (/^$/) { 10781404Speter # Empty line; just skip at this point. 10881404Speter } elsif (/^[MTWFS]/) { 10981404Speter # Looks like the name of a day; assume opener and move to 11081404Speter # "in entry" state. 11181404Speter $lastkey = $_; 11281404Speter $conf = 2; 11381404Speter print STDERR "found $_" if $tjd; 11481404Speter } else { 11581404Speter die ("conflict crosses entry boundaries: $_"); 11681404Speter } 11781404Speter } elsif ($conf == 2) { 11881404Speter # In entry. Copy into variable until we see beginner line. 11981404Speter if (/^[MTWFS]/) { 12081404Speter # Entry beginner line. 12181404Speter 12281404Speter # Copy last key into array. 12381404Speter if ($lastkey ne '') { 12481404Speter $conflist{$lastkey} = $lastval; 12581404Speter 12681404Speter $lastkey = ''; 12781404Speter $lastval = ''; 12881404Speter } 12981404Speter 13081404Speter $lastkey = $_; 13181404Speter print STDERR "found $_" if $tjd; 13281404Speter $lastval = ''; 13381404Speter } else { 13481404Speter $lastval .= $_; 13581404Speter } 13681404Speter } else { 13781404Speter # Just copy. 13881404Speter print; 13981404Speter } 14081404Speter} 14181404Speter 14281404Speter# Compare ChangeLog time strings like <=>. 14381404Speter# 14481404Speter# 0 1 2 3 14581404Speter# Thu Aug 11 13:22:42 1994 Tom Tromey (tromey@creche.colorado.edu) 14681404Speter# 0123456789012345678901234567890 14781404Speter# 14881404Spetersub clcmp { 14981404Speter # First check year. 15081404Speter $r = substr ($a, 20, 4) <=> substr ($b, 20, 4); 15181404Speter 15281404Speter # Now check month. 15381404Speter $r = $months{substr ($a, 4, 3)} <=> $months{substr ($b, 4, 3)} if !$r; 15481404Speter 15581404Speter # Now check day. 15681404Speter $r = substr ($a, 8, 2) <=> substr ($b, 8, 2) if !$r; 15781404Speter 15881404Speter # Now check time (3 parts). 15981404Speter $r = substr ($a, 11, 2) <=> substr ($b, 11, 2) if !$r; 16081404Speter $r = substr ($a, 14, 2) <=> substr ($b, 14, 2) if !$r; 16181404Speter $r = substr ($a, 17, 2) <=> substr ($b, 17, 2) if !$r; 16281404Speter 16381404Speter $r; 16481404Speter} 165