-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathapply-patches
executable file
·213 lines (184 loc) · 5.14 KB
/
apply-patches
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/usr/bin/perl -w
# Fre Feb 2 21:53:16 CET 2007
(my $email='pflanze%gmx,ch')=~ tr/%,/@./;
use strict;
$|++;
$0=~ /(.*?)([^\/]+)\z/s or die "?";
my ($mydir, $myname)=($1,$2);
our $patchdir;
our @patch= qw(patch);
our $configname="$myname-options.pl";
sub usage {
print STDERR map{"$_\n"} @_ if @_;
print "$myname patchesdir
Expects an '$configname' file in the patchesdir returning a hash
with patchnam=>[patch options] data.
Options:
--recurse apply itself to subdirectories contained in patchesdir (default)
--no-recurse do not enter subdirectories of patchesdir
(Christian Jaeger <$email>)
";
exit (@_ ? 1 : 0);
}
my @args;
our $DEBUG=0;
our $verbose; *verbose=*DEBUG;
our $opt_recurse=1;
for (my $i=0; $i<=$#ARGV; $i++) {
local $_=$ARGV[$i];
if (/^--?h(elp)?$/) {
usage
} elsif ($_ eq '--') {
push @args, @ARGV[$i+1..$#ARGV];
last;
} elsif (/^--?d(ebug)?$/) {
$DEBUG=1;
} elsif (/^--?v(erbose)?$/) {
$DEBUG=1;
} elsif (/^--?(no-)?recurse$/) {
$opt_recurse= ! $1;
# } elsif (/^--?X(?:XXX(?:=(.*))?)?$/) {
# if (defined $1) {
# $XXX=$1
# } else {
# $XXX=$ARGV[++$i] or usage "missing argument for '$_' option";
# }
} elsif (/^-./) {
usage("Unknown option '$_'\n");
} else {
push @args, $_
}
}
usage unless @args==1;
use Chj::xpipeline
(#'xreceiverpipeline'
'xreceiverpipeline_with_out_to');
use Chj::xopen 'xopen_read';
sub xsystem_with_stdin_to ($ $ ) {
my ($fh,$cmd)=@_;
my $pid=fork;
defined $pid or die "fork: $!";
if ($pid) {
waitpid ($pid,0);
$?
} else {
open STDIN,"<&",$fh or die "could not redirect '$fh' to stdin: $!";
exec @$cmd or die "could not exec '$$cmd[0]': $!";
}
}
use Chj::singlequote;
#sub fh_or_file_to_fh ($ ) {
# my ($fh_or_file)=@_;
# {
{
package _Fh_or_file; #und JA will man das lokal haben.
use Class::Array -fields=> -publica=>
(
'path',
'fh',
);
sub new {
my $cl=shift;
my ($fh_or_path)=@_;
if (UNIVERSAL::isa($fh_or_path,$cl)) {
$fh_or_path
} else {
my $s= bless[],$cl;
if (ref(\$fh_or_path) eq "SCALAR") {
$$s[Path]= $fh_or_path;
} else {
$$s[Fh]= $fh_or_path;
}
}
}
sub fh {
my $s=shift;
$$s[Fh]||=do {
xopen_read ($$s[Path]); # mir kommt in sinn dass die ja eh pfad speichern.
}
}
end Class::Array;
}
sub Dumpcmd {
my ($Fh,$cmd)=@_;
my $p= $Fh->path;
join (", ",map{Chj::singlequote$_} @$cmd)
. ($p ? " < '$p'" :"");
}
sub Our_die ($ $ $ ){
my ($status,$Fh,$cmd)=@_;
my $p= $Fh->path;
#print "\n";#HACK noch sowas interdis eh dependentielles
die "command exited with status $status: ". #ewig auch da
Dumpcmd ($Fh,$cmd);
}
sub xxsystem_with_stdin_to ( $ $ ){
my ($fh_or_file,$cmd)=@_;
my $Fh= new _Fh_or_file($fh_or_file);
my $status= xsystem_with_stdin_to ($Fh,$cmd);
$status==0 or Our_die ($status,$Fh,$cmd);
}
use Chj::Util::AskYN;
sub Filename ($ ) {
my ($path)=@_;
$path=~ s|.*/||s;
$path
}
use Chj::Util::Interprocess 'In_subprocess';
sub run_on_dir {
my ($patchesdir)=@_;
local our @allitems= glob "$patchesdir/*";
local our @files= grep { -f $_ } @allitems;
local our @dirs= grep { -d $_ } @allitems;
my $errors=0;
#(run_on_dir($_) for @dirs) if $opt_recurse;
if ($opt_recurse) {
#(run_on_dir($_) for @dirs)
$errors+= run_on_dir($_) for @dirs;
#UNGLAUBLICH
}
# keep parent clean so that we don't run into problems of multiple config loading
$errors+= In_subprocess sub {
local our $config= require "$patchesdir/$configname";
my $errors=0;
for my $file (sort @files) {
next if $file=~ /~\z/;
my $itemname=Filename ($file);
next if $itemname eq $configname;
if (my $additionalargs= $config->{$itemname}) {
print "* applying patch '$itemname':\n";
#my $p= $item;#xopen_read ($item); #FUN, forgetting to change her were saver that made path method exist.
my $p= xopen_read ($file);
my $cmd= [@patch,@$additionalargs];
if ($verbose) {
print " calling: ".Dumpcmd($p,$cmd)."\n";
}
my $status= xsystem_with_stdin_to ($p, $cmd);# mch ich mir mühe oben dann doch so.
if ($status) {
$errors++;
print "\n";
if (!maybe_askyn "($myname) got errors, do you want to continue anyway?") {
exit 1;
}
}
#print "done.\n";
} else {
#warn "ignoring un-mentioned file '$itemname'";
if (not exists $config->{$itemname}) {
print "($myname) ignoring un-mentioned file '$itemname'\n";#eben schon schöner weil langer pfad zuskriptnicht. so passts auf eine zeile.
}
}
}
#print "\n";
$errors
};
$errors
}
our ($patchesdir)=@args; # nicht @_ bitte
my $errors= run_on_dir ($patchesdir);
print "\n";
print "finished".($errors? "":" successfully").".\n";
__END__
ideen / "not done":
- reihenfolge bzgl rekursion und auch überhaupt (in configfiles arrays verwenden wäre das eine, aber eben, rekursion first or not oder wie soll das sein, "kreuz weise noch?")
- was wenn im Falle von den qmail-mime patches, verschiedene sets *aus* den files eines dirs genommen werden sollen? name des option files eben wählbar machen wohl?.