Merge branch 'master' into devel
[tools/build.git] / spec_add_patch
1 #!/usr/bin/perl -w
2 # vim:sw=4:et
3 # Author: Dirk Mueller
4
5 ################################################################
6 #
7 # Copyright (c) 1995-2014 SUSE Linux Products GmbH
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License version 2 or 3 as
11 # published by the Free Software Foundation.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program (see the file COPYING); if not, write to the
20 # Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #
23 ################################################################
24
25 use strict;
26
27 sub helpexit {
28     print "$0: <patches...> [file.spec]\n";
29     exit 1;
30 }
31
32 my $specname;
33 my %diffs;
34
35 for my $arg (@ARGV) {
36         if ($arg =~ /\.spec$/) {
37                 helpexit() if $specname;
38                 $specname = $arg;
39                 next;
40         }
41         $diffs{$arg} = 1;
42 }
43
44 sub find_specfile()
45 {
46     opendir(D, ".");
47     my @specs = grep { /\.spec$/ } readdir(D);
48     closedir(D);
49
50     # choose the one with the shortest name (heuristic)
51     $specname = ( sort { length($a) - length($b) } @specs)[0];
52
53 }
54
55 if (!defined($specname) || ! -f $specname) {
56     &find_specfile();
57 }
58
59
60 open(S, '<', $specname) or die;
61
62 my $ifdef_level = 0;
63 my $in_prep = 0;
64 my $in_global = 1;
65 my $last_patch_in_prep_index = 0;
66 my $last_patch_in_global_index = 0;
67 my @c = ();
68 my $index = 0;
69
70 # first read the specfile, parse useful information
71 while(<S>)
72 {
73
74     if(/^\s*%\s*endif/) {
75         $ifdef_level--;
76         $last_patch_in_prep_index = $index if ($in_prep && $ifdef_level == 0);
77     }
78     die if ($ifdef_level < 0);
79     $ifdef_level++ if(/^\s*%\s*if/);
80
81     if ($ifdef_level == 0 && !$in_prep && $in_global
82         && /^\%(?:prep|build|install|package|description|doc)/) {
83         $in_global = 0;
84     }
85
86     if (!$in_prep && /^%prep/i) {
87         $in_prep = 1;
88         die if ($in_global);
89     }
90
91     if ($in_prep
92         && /^%setup\b/) {
93         $last_patch_in_prep_index = $index;
94     }
95
96     if ($in_prep
97         && /^\%(?:build|install|package|description|doc)/) {
98         $in_prep = 0;
99     }
100
101     die if (($in_prep + $in_global) > 1);
102
103     if ($in_global && /^Patch(?:\d+)?:\s+(.+)/) {
104         $last_patch_in_global_index = $index;
105         if ($diffs{$1}) {
106             print "$1 already in, skipped.";
107             delete $diffs{$1};
108         }
109     }
110
111     if ($in_global && $ifdef_level == 0 && /^Source(?:\d+)?:/) {
112         $last_patch_in_global_index = $index;
113     }
114
115     if ($in_prep && $ifdef_level == 0 && /^\%patch/) {
116         $last_patch_in_prep_index = $index;
117     }
118     push(@c, $_);
119     $index++;
120 }
121 close(S);
122
123 die if ($ifdef_level > 0);
124 die if ($in_global || $in_prep);
125 die if ($last_patch_in_prep_index == 0);
126 die if ($last_patch_in_global_index == 0);
127
128 #print "adding Patch: $diffname to line $last_patch_in_global_index\n";
129 #print "adding %patch to line $last_patch_in_prep_index\n";
130
131 # determine patch number
132 my $patchnum = 0;
133 $patchnum = $1+1 if ($c[$last_patch_in_global_index] =~ /Patch(\d+):/);
134 $patchnum = 1 if ($c[$last_patch_in_global_index] =~ /Patch:/);
135
136 for my $diffname (keys %diffs) {
137     # determine strip level
138     my $striplevel = "";
139     open(P, '<', $diffname) or die "$diffname: $!\n";
140     while(<P>) {
141         $striplevel = " -p1" if (m/^--- a/ or m/^--- [^\/]+-\d+\./);
142         last if (/^--- /);
143
144     }
145     close(P);
146
147     print "Adding patch$striplevel $diffname to $specname\n";
148
149
150     splice @c, $last_patch_in_prep_index+1, 0, ("\%patch$patchnum$striplevel\n");
151     splice @c, $last_patch_in_global_index+1, 0,
152     (sprintf "Patch%s:%s%s\n", $patchnum, ' ' x (10-length($patchnum)), $diffname);
153     ++$last_patch_in_global_index;
154     $last_patch_in_prep_index+=2; # actually line number
155     ++$patchnum;
156 }
157
158 open(O, '>', "$specname.new") or die;
159 print O @c;
160 close(O);
161
162 system("diff", "-u", $specname, "$specname.new");
163 rename("$specname.new", $specname);