6 use Fedora
::Rebuild
::Package
::StateLock
;
7 use RPM
::VersionCompare
;
8 use Fedora
::Rebuild
::Scheduler
;
13 Usage: comparebuildroots THREADS OLD_TAG NEW_TAG [LIST]
15 Loads list of source package base names from file LIST or standard input,
16 queries koji for latest builds with OLD_TAG and NEW_TAG, compares their
17 versions and reports differences. The query will run in parallel
20 Output format is a package per line. First column is package name, second
21 column is version from OLD_TAG, and third column is version from NEW_TAG.
22 Columns are separated by tabulator. If a package is missing in given tag,
23 empty string is printed.
25 Package name is preceeded by a character signaling difference between tags.
26 A space stands for equaled builds, plus for newer build in NEW_TAG, minus for
27 newer build in OLD_TAG.
29 If an error occures, the script exits immediately with non-zero return code.
33 # Print message to error output
39 # Run command while appending stderr and stdout to log and stdout to refered
40 # output argument. In case of empty command output fill empty string;
41 # Blocks. If workdir is nonempty string, switch into it befere execution
42 # (and opening the log).
43 # Return true if command succeeds.
45 my ($output, @command) = @_;
48 if (!pipe $child, $parent) {
49 log_error
("Could not get connected pipes for command " .
50 Fedora
::Rebuild
::Package
::StateLock
::format_command
(@command) .
57 open(STDOUT
, '>&', fileno $parent) and
62 my $pid = Proc
::SyncExec
::sync_exec
($redirect, @command);
69 log_error
("Could not execute " .
70 Fedora
::Rebuild
::Package
::StateLock
::format_command
(@command) .
75 for ($$output = ''; local $_ = <$child>;) {
79 if ($pid != waitpid($pid, 0) || $?
) {
80 log_error
("Command " .
81 Fedora
::Rebuild
::Package
::StateLock
::format_command
(@command) .
83 Fedora
::Rebuild
::Package
::StateLock
::child_error_as_string
. "\n");
91 # Get latest build in a tag as version-release string.
92 # Return build string in case of succes, empty string if package has not yet
93 # been built, undef in case of errror;
94 sub get_latest_build
{
95 my ($tag, $package) = @_;
97 if (!dooutput
(\
$build, 'koji', 'latest-pkg', '--quiet', $tag, $package)) {
101 if (!defined $build || $build eq '') {
106 if (! ($build =~ /^([\S]+)/)) {
111 # Remove package base name
112 if (! ($build =~ /^.*-([^-]+-[^-]+)$/)) {
120 # Compare version-release string of new and old build.
121 # Returns 0 if equaled, 1 if $new is bigger, -1 if $new od older, undef in
124 my ($new, $old) = @_;
137 return RPM
::VersionCompare
::labelCompare
($new, $old);
140 # Compare a package in the buildroots
141 sub compare_package
{
142 my ($package, $old_tag, $new_tag) = @_;
144 my $old_build = get_latest_build
($old_tag, $package);
145 my $new_build = get_latest_build
($new_tag, $package);
147 if (!defined $old_build || !defined $new_build) {
148 log_error
("Could not retrieve latest builds of `" . $package . "'.\n");
152 my $order = compare
($new_build, $old_build);
153 if (!defined $order) {
154 log_error
("Could not compare `" . $old_build. "' and `" .
155 $new_build . "'.\n");
162 } elsif ($order > 0) {
165 print $diff . "$package\t$old_build\t$new_build\n";
175 my $threads = shift @ARGV;
176 my $old_tag = shift @ARGV;
177 my $new_tag = shift @ARGV;
181 # Load list of packages
189 my $scheduler = Fedora
::Rebuild
::Scheduler
->new(
191 #name => 'Comparing build roots',
197 foreach my $package (@packages) {
198 my $job = $scheduler->schedule(\
&compare_package
, $package,
200 if (! defined $job) { next; }
201 $jobs{$job} = $package;
202 my %finished = $scheduler->finish(++$i < @packages);
204 while (my ($job, $status) = each %finished) {
205 my $package = $jobs{$job};
207 log_error
"Could check `" . $package->name . "' package.\n";
208 log_error
"Waiting for finishing scheduled jobs...\n";
209 $scheduler->finish(1);
210 log_error
"All jobs have finished.\n";
211 croak
"Could check all packages.\n";