force enable DO_CUMULATE
[platform/upstream/build.git] / spec_add_patch
1 #!/usr/bin/perl -w
2 # vim:sw=4:et
3 # Author: Dirk Mueller
4
5 use strict;
6
7 sub helpexit {
8     print "$0: <patches...> [file.spec]\n";
9     exit 1;
10 }
11
12 my $specname;
13 my %diffs;
14
15 for my $arg (@ARGV) {
16         if ($arg =~ /\.spec$/) {
17                 helpexit() if $specname;
18                 $specname = $arg;
19                 next;
20         }
21         $diffs{$arg} = 1;
22 }
23
24 sub find_specfile()
25 {
26     opendir(D, ".");
27     my @specs = grep { /\.spec$/ } readdir(D);
28     closedir(D);
29
30     # choose the one with the shortest name (heuristic)
31     $specname = ( sort { length($a) - length($b) } @specs)[0];
32
33 }
34
35 if (!defined($specname) || ! -f $specname) {
36     &find_specfile();
37 }
38
39
40 open(S, '<', $specname) or die;
41
42 my $ifdef_level = 0;
43 my $in_prep = 0;
44 my $in_global = 1;
45 my $last_patch_in_prep_index = 0;
46 my $last_patch_in_global_index = 0;
47 my @c = ();
48 my $index = 0;
49
50 # first read the specfile, parse useful information
51 while(<S>)
52 {
53
54     if(/^\s*%\s*endif/) {
55         $ifdef_level--;
56         $last_patch_in_prep_index = $index if ($in_prep && $ifdef_level == 0);
57     }
58     die if ($ifdef_level < 0);
59     $ifdef_level++ if(/^\s*%\s*if/);
60
61     if ($ifdef_level == 0 && !$in_prep && $in_global
62         && /^\%(?:prep|build|install|package|description|doc)/) {
63         $in_global = 0;
64     }
65
66     if (!$in_prep && /^%prep/i) {
67         $in_prep = 1;
68         die if ($in_global);
69     }
70
71     if ($in_prep
72         && /^%setup\b/) {
73         $last_patch_in_prep_index = $index;
74     }
75
76     if ($in_prep
77         && /^\%(?:build|install|package|description|doc)/) {
78         $in_prep = 0;
79     }
80
81     die if (($in_prep + $in_global) > 1);
82
83     if ($in_global && /^Patch(?:\d+)?:\s+(.+)/) {
84         $last_patch_in_global_index = $index;
85         if ($diffs{$1}) {
86             print "$1 already in, skipped.";
87             delete $diffs{$1};
88         }
89     }
90
91     if ($in_global && $ifdef_level == 0 && /^Source(?:\d+)?:/) {
92         $last_patch_in_global_index = $index;
93     }
94
95     if ($in_prep && $ifdef_level == 0 && /^\%patch/) {
96         $last_patch_in_prep_index = $index;
97     }
98     push(@c, $_);
99     $index++;
100 }
101 close(S);
102
103 die if ($ifdef_level > 0);
104 die if ($in_global || $in_prep);
105 die if ($last_patch_in_prep_index == 0);
106 die if ($last_patch_in_global_index == 0);
107
108 #print "adding Patch: $diffname to line $last_patch_in_global_index\n";
109 #print "adding %patch to line $last_patch_in_prep_index\n";
110
111 # determine patch number
112 my $patchnum = 0;
113 $patchnum = $1+1 if ($c[$last_patch_in_global_index] =~ /Patch(\d+):/);
114 $patchnum = 1 if ($c[$last_patch_in_global_index] =~ /Patch:/);
115
116 for my $diffname (keys %diffs) {
117     # determine strip level
118     my $striplevel = "";
119     open(P, '<', $diffname) or die "$diffname: $!\n";
120     while(<P>) {
121         $striplevel = " -p1" if (m/^--- a/ or m/^--- [^\/]+-\d+\./);
122         last if (/^--- /);
123
124     }
125     close(P);
126
127     print "Adding patch$striplevel $diffname to $specname\n";
128
129
130     splice @c, $last_patch_in_prep_index+1, 0, ("\%patch$patchnum$striplevel\n");
131     splice @c, $last_patch_in_global_index+1, 0,
132     (sprintf "Patch%s:%s%s\n", $patchnum, ' ' x (10-length($patchnum)), $diffname);
133     ++$last_patch_in_global_index;
134     $last_patch_in_prep_index+=2; # actually line number
135     ++$patchnum;
136 }
137
138 open(O, '>', "$specname.new") or die;
139 print O @c;
140 close(O);
141
142 system("diff", "-u", $specname, "$specname.new");
143 rename("$specname.new", $specname);