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

Last change on this file was 2498, checked in by Bruno Cornec, 4 years ago

Fix pb_version_init call

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