--- /dev/null
+#!/usr/bin/perl -w
+# vim:sw=4:et
+# Author: Dirk Mueller
+
+use strict;
+
+my $diffname = $ARGV[0];
+my $specname = $ARGV[1];
+
+if (!defined($diffname) || ! -f $diffname) {
+
+ print "$0: <diffname>\n";
+ exit 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 $already_found_patch = 0;
+my @c = ();
+my $index = 0;
+
+# first read the specfile, parse useful information
+while(<S>)
+{
+
+ 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+)?:/) {
+ $last_patch_in_global_index = $index;
+ }
+
+ if ($in_global && $ifdef_level == 0 && /^Source(?:\d+)?:/) {
+ $last_patch_in_global_index = $index;
+ }
+
+ if ($in_global && /^Patch.*?:\s+$diffname/) {
+ $already_found_patch = 1;
+ }
+
+ if ($in_prep && $ifdef_level == 0 && /^\%patch/) {
+ $last_patch_in_prep_index = $index;
+ }
+ push(@c, $_);
+ $index++;
+}
+close(S);
+
+exit 0 if ($already_found_patch);
+
+print "Adding patch $diffname to $specname\n";
+
+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:/);
+
+# determine strip level
+my $striplevel = "";
+open(P, "<$diffname") or die;
+while(<P>) {
+ $striplevel = " -p1" if (m/^--- a/ or m/^--- [^\/]+-\d+\./);
+ last if (/^--- /);
+
+}
+close(P);
+
+
+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);
+
+open(O, ">$specname.new") or die;
+print O @c;
+close(O);
+
+system("diff", "-u", $specname, "$specname.new");
+rename("$specname.new", $specname);