source: ProjectBuilder/devel/pb/lib/ProjectBuilder/Filter.pm@ 2254

Last change on this file since 2254 was 2254, checked in by Bruno Cornec, 7 years ago

Automatically modify v0 filter files into v1 format

File size: 9.3 KB
Line 
1#!/usr/bin/perl -w
2#
3# ProjectBuilder Filter module
4# Filtering subroutines brought by the the Project-Builder project
5# which can be easily used by pbinit
6#
7# $Id$
8#
9# Copyright B. Cornec 2007-2016
10# Eric Anderson's changes are (c) Copyright 2012 Hewlett Packard
11# Provided under the GPL v2
12
13package ProjectBuilder::Filter;
14
15use strict 'vars';
16use Data::Dumper;
17use English;
18use File::Basename;
19use File::Copy;
20use lib qw (lib);
21use ProjectBuilder::Version;
22use ProjectBuilder::Base;
23use ProjectBuilder::Conf;
24use ProjectBuilder::Distribution;
25use ProjectBuilder::Changelog;
26use ProjectBuilder::VCS;
27
28# Inherit from the "Exporter" module which handles exporting functions.
29
30use vars qw($VERSION $REVISION @ISA @EXPORT);
31use Exporter;
32
33# Export, by default, all the functions into the namespace of
34# any code which uses this module.
35
36our @ISA = qw(Exporter);
37our @EXPORT = qw(pb_get_filters pb_filter_file_pb pb_filter_file_inplace pb_filter_file pb_filter_var_print);
38($VERSION,$REVISION) = pb_version_init();
39
40=pod
41
42=head1 NAME
43
44ProjectBuilder::Filter, part of the project-builder.org
45
46=head1 DESCRIPTION
47
48This module provides filtering functions suitable for pbinit calls.
49
50=over 4
51
52=item B<pb_get_filters>
53
54This function gets all filters to apply. They're cumulative from the less specific to the most specific.
55
56Suffix of those filters is .yml. Filter all.yml applies to whatever distribution. The pbfilter directory may be global under pbconf or per package, for overloading values. Then in order filters are loaded for distribution type, distribution family, distribution name, distribution name-version.
57
58The first parameter is the package name.
59The second parameter is OS hash
60
61The function returns a pointer on a hash of filters.
62
63=cut
64
65sub pb_get_filters {
66
67my @ffiles;
68my @ffilestoconvert;
69my $pbpkg = shift || die "No package specified";
70my $pbos = shift;
71my $ptr = undef; # returned value pointer on the hash of filters
72my $h;
73
74pb_log(2,"Entering pb_get_filters - pbpkg: $pbpkg - pbos: ".Dumper($pbos)."\n");
75
76# Global filter files first, then package specific
77my @file_basenames = ('all');
78@file_basenames = reverse pb_distro_to_keylist($pbos, 'all') if (defined $pbos);
79# Build list of all filter files
80foreach my $dir ("$ENV{PBROOTDIR}/pbfilter", "$ENV{PBROOTDIR}/$pbpkg/pbfilter") {
81 foreach my $file_basename (@file_basenames) {
82 my $path = "$dir/${file_basename}.yml";
83 if (-f $path) {
84 push(@ffiles, $path);
85 } else {
86 my $path2 = "$dir/${file_basename}.pbf";
87 push(@ffilestoconvert, $path2) if (-f $path2);
88 }
89 }
90}
91
92# Convert all old filter files into new ones
93if (@ffilestoconvert) {
94 foreach my $f (@ffilestoconvert) {
95 my $fyml = $f;
96 $fyml =~ s/\.pbf/.yml/;
97 pb_update_conf_v0($f,$fyml);
98 my ($pburl) = pb_conf_get("pburl");
99 my ($scheme, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
100 pb_vcs_add_if_not_in($scheme,$fyml);
101 push(@ffiles, $fyml);
102 }
103
104if (@ffiles) {
105 pb_log(2,"DEBUG ffiles: ".Dumper(\@ffiles)."\n");
106
107 foreach my $f (@ffiles) {
108 pb_log(3,"DEBUG processing filter file $f\n");
109 $h = pb_conf_cache($f,$h);
110 }
111 $ptr = $h->{"filter"};
112
113 # TODO: find a place to document it. Why not in this file as pod and also documenting filters ?
114 # Handle transform
115 if (defined $h->{transform}) {
116 while (my ($out_key,$spec) = each %{$h->{transform}}) {
117 die "Unknown transform for $out_key '$spec' expected <out-key> <transform>" unless $spec =~ /^([\w\-]+)\s+(.+)$/;
118 my ($in_key, $expr) = ($1, $2);
119 local $_ = $ptr->{$in_key} || '';
120 eval $expr;
121 die "Error evaluating tranform for $out_key ($expr): $@" if $@;
122 $ptr->{$out_key} = $_;
123 pb_log(2, "Transform $in_key to $out_key\n$ptr->{$in_key}\n$ptr->{$out_key}\n");
124 }
125 }
126}
127pb_log(2,"DEBUG f:".Dumper($ptr)."\n") if (defined $ptr);
128return($ptr);
129}
130
131=item B<pb_filter_file>
132
133This function applies all filters to files.
134
135It takes 4 parameters.
136
137The first parameter is the file to filter.
138The second parameter is the pointer on the hash of filters. If undefined no filtering will occur.
139The third parameter is the destination file after filtering.
140The fourth parameter is the pointer on the hash of variables to filter (tag, ver, ...)
141
142=cut
143
144sub pb_filter_file {
145
146my $f=shift;
147my $ptr=shift;
148my %filter;
149if (defined $ptr) {
150 %filter=%$ptr;
151} else {
152 %filter = ();
153}
154my $destfile=shift;
155my $pb=shift;
156my $tuple = "unknown";
157$tuple = "$pb->{'pbos'}->{'name'}-$pb->{'pbos'}->{'version'}-$pb->{'pbos'}->{'arch'}" if (defined $pb->{'pbos'});
158
159pb_log(2,"DEBUG: From $f to $destfile (tuple: $tuple)\n");
160pb_log(3,"DEBUG($tuple): pb ".Dumper($pb)."\n");
161pb_mkdir_p(dirname($destfile)) if (! -d dirname($destfile));
162open(DEST,"> $destfile") || die "Unable to create $destfile: $!";
163open(FILE,"$f") || die "Unable to open $f: $!";
164while (<FILE>) {
165 my $line = $_;
166 foreach my $s (keys %filter) {
167 # Process single variables
168 my $tmp = $filter{$s};
169 next if (not defined $tmp);
170 pb_log(3,"DEBUG filter{$s}: $filter{$s}\n");
171 # Expand variables if any single one found
172 if ($tmp =~ /\$/) {
173 pb_log(3,"*** Filtering variable in $tmp ***\n");
174 # Order is important as we need to handle hashes refs before simple vars
175 # (?: introduce a Non-capturing groupings cf man perlretut
176 # We need to avoid handling other VARs (Makefile e.g) so restrict here to $pb type of vars.
177 eval { $tmp =~ s/(\$\w+(?:-\>\{\'\w+\'\})*)/$1/eeg };
178 if (($s =~ /^PBDESC$/) && ($line =~ /^ PBDESC/)) {
179 # if on debian, we need to preserve the space before each desc line
180 pb_log(3,"*** DEBIAN CASE ADDING SPACE ***\n");
181 $tmp =~ s/\$\//\$\/ /g;
182 pb_log(3,"*** tmp:$tmp ***\n");
183 }
184 # Support $/ vars
185 eval { $tmp =~ s/(\$\/)/$1/eeg };
186 } elsif (($s =~ /^PBLOG$/) && ($line =~ /^PBLOG$/)) {
187 # special case for ChangeLog only for pb
188 pb_log(3,"DEBUG filtering PBLOG\n");
189 pb_changelog($pb, \*DEST, $tmp);
190 $tmp = "";
191 } elsif (($s =~ /^PBPATCHSRC$/) && ($line =~ /^PBPATCHSRC$/)) {
192 pb_log(3,"DEBUG($tuple) filtering PBPATCHSRC\n");
193 my $i = 0;
194 pb_log(3,"DEBUG($tuple): pb ".Dumper($pb)."\n");
195 pb_log(3,"DEBUG($tuple): pb/patches/tuple $pb->{'patches'}->{$tuple}\n");
196 if (defined $pb->{'patches'}->{$tuple}) {
197 foreach my $p (split(/,/,$pb->{'patches'}->{$tuple})) {
198 pb_log(3,"DEBUG($tuple) Adding patch $i ".basename($p)."\n");
199 print DEST "Patch$i: ".basename($p).".gz\n";
200 $i++;
201 }
202 }
203 $tmp = "";
204 } elsif (($s =~ /^PBMULTISRC$/) && ($line =~ /^PBMULTISRC$/)) {
205 pb_log(3,"DEBUG($tuple) filtering PBMULTISRC\n");
206 my $i = 1;
207 if (defined $pb->{'sources'}->{$tuple}) {
208 foreach my $p (split(/,/,$pb->{'sources'}->{$tuple})) {
209 pb_log(3,"DEBUG($tuple) Adding source $i ".basename($p)."\n");
210 print DEST "Source$i: ".basename($p)."\n";
211 $i++;
212 }
213 }
214 $tmp = "";
215 } elsif (($s =~ /^PBPATCHCMD$/) && ($line =~ /^PBPATCHCMD$/)) {
216 pb_log(3,"DEBUG($tuple) filtering PBPATCHCMD\n");
217 my $i = 0;
218 if (defined $pb->{'patches'}->{$tuple}) {
219 my ($patchcmd,$patchopt) = pb_distro_get_param($pb->{'pbos'},pb_conf_get_if("ospatchcmd","ospatchopt"));
220 foreach my $p (split(/,/,$pb->{'patches'}->{$tuple})) {
221 pb_log(3,"DEBUG($tuple) Adding patch command $i ($patchopt)\n");
222 print DEST "%patch$i $patchopt\n";
223 $i++;
224 }
225 }
226 print DEST "\n";
227 $tmp = "";
228 }
229 $line =~ s|$s|$tmp|g;
230 }
231 print DEST $line;
232}
233close(FILE);
234close(DEST);
235}
236
237=item B<pb_filter_file_inplace>
238
239This function applies all filters to a file in place.
240
241It takes 3 parameters.
242
243The first parameter is the pointer on the hash of filters.
244The second parameter is the destination file after filtering.
245The third parameter is the pointer on the hash of variables to filter (tag, ver, ...)
246
247=cut
248
249# Function which applies filter on files (external call)
250sub pb_filter_file_inplace {
251
252my $ptr=shift;
253my $destfile=shift;
254my $pb=shift;
255
256my $cp = "$ENV{'PBTMP'}/".basename($destfile).".$$";
257copy($destfile,$cp) || die "Unable to copy $destfile to $cp";
258
259pb_filter_file($cp,$ptr,$destfile,$pb);
260unlink $cp;
261}
262
263
264=item B<pb_filter_var_print>
265
266This function prints every variable expanded in order to help debug stacking issues with conf files. If a VM/VE/RM is given restrict display to this distribution. If parameters are passed, restrict again the display to that package only.
267
268=cut
269
270sub pb_filter_var_print {
271
272my $pbos = shift;
273my @keys = @_;
274my $ptr = undef;
275
276if ($#keys == -1) {
277 pb_log(0,"Full pb variables for project $ENV{'PBPROJ'}\n");
278 pb_log(0,"============================================\n");
279}
280if (defined $ENV{'PBV'}) {
281 pb_log(0,"Distribution $ENV{'PBV'}\n");
282 pb_log(0,"========================\n");
283} else {
284 pb_log(0,"Local Distribution\n");
285 pb_log(0,"==================\n");
286}
287
288foreach my $k (@keys) {
289 $ptr = pb_get_filters($k,$pbos);
290 pb_log(0,"Package $k\n");
291 pb_log(0,"==================\n");
292 foreach my $f (sort keys %$ptr) {
293 pb_log(0,"Filter $f => $ptr->{$f}\n");
294 }
295 pb_log(0,"==================\n");
296}
297}
298
299
300=back
301
302=head1 WEB SITES
303
304The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
305
306=head1 USER MAILING LIST
307
308None exists for the moment.
309
310=head1 AUTHORS
311
312The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
313
314=head1 COPYRIGHT
315
316Project-Builder.org is distributed under the GPL v2.0 license
317described in the file C<COPYING> included with the distribution.
318
319=cut
320
3211;
Note: See TracBrowser for help on using the repository browser.