add script that simplifies adding patches to spec files
authorLudwig Nussel <ludwig.nussel@suse.de>
Fri, 22 Jan 2010 13:44:09 +0000 (14:44 +0100)
committerLudwig Nussel <ludwig.nussel@suse.de>
Fri, 22 Jan 2010 13:44:09 +0000 (14:44 +0100)
Makefile
spec_add_patch [new file with mode: 0755]

index 859ba7b..e2e3967 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -51,6 +51,7 @@ install:
            changelog2spec \
            spec2changelog \
            download \
+           spec_add_patch \
            spectool \
            unrpm \
            $(DESTDIR)$(pkglibdir)
diff --git a/spec_add_patch b/spec_add_patch
new file mode 100755 (executable)
index 0000000..db65032
--- /dev/null
@@ -0,0 +1,133 @@
+#!/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);