#!/usr/bin/perl -w # vim:sw=4:et # Author: Dirk Mueller ################################################################ # # Copyright (c) 1995-2014 SUSE Linux Products GmbH # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or 3 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (see the file COPYING); if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # ################################################################ use strict; sub helpexit { print "$0: [file.spec]\n"; exit 1; } my $specname; my %diffs; for my $arg (@ARGV) { if ($arg =~ /\.spec$/) { helpexit() if $specname; $specname = $arg; next; } $diffs{$arg} = 1; } sub find_specfile() { opendir(D, "."); my @specs = grep { /\.spec$/ } readdir(D); closedir(D); # choose the one with the shortest name (heuristic) $specname = ( sort { length($a) - length($b) } @specs)[0]; } if (!defined($specname) || ! -f $specname) { &find_specfile(); } open(S, '<', $specname) or die; my $ifdef_level = 0; my $in_prep = 0; my $in_global = 1; my $last_patch_in_prep_index = 0; my $last_patch_in_global_index = 0; my @c = (); my $index = 0; # first read the specfile, parse useful information while() { if(/^\s*%\s*endif/) { $ifdef_level--; $last_patch_in_prep_index = $index if ($in_prep && $ifdef_level == 0); } die if ($ifdef_level < 0); $ifdef_level++ if(/^\s*%\s*if/); if ($ifdef_level == 0 && !$in_prep && $in_global && /^\%(?:prep|build|install|package|description|doc)/) { $in_global = 0; } if (!$in_prep && /^%prep/i) { $in_prep = 1; die if ($in_global); } if ($in_prep && /^%setup\b/) { $last_patch_in_prep_index = $index; } if ($in_prep && /^\%(?:build|install|package|description|doc)/) { $in_prep = 0; } die if (($in_prep + $in_global) > 1); if ($in_global && /^Patch(?:\d+)?:\s+(.+)/) { $last_patch_in_global_index = $index; if ($diffs{$1}) { print "$1 already in, skipped."; delete $diffs{$1}; } } if ($in_global && $ifdef_level == 0 && /^Source(?:\d+)?:/) { $last_patch_in_global_index = $index; } if ($in_prep && $ifdef_level == 0 && /^\%patch/) { $last_patch_in_prep_index = $index; } push(@c, $_); $index++; } close(S); die if ($ifdef_level > 0); die if ($in_global || $in_prep); die if ($last_patch_in_prep_index == 0); die if ($last_patch_in_global_index == 0); #print "adding Patch: $diffname to line $last_patch_in_global_index\n"; #print "adding %patch to line $last_patch_in_prep_index\n"; # determine patch number my $patchnum = 0; $patchnum = $1+1 if ($c[$last_patch_in_global_index] =~ /Patch(\d+):/); $patchnum = 1 if ($c[$last_patch_in_global_index] =~ /Patch:/); for my $diffname (keys %diffs) { # determine strip level my $striplevel = ""; open(P, '<', $diffname) or die "$diffname: $!\n"; while(

) { $striplevel = " -p1" if (m/^--- a/ or m/^--- [^\/]+-\d+\./); last if (/^--- /); } close(P); print "Adding patch$striplevel $diffname to $specname\n"; splice @c, $last_patch_in_prep_index+1, 0, ("\%patch$patchnum$striplevel\n"); splice @c, $last_patch_in_global_index+1, 0, (sprintf "Patch%s:%s%s\n", $patchnum, ' ' x (10-length($patchnum)), $diffname); ++$last_patch_in_global_index; $last_patch_in_prep_index+=2; # actually line number ++$patchnum; } open(O, '>', "$specname.new") or die; print O @c; close(O); system("diff", "-u", $specname, "$specname.new"); rename("$specname.new", $specname);