#!/usr/bin/perl use strict; use warnings; # Split "A B >= 1" dependencies string into ("A", "B >= 1") list. sub appendsymbols { my ($array, $line) = @_; my $qualified; my $dependency; for my $token (split(/\s/, $line)) { if ($token =~ /\A[<>]?=\z/) { $qualified = 1; $dependency .= ' ' . $token; next; } if (!$qualified) { if (defined $dependency) { push @$array, $dependency; } $dependency = $token; next; } if ($qualified) { $qualified = 0; $dependency .= ' ' . $token; push @$array, $dependency; $dependency = undef; next; } } if (defined $dependency) { push @$array, $dependency; } } # Return true if the argument is a Perl dependency. Otherwise return false. sub is_perl_dependency { my $dependency = shift; return ($dependency =~ /\Aperl\(/); } my $file = shift @ARGV; if (!defined $file) { die "Missing an argument with an RPM build log!\n" } # Parse build log open(my $log, '<', $file) or die "Could not open `$file': $!\n"; my ($package, %packages); while (!eof($log)) { defined($_ = <$log>) or die "Error while reading from `$file': $!\n"; chomp; if (/\AProcessing files: ([\S]+)-[^-]+-[^-]+$/) { $package = $1; $packages{$package}{requires} = []; $packages{$package}{provides} = []; } elsif ($package && /\AProvides: (.*)\z/) { appendsymbols($packages{$package}{provides}, $1); } elsif ($package && /\ARequires: (.*)\z/) { appendsymbols($packages{$package}{requires}, $1); } } close($log); # Save dependencies into file my $filename = 'gendep.macros'; open (my $gendep, '>', $filename) or die "Could not open `$filename' for writing: $!\n"; for my $package (sort keys %packages) { # Macro name my $macro = 'gendep_' . $package; $macro =~ s/[+-]/_/g; $gendep->print("%global $macro \\\n"); # Macro value for my $dependency (@{$packages{$package}{requires}}) { if (is_perl_dependency($dependency)) { $gendep->print("Requires: $dependency \\\n"); } } for my $dependency (@{$packages{$package}{provides}}) { if (is_perl_dependency($dependency)) { $gendep->print("Provides: $dependency \\\n"); } } # Macro trailer $gendep->print("%{nil}\n"); } close($gendep) or die "Could not close `$filename': $!\n"; __END__ =encoding utf8 =head1 NAME generatedependencies - Distil generated Perl dependencies from a build log =head1 SYNOPSIS B I =head1 DESCRIPTION It opens specified RPM build log I. It locates a protocol about autogenerated dependencies. It stores the reported dependencies into F<./gendep.macros> file. The output file will define macros C>. A macro for each binary package. The macro name will use underscores instead of hyphens or other SPEC language special characters. It will ignore non-Perl dependencies (not C) as they do not come from Perl dependency generator. =head1 EXIT CODE Returns zero, if no error occurred. Otherwise non-zero code is returned. =head1 EXAMPLE The invocation is: $ generatedependencies .build-5.24.0-364.fc25.log The output is: $ grep -A5 perl_Devel_Peek gendep.macros %global gendep_perl_Devel_Peek \ Requires: perl(Exporter) \ Requires: perl(XSLoader) \ Provides: perl(Devel::Peek) = 1.23 \ %nil{} %global gendep_perl_Devel_SelfStubber \ The output can be used in a spec file like: Name: perl Source0: gendep.macros %include %{SOURCE0} %package Devel-Peek %gendep_Devel_Peek %package Devel-SelfStubber %gendep_Devel_SelfStubber =head1 COPYING Copyright (C) 2016 Petr Písař This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =cut