diff options
author | Florent Villard <warly@mandriva.com> | 2006-01-28 20:47:32 +0000 |
---|---|---|
committer | Florent Villard <warly@mandriva.com> | 2006-01-28 20:47:32 +0000 |
commit | cc813080359c6b96cddf4da4e98ba6a239404ba9 (patch) | |
tree | 92a77129a2758bd06ef23aeb3f35dcd2b644b166 | |
parent | 599f1db48f58544a4d505020e8bd740282e6f3d2 (diff) | |
download | iurt-cc813080359c6b96cddf4da4e98ba6a239404ba9.tar iurt-cc813080359c6b96cddf4da4e98ba6a239404ba9.tar.gz iurt-cc813080359c6b96cddf4da4e98ba6a239404ba9.tar.bz2 iurt-cc813080359c6b96cddf4da4e98ba6a239404ba9.tar.xz iurt-cc813080359c6b96cddf4da4e98ba6a239404ba9.zip |
Major revamping of the iurt code, use mkcd parsecommandline, add more function, make it more generic
-rwxr-xr-x | iurt2 | 773 |
1 files changed, 419 insertions, 354 deletions
@@ -1,9 +1,9 @@ #!/usr/bin/perl # # Copyright (C) 2005 Mandrakesoft -# Copyright (C) 2005 Mandriva +# Copyright (C) 2005,2006 Mandriva # -# Author: Florent Villard <warly@mandraesoft.com> +# Author: Florent Villard <warly@mandriva.com> # # 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 @@ -32,37 +32,94 @@ use URPM; use File::NCopy qw(copy); use MIME::Words qw(encode_mimewords); use Fcntl ':flock'; +use Mkcd::Commandline qw(parseCommandLine usage); + +my $program_name = 'iurt'; +# sessing parameters +my $arg = @ARGV; +my (@params, %run); +$run{todo} = [ ]; +@params = ( + # [ "one letter option", "long name option", "number of args (-X means ´at least X´)", "help text", "function to call", "log info"] + [ "", "$program_name", 0, "[options]", + "$program_name rebuild bot", + sub { $arg or usage($program_name, \@params) }, "" ], + [ "", "cache", 0, "", + "Use the global cache file", + sub { $run{cache} = 1 }, "Activating cache use" ], + [ "c", "chroot", 0, "", + "Check chroot and update it if needed", + sub { $run{chroot} = 1 }, "Activating debug mode" ], + [ "", "config_help", 0, "", + "Explain configuration files keywords", + sub { $run{config_usage} = 1 }, "Activating debug mode" ], + [ "", "debug", 0, "", + "Activate debug mode", + sub { $run{debug} = 1 }, "Activating debug mode" ], + [ "u", "unionfs", 0, "", + "Activate unionfs mode", + sub { $run{unionfs} = 1 }, "Activating unionfs mode" ], + [ "l", "log", 1, "<log file>", + "Log file.", + sub { + $run{log} = pop @_; + open $run{LOG}, ">$run{log}" or die "unable to open $run{log}\n"; + print *{$run{LOG}}, "command line: @ARGV\n" + }, "Log file" ], + [ "m", "media", -1, "", + "Media to rebuild", + sub { ($run{media}) = @_ }, "Adding a media to rebuild" ], + [ "r", "rebuild", -2, "<distro> <architecture> <srpm 1> <srpm 2> ... <srpm n>", + "Rebuild the packages, e.g. $program_name -r cooker x86_64 /home/foo/rpm/SRPMS/foo-2.3-12mdk.src.rpm", + sub { + $run{rebuild} = 1; + $run{distro} = shift @_; + $run{my_arch} = shift @_; + foreach (@_) { + if (m,(.*/)([^/]*.src.rpm)$, && -f $_) { + push @{$run{todo}}, [ $1, $2 ]; + print {$run{LOG}} "iurt: force build for $2 (from $1)\n"; + 0 + } else { + die "FATAL iurt: $_ does not seems to be a SRPM\n" + } + } + }, "Activating rebuild mode" ], + [ "", "upload", [ + ["", "upload", 0, "[options]", + "Upload the rebuild packages", + sub { my ($tmp) = @_; + $tmp->[0] ||= {}; + 1 + }, "Setting upload options"], + [ "m", "markrelease", 0, "", + "Mark SVN directory when uploading the packages", + sub { $run{markrelease} = 1 }, "Adding markrelease repsys option" ], + ], "[options]", + "Upload the rebuild packages", + sub { $run{upload} = 1 }, "Setting the upload flag" ], + [ "w", "warn", 0, "", + "Warn maintainer of the packages about problem in the rebuild", + sub { $run{warn} = @_ }, "Setting warn flag to warn maintainers" ], + [ "d", "dir", -1, "", + "Directory where to find packages to rebuild", + sub { $run{extra_dir} = @_ }, "Adding extra source packages directories" ], +); -# maybe time to switch to mkcd::parse_command_line -my ($debug, $unionfs, $nocheckchroot, $force_build, @todo, $config_usage); -my @argv = grep { - if ($force_build && !/--/) { - if (m,(.*/)([^/]*.src.rpm)$, && -f $_) { - push @todo, [ $1, $2 ]; - print STDERR "iurt: force build for $2 (from $1)\n"; - 0 - } else { - die "FATAL iurt: $_ does not seems to be a SRPM\n" - } - } else { - $force_build = 0; - if (/--debug/) { $debug = 1; 0 } - elsif (/--unionfs/) { $unionfs = 1; 0 } - elsif (/--nocheckchroot/) { $nocheckchroot = 1; 0 } - elsif (/--force_build/) { $force_build = 1; 0 } - elsif (/--help/) { usage(); 0 } - elsif (/--config_help/) { $config_usage = 1; 0 } - elsif (/--./) { usage("$_ is an unknown option") } - else { 1 } - } -} @ARGV; - -my $distro_version = shift @argv; -my $distro_tag = $distro_version; -$distro_tag =~ s,/,-,g; -my $my_arch = shift @argv; -my $media = shift @argv; -my @special_srpm_dir = @argv; +open(my $LOG, ">&$run{LOG}"); +$run{LOG} = $LOG; + +my $todo = parseCommandLine("$program_name", \@ARGV, \@params); +@ARGV and usage("$program_name", \@params, "@ARGV, too many arguments"); +foreach my $t (@$todo) { + print {$run{LOG}} "$program_name: $t->[2]\n"; + &{$t->[0]}(@{$t->[1]}) or print {$run{LOG}} "ERROR: $t->[2]\n"; +} + +# maybe time to switch to $program_name::parse_command_line + +$run{distro_tag} = $run{distro}; +$run{distro_tag} =~ s,/,-,g; my $urpmi_options = "-v --no-verify-rpm --nolock --auto"; my $real_arch = `uname -m`; @@ -76,8 +133,8 @@ my %arch_comp = ( ); my $HOME = $ENV{HOME}; -my $configfile = "$HOME/.iurt.$distro_tag.conf"; -print STDERR "iurt: loading config file $configfile\n"; +my $configfile = "$HOME/.iurt.$run{distro_tag}.conf"; +print {$run{LOG}} "iurt: loading config file $configfile\n"; my $config; if (-f $configfile) { $config = do $configfile or die "FATAL iurt: syntax error in $configfile"; @@ -86,240 +143,114 @@ if (-f $configfile) { } my %config_usage = ( - home => { desc => 'Home dir', default => $HOME }, + admin => { desc => 'Mail of the administrator of packages builds', default => '' }, + all_media => { desc => 'List of known media', default => [ 'main', 'contrib' ] }, + basesystem_media => { desc => 'Where to find basesystem packages', default => "$config->{repository}/$run{distro}/$run{my_arch}/media/main/" }, cache_home => { desc => 'Where to store the cache files', default => "$HOME/.bugs" }, - supported_arch => { desc => 'Table of supported architecture', default => ['i586', 'x86_64'] }, - upload => { desc => 'Where to copy build packages', default => "$HOME/uploads/" }, - local_home => { desc => 'Where to build packages', default => $HOME }, - repository => { desc => 'Prefix of the repositories', default => '/mnt/BIG/dis/' }, - packager => { desc => 'Name of the build bot', default => 'Iurt' }, - install_chroot_binary => { desc => 'Tool used to create initial chroot', default => 'install-chroot-tar.sh' }, distribution => { desc => 'Name of the packages distribution', default => 'Mandriva Linux' }, - vendor => { desc => 'Name of the packages vendor', default => 'Mandriva' }, - basesystem_media => { desc => 'Where to find basesystem packages', default => "$config->{repository}/$distro_version/$my_arch/media/main/" }, - all_media => { desc => 'List of known media', default => [ 'main', 'contrib' ] }, + home => { desc => 'Home dir', default => $HOME }, + install_chroot_binary => { desc => 'Tool used to create initial chroot', default => 'install-chroot-tar.sh' }, + local_home => { desc => 'Where to build packages', default => $HOME }, log_size_limit => { desc => 'Maximum authorized size for a log file', default => '100M' }, log_size_date => { desc => 'Number of days log should be kept', default => '30' }, - no_mail => { desc => 'Hash table with people mail address where we should not send any mails', default => {} }, minimum_package_number => { "Minimum number of packages in a synthesis file to consider it valid", default => 1000 }, + no_mail => { desc => 'Hash table with people mail address where we should not send any mails', default => {} }, + packager => { desc => 'Name of the build bot', default => 'Iurt' }, + repository => { desc => 'Prefix of the repositories', default => '/mnt/BIG/dis/' }, + rsync_to => { desc => 'Server where the result of the builds should be rsynced (name@server:path format)', default => ''}, + sendmail => { desc => 'If the bot will send mail reports regarding build', default => 0 }, + supported_arch => { desc => 'Table of supported architecture', default => ['i586', 'x86_64'] }, + upload => { desc => 'Where to copy build packages', default => "$HOME/uploads/" }, + vendor => { desc => 'Name of the packages vendor', default => 'Mandriva' }, ); -config_usage() if $config_usage; -$my_arch or usage("no architecture given (media $media, my_arch $my_arch, todo @todo)"); -if (!$arch_comp{$real_arch}{$my_arch}) { - die "FATAL iurt: could not compile $my_arch binaries on a $real_arch" +config_usage() if $run{config_usage}; +$run{my_arch} or usage("no architecture given (media $run{media}, run{my_arch} $run{my_arch}, todo @{$run{todo}})"); +if (!$arch_comp{$real_arch}{$run{my_arch}}) { + die "FATAL iurt: could not compile $run{my_arch} binaries on a $real_arch" } foreach my $k (keys %config_usage) { $config->{$k} ||= $config_usage{$k}{default} } -$config->{upload} .= $distro_version; +$config->{upload} .= $run{distro}; $config->{upload} =~ s/community//g; -if ($distro_version ne 'cooker') { - if ($media ne 'main') { - $config->{upload} .= "/$media" +if ($run{distro} ne 'cooker') { + if ($run{media} ne 'main') { + $config->{upload} .= "/$run{media}" } -} elsif ($media eq 'contrib') { +} elsif ($run{media} eq 'contrib') { $config->{upload} =~ s/cooker/contrib/g; } -d $config->{upload} or usage("$config->{upload} does not exist"); -my $pidfile = "$config->{cache_home}/iurt.$distro_tag.$my_arch.pid"; -if (!$debug) { - open my $lock, "$pidfile.lock"; - flock($lock,LOCK_EX); - if (-f $pidfile) { - my (@stat) = stat $pidfile; - open my $test_PID, $pidfile; - my $pid = <$test_PID>; - close $test_PID; - if ($pid && getpgrp $pid != -1) { - my $time = $stat[9]; - if ($time < time - 36000) { - print STDERR "iurt: an other iurt pid $pid is running for a very long time, killing it\n"; - my $i; - while ($i < 5 && getpgrp $pid != -1) { - kill_for_good($pid); - $i++; - sleep 1 - } - } else { - print STDERR "iurt: an other iurt is running for $my_arch, pid $pid, since ",time - $time," seconds\n"; - exit - } - } else { - print STDERR "iurt: a previous iurt for $my_arch seems dead, cleaning.\n"; - unlink $pidfile - } - } - open my $PID, ">$pidfile" or die "FATAL iurt: could not open pidfile $pidfile for writing"; - print $PID $$; - close $PID; +if (!$run{debug} && $run{media} || $run{chroot}) { + $run{pidfile} = "$config->{cache_home}/iurt.$run{distro_tag}.$run{my_arch}.pid"; + check_pid(\%run) +} - flock($lock,LOCK_UN); - close $lock; + +my $debug_tag = '_debug' if $run{debug}; +my $chroot = "$config->{local_home}/chroot$debug_tag"; +my $chroot_tar = "$chroot-$run{distro_tag}.$run{my_arch}.tar.gz"; +if ($run{chroot}) { + check_chroot($chroot, $chroot_tar, \%run) } -my $cachefile = "$config->{cache_home}/iurt.$distro_tag.$my_arch.cache"; -print STDERR "iurt: loading cache file $cachefile\n"; +my $cachefile = "$config->{cache_home}/iurt.$run{distro_tag}.$run{my_arch}.cache"; my $cache; -if (-f $cachefile) { +if (-f $cachefile || $run{cache}) { + print {$run{LOG}} "iurt: loading cache file $cachefile\n"; $cache = do $cachefile } else { $cache = { rpm_srpm => {}, failure => {}, queue => {}, warning => {}, run => 0, needed => {}, no_unionfs => {} } } -my %big; -my %srpm_version; -my @wrong_rpm; -# FIXME need to check if scanning all the architecture is needed (except of noarch unsynchronity this should not be mandatory) -# in that case, @supported_arch may be removed -# -#foreach my $arch (@{$config->{supported_arch}}) { -# -# We could rely on only parsing the synthesis, hoping that they are correct, however this scan is very fast, so. -my $rpms_dir = "$config->{repository}/$distro_version/$my_arch/media/$media/"; -print STDERR "iurt: checking current packages in $rpms_dir\n"; -opendir my $rpmdir, $rpms_dir or die "Could not open $rpms_dir: $!"; -foreach my $rpm (readdir $rpmdir) { - my ($rarch, $srpm) = update_srpm($rpms_dir, $rpm); - $rarch or next; - $big{$rpm} = 1; - $cache->{queue}{$srpm} = 1; - check_version($srpm) -} -closedir $rpmdir; - -my %provides; -my %pack_provide; -foreach my $m (@{$config->{all_media}}) { - my $synthesis_file = "$config->{repository}/$distro_version/$my_arch/media/$m/media_info/synthesis.hdlist.cz"; - if (-f $synthesis_file) { - print STDERR "Parsing $synthesis_file\n"; - if (open my $syn, "zcat $synthesis_file |") { - my @prov; - my $nb; - while (<$syn>) { - if (/^\@provides@(.*)/) { - foreach my $p (split '@', $1) { - $p =~ /([^[]+)(?:\[(.*)\])?/g; - push @prov, $1; - $provides{$1} = $2 || 1 - } - } elsif (/\@info\@([^@]+)@/) { - $nb++; - my ($name) = $1 =~ /(.*)-[^-]+-[^-]+\..*$/; - foreach (@prov) { - $pack_provide{$_} = $name - } - @prov = () - } - } - $nb < $config->{minimum_package_number} and die "FATAL iurt: synthesis files seems corrupted, only $nb packages found." - } else { - die "FATAL iurt: Could not open $synthesis_file\n"; - } - } -} -#} - -my %maint; - --d "$config->{upload}/build/$my_arch" or mkdir "$config->{upload}/build/$my_arch"; -my $clean; -my %rep; -my %done_rpm; -# -# FIXME all the rep but the first one are cleaned -# this may not be usefull anymore -# -my $to_compile; -foreach my $dir ("$config->{repository}/$distro_version/SRPMS/$media/", @special_srpm_dir) { - print STDERR "iurt: checking SRPMS dir $dir\n"; - opendir my $rpmdir, $dir or next; - foreach my $srpm (readdir $rpmdir) { - # this is for the output of the new svn system - if ($srpm =~ /^\@\d+:(.*)/) { - link "$dir/$srpm", "$dir/$1"; - # unlink "$dir/$srpm"; - $srpm = $1 - } - $srpm =~ /(.*)-[^-]+-[^-]+\.src\.rpm$/ or next; - if ($config->{unwanted_packages} && $srpm =~ /$config->{unwanted_packages}/) { next } - my $ok = 1; - if (check_version($srpm)) { - defined $cache->{failure}{$srpm} and next; - if (!$cache->{queue}{$srpm} && check_needed($srpm)) { - my $hdr = rpm2header("$dir/$srpm"); - check_arch($hdr) and next; - my $changelog = $hdr->queryformat("%{CHANGELOGNAME}"); - my ($mail) = $changelog =~ /<(.*@.*)>/; - $maint{$srpm} = $mail; - print "iurt: will try to compile $srpm\n"; - $to_compile++; - push @todo, [ $dir , $srpm ] - } - foreach my $arch (@{$config->{supported_arch}}) { - $ok &&= $cache->{queue}{$srpm} - } - } - if ($clean && ($rep{$srpm} || $ok)) { - print "iurt: cleaning $dir/$srpm\n"; - unlink "$dir/build/$srpm"; - unlink "$dir/$srpm" - } - $rep{$srpm} = 1 - } - $clean = 1; - closedir $rpmdir -} +my (%srpm_version, @wrong_rpm, %provides, %pack_provide, $to_compile, %maint); +$to_compile += check_media(\%run, $cache, $config, \%srpm_version, \@wrong_rpm, \%provides, \%pack_provide, \%maint) if $run{media}; +$to_compile += search_packages(1, $cache, \%run, @{$run{extra_dir}}) if $run{extra}; dump_cache(); -if (!@todo && !$debug) { +if (!@{$run{todo}} && !$run{debug}) { print "iurt: nothing to do\n"; - unlink $pidfile; + unlink $run{pidfile} if $run{pidfile}; exit } print "iurt: will try to compile $to_compile packages\n"; +exit if !$run{rebuild}; + $cache->{run} ||= 1; -my $run = ++$cache->{run}; +$run{run} = ++$cache->{run}; -my $local_spool = "$config->{local_home}/iurt/$distro_tag/$my_arch"; -if (!-d "$config->{local_home}/iurt/$distro_tag/") { - mkdir "$config->{local_home}/iurt/$distro_tag"; +my $local_spool = "$config->{local_home}/iurt/$run{distro_tag}/$run{my_arch}"; +if (!-d "$config->{local_home}/iurt/$run{distro_tag}/") { + mkdir "$config->{local_home}/iurt/$run{distro_tag}"; if (!-d $local_spool) { mkdir $local_spool; mkdir "$local_spool/log" } } -my $debug_tag = '_debug' if $debug; -my $chroot = "$config->{local_home}/chroot$debug_tag"; -my $chroot_tar = "$chroot-$distro_tag.$my_arch.tar.gz"; -my $unionfs_dir; -if (!$nocheckchroot) { - print "iurt: checking basesystem tar\n"; - system(qq{sudo pkill -9 -u root -f "urpmi $urpmi_options --root $chroot"}); - clean_chroot($chroot, 1) or die "FATAL iurt: Could no prepare initial chroot"; - perform_command("sudo $config->{install_chroot_binary} cooker $config->{basesystem_media} $chroot_tar $chroot 501 basesystem tar rpm-build", - mail => $config->{admin}, - error => "[REBUILD] Creating the inital chroot for $distro_tag on $my_arch failed", - hash => 'chroot_inititialization', - timeout => 600, - log => "$local_spool/log/", - debug_mail => $debug, - die => 1); -} dump_rpmmacros("$chroot/home/builder/.rpmmacros") or die "FATAL iurt: could not dump rpm macros"; -if ($unionfs) { +my $unionfs_dir; +if ($run{unionfs}) { $unionfs_dir = "$config->{local_home}/iurt_unionfs$debug_tag"; clean_all_unionfs($unionfs_dir); -d $unionfs_dir or mkdir $unionfs_dir } -my $s = sub { print "iurt: dumping cache...\n"; dump_cache(); exit }; + +my $s = sub { + print "iurt: dumping cache...\n"; + dump_cache(); + $Data::Dumper::Indent = 0; + $Data::Dumper::Terse = 1; + print "Running environment:\n", Data::Dumper->Dump([\%run]), "\n\n"; + print "Configuration:\n",Data::Dumper->Dump([$config]),"\n\n"; + exit +}; $SIG{TERM} = $s; $SIG{INT} = $s; @@ -328,13 +259,13 @@ my $wait_limit; my $done; my $home = $config->{local_home}; my $union_id = 1; -my $unionfs_tmp = $unionfs; -foreach (my $i ; $i < @todo; $i++) { - my ($dir, $srpm) = @{$todo[$i]}; +my $unionfs_tmp = $run{unionfs}; +foreach (my $i ; $i < @{$run{todo}}; $i++) { + my ($dir, $srpm) = @{$run{todo}[$i]}; $done{$srpm} and next; $done{$srpm} = 1; check_version($srpm) or next; - if ($debug) { $debug++ == 2 and exit } + if ($run{debug}) { $run{debug}++ == 2 and exit } $done++; print "iurt: packages $srpm [$done/$to_compile]\n"; # FIXME unfortunately urpmi stalls quite often @@ -344,8 +275,8 @@ foreach (my $i ; $i < @todo; $i++) { die "FATAL iurt: Could not have urpmi working !" } if ($unionfs_tmp) { - my $mount_point = "$unionfs_dir/unionfs.$run.$union_id"; - print STDERR "Cleaning $mount_point\n"; + my $mount_point = "$unionfs_dir/unionfs.$run{run}.$union_id"; + print {$run{LOG}} "Cleaning $mount_point\n"; if (!clean_mnt($mount_point)) { dump_cache(); die "FATAL iurt: could not kill remaining processes acceding $mount_point" @@ -353,110 +284,126 @@ foreach (my $i ; $i < @todo; $i++) { my $tmpfs; # we cannont just rm -rf $tmpfs, this create defunct processes afterwards (and lock particularly hard the urpmi database) - $union_id = clean_unionfs($unionfs_dir, $run, $union_id); - $tmpfs = "$unionfs_dir/tmpfs.$run.$union_id"; - $chroot = "$unionfs_dir/unionfs.$run.$union_id"; + $union_id = clean_unionfs($unionfs_dir, $run{run}, $union_id); + $tmpfs = "$unionfs_dir/tmpfs.$run{run}.$union_id"; + $chroot = "$unionfs_dir/unionfs.$run{run}.$union_id"; mkdir $tmpfs or die "Could not create $tmpfs ($!)"; mkdir $chroot or die "Could not create $chroot ($!)"; if ($cache->{no_unionfs}{$srpm}) { $unionfs_tmp = 0; - clean_chroot($chroot) + clean_chroot($chroot, \%run) } else { # if the previous package has been built without unionfs, chroot need to be cleaned - clean_chroot($chroot) if !$unionfs_tmp; + clean_chroot($chroot, \%run) if !$unionfs_tmp; $unionfs_tmp = 1; system(qq{sudo mount -t tmpfs none $tmpfs}) and die "FATAL iurt: could not mount $tmpfs ($!)"; system(qq{sudo mount -o dirs=$tmpfs=rw:$home/chroot$debug_tag=ro -t unionfs none $chroot}) and die "FATAL iurt: could not mount $tmpfs and $home/chroot with unionfs ($!)"; - system("sudo chroot $chroot mount none -t proc /proc") and die "FATAL iurt: could not mount /proc in the chroot $chroot."; + system("sudo mount -t proc none $chroot/proc") and die "FATAL iurt: could not mount /proc in the chroot $chroot."; } } else { - print STDERR "iurt: installing a new chroot for $srpm in $chroot\n"; - clean_chroot($chroot) + print {$run{LOG}} "iurt: installing a new chroot for $srpm in $chroot\n"; + clean_chroot($chroot, \%run) } my ($srpm_name) = $srpm =~ /(.*)-[^-]+-[^-]+\.src\.rpm$/ or next; - my $maintainer = `rpmmon -s -p $srpm_name`; - my $cc = "$maint{$srpm}";#, maintainers\@mandriva.com"; - chomp $maintainer; - if (!$maintainer || $maintainer eq 'NOT_FOUND') { + my ($maintainer, $cc); + if (!$run{warn}) { + $maintainer = `rpmmon -s -p $srpm_name`; + $cc = "$maint{$srpm}";#, maintainers\@mandriva.com"; + chomp $maintainer; + if (!$maintainer || $maintainer eq 'NOT_FOUND') { $maintainer = $cc; #$cc = 'maintainers@mandriva.com' + } } #($maintainer, $cc) = ($config->{admin},''); # recreate a new srpm for buildarch condition in the spec file print "Copying $srpm to $chroot\n"; perform_command("sudo cp $dir/$srpm $chroot/home/builder/rpm/SRPMS/", + \%run, $config, mail => $config->{admin}, error => "[REBUILD] cannot copy $srpm to $chroot", - debug_mail => $debug, + debug_mail => $run{debug}, hash => "copy_$srpm") or next; perform_command(qq{sudo chroot $chroot su builder -c "rpm -i /home/builder/rpm/SRPMS/$srpm"}, + \%run, $config, mail => $config->{admin}, error => "[REBUILD] cannot install $srpm in $chroot", - debug_mail => $debug, + debug_mail => $run{debug}, hash => "install_$srpm") or next; perform_command(qq{sudo chroot $chroot su builder -c "rpm --nodeps -bs /home/builder/rpm/SPECS/*.spec"}, + \%run, $config, mail => $config->{admin}, error => "[REBUILD] cannot create $srpm in $chroot", - debug_mail => $debug, + debug_mail => $run{debug}, hash => "create_$srpm") or next; print "Installing build dependencies of $srpm...\n"; - #system(qq{sudo pkill -9 -u root -f "$todo[$i-1][1]"}) if $i - 1 >= 0; - #system(qq{sudo pkill -9 -u root -f "urpmi $urpmi_options --root $chroot"}); perform_command("sudo urpmi $urpmi_options --root $chroot $chroot/home/builder/rpm/SRPMS/$srpm", + \%run, $config, mail => $maintainer, - error => "[REBUILD] install of build dependencies of $srpm failed on $my_arch", + error => "[REBUILD] install of build dependencies of $srpm failed on $run{my_arch}", hash => "install_deps_$srpm", timeout => 600, freq => 1, cc => $cc, - debug_mail => $debug, + debug_mail => $run{debug}, error_regexp => 'cannot be installed', wait_regexp => 'database locked', wait_callback => sub { $wait_limit++; if ($wait_limit > 10) { $wait_limit = 0; system(qq{sudo pkill -9 urpmi}) } }, log => "$local_spool/log/", callback => sub { my ($opt, $output) = @_; - print "calling callback for $opt->{hash}\n" if $debug; - my ($missing_deps, $version) = $output =~ /\(due to unsatisfied ([^[)]*)(?:\[(.*)\])?/; - $missing_deps or return; - my $p = $pack_provide{$missing_deps} || $missing_deps; - my $other_maint = `rpmmon -p $p`; - $version ||= 0; - chomp $other_maint; - print "missing dep: $missing_deps ($other_maint)\n"; - if ($other_maint && $other_maint ne 'NOT_FOUND') { - $opt->{mail} = $other_maint; - $opt->{error} = "[missing] $missing_deps, needed to build $srpm, is not available on $my_arch"; + print {$run{LOG}} "calling callback for $opt->{hash}\n" if $run{debug}; + my @missing_deps = $output =~ /\(due to unsatisfied ([^[ ]*)(?: (.*)| \[(.*)\])?\)/g; + @missing_deps or return; + while (my $missing_deps = shift @missing_deps) { + my $version = shift @missing_deps; + my $version2 = shift @missing_deps; + $version ||= $version2 || 0; + my $p = $pack_provide{$missing_deps} || $missing_deps; + my $other_maint = `rpmmon -p $p`; + chomp $other_maint; + print {$run{LOG}} "missing dep: $missing_deps ($other_maint)\n"; + if ($other_maint && $other_maint ne 'NOT_FOUND') { + $opt->{mail} = $other_maint; + $opt->{error} = "[missing] $missing_deps, needed to build $srpm, is not available on $run{my_arch}"; + } + # remember what is needed, and do not try to recompile until it is available + push @{$cache->{needed}{$srpm}}, [ $missing_deps, $version, $other_maint || $maintainer ]; } - # remember what is needed, and do not try to recompile until it is available - push @{$cache->{needed}{$srpm}}, [ $missing_deps, $version, $other_maint || $maintainer ]; }, ) or next; + # try to workarround the rpm -qa db4 error(2) from dbcursor->c_get: No such file or directory + # running rpm -qa several time seems to fix the problem + foreach (1 .. 3) { + system("sudo chroot $chroot rpm -qa") + } perform_command("sudo chroot $chroot rpm -qa", + \%run, $config, hash => "rpm_qa_$srpm", timeout => 60, - debug_mail => $debug, - log => "$local_spool/log/") or next; + debug_mail => $run{debug}, + log => "$local_spool/log/"); # or next; As this failed quite often, do not stop print "Compiling $srpm\n"; if (!perform_command(qq{TMP=/home/builder/tmp/ sudo chroot $chroot /bin/su builder -c "rpm --rebuild /home/builder/rpm/SRPMS/$srpm"}, + \%run, $config, mail => $maintainer, - error => "[REBUILD] $srpm from $distro_tag does not build correctly on $my_arch", + error => "[REBUILD] $srpm from $run{distro_tag} does not build correctly on $run{my_arch}", hash => "build_$srpm", timeout => 18000, - debug_mail => $debug, + debug_mail => $run{debug}, cc => $cc, log => "$local_spool/log/", error_regexp => 'rror.*ailed|Bad exit status|RPM build error', callback => sub { my ($opt, $output) = @_; - print STDERR "iurt: calling callback for $opt->{hash}\n" if $debug; + print {$run{LOG}} "iurt: calling callback for $opt->{hash}\n" if $run{debug}; if ($unionfs_tmp && $output =~ /no space left on device/i) { - print STDERR "ERROR iurt: running out of space to compile $srpm in unionfs mode, will recompile it in normal mode\n"; + print {$run{LOG}} "ERROR iurt: running out of space to compile $srpm in unionfs mode, will recompile it in normal mode\n"; $cache->{no_unionfs}{$srpm} = 1 } elsif ($unionfs_tmp && $output =~ m,$home,) { - print STDERR "ERROR iurt: seems like building $srpm needs to acces /proc/self/exe, which is broken with unionfs, will recompile it in normal mode\n"; + print {$run{LOG}} "ERROR iurt: seems like building $srpm needs to access /proc/self/exe, which is broken with unionfs, will try to recompile it in non unionfs mode\n"; $cache->{no_unionfs}{$srpm} = 1 } }, @@ -469,9 +416,9 @@ foreach (my $i ; $i < @todo; $i++) { # on a new machine with more ram, or if next version compiles just fine with unionfs, we will # loose the unionfs advantage. # - # Maybe the right thing to do would be to first try to increate the tmpfs size (more than 50 % of the + # Maybe the right thing to do would be to first try to increase the tmpfs size (more than 50 % of the # physical RAM), but this will lead to more swap usage, and slower compilation (and lost of the unionfs - # plus). Or to keep the faulty package an unionfs exception for some time, to save some more extra builds. + # plus). Or to keep the faulty package a unionfs exception for some time, to save some more extra builds. # if (!$unionfs_tmp) { $cache->{failure}{$srpm} = 1 @@ -483,32 +430,33 @@ foreach (my $i ; $i < @todo; $i++) { # do some cleaning if the compilation is successful delete $cache->{needed}{$srpm} if defined $cache->{needed}{$srpm}; if (!perform_command("sudo urpmi $urpmi_options --root $chroot $chroot/home/builder/rpm/RPMS/*/*.rpm", + \%run, $config, mail => $maintainer, error => "[REBUILD] binaries packages generated from $srpm do not install correctly", hash => "binary_test_$srpm", timeout => 300, - debug_mail => $debug, + debug_mail => $run{debug}, freq => 1, error_regexp => 'unable to access', log => "$local_spool/log/")) { $cache->{failure}{$srpm} = 1; next } - if ($debug) { + if ($run{debug}) { print "iurt: debug mode, skip other packages\n"; exit } else { system("cp $chroot/home/builder/rpm/RPMS/*/*.rpm $local_spool") and print "ERROR: could not copy rpm files from $chroot/home/builder/rpm/RPMS/ to $local_spool ($!)\n"; - process_queue() + process_queue($config, \%run, \@wrong_rpm) } } -print STDERR "iurt: reprocess generated packages queue\n"; -process_queue(); +print {$run{LOG}} "iurt: reprocess generated packages queue\n"; +process_queue($config, \%run, \@wrong_rpm); dump_cache(); -print STDERR "ERROR iurt: RPM with a wrong SRPM name\n" if @wrong_rpm; +print {$run{LOG}} "ERROR iurt: RPM with a wrong SRPM name\n" if @wrong_rpm; if (open my $file, ">$local_spool/log/wrong_srpm_names.log") { foreach (@wrong_rpm) { print $file "$_->[1] -> $_->[0] (", $cache->{rpm_srpm}{$_->[1]},")\n"; @@ -518,51 +466,17 @@ if (open my $file, ">$local_spool/log/wrong_srpm_names.log") { if ($config->{rsync_to}) { # remove some old and very big log files not to saturate the server system(qq{find $local_spool/log/ -name "*.log" \( -size +$config->{log_size_limit} -or -mtime +$config->{log_size_date} \) -exec rm -f {} \;}); - system("rsync --delete -alHPe 'ssh -c arcfour' $local_spool/log/ $config->{rsync_to}/$distro_tag/$my_arch/log/"); + system("rsync --delete -alHPe 'ssh -c arcfour' $local_spool/log/ $config->{rsync_to}/$run{distro_tag}/$run{my_arch}/log/"); } # one last try to clean -print STDERR "iurt: try to clean remaining unionfs\n"; -if ($unionfs) { +print {$run{LOG}} "iurt: try to clean remaining unionfs\n"; +if ($run{unionfs}) { clean_all_unionfs($unionfs_dir) } - -unlink $pidfile; - +unlink $run{pidfile} if $run{pidfile}; exit; -sub usage { - my ($error) = @_; - print " - ERROR iurt: $error" if $error; - print " - - usage: - - iurt [options] <distro version> <arch> <media> - e.g. iurt community/2006.0 x86_64 main - - options: - --config_help: Display configuration file help - - --debug: Compile one package in debug mode (do not send mail, create - chroot_debug directory). This mode can be used on a system - where a iurt is already running. - - --force_build <force_srpm_build_1> <force_srpm_build_2> ... <force_srpm_build_n> - list of extra srpm to build - - --help: Display this help - - --nocheckchroot: start building without the inital check of the chroot. - - --unionfs: Use a tmpfs mounted with the chroot via unionfs as build chroot. - This is much faster but you need some memory. - -"; - exit -} - sub config_usage { print " @@ -572,7 +486,8 @@ sub config_usage { $Data::Dumper::Indent = 0; $Data::Dumper::Terse = 1; foreach my $k (sort keys %config_usage) { - print " $k: $config_usage{$k}{desc} (default: ", Data::Dumper->Dump([$config_usage{$k}{default}]), ", current: ", Data::Dumper->Dump([$config->{$k}]),")\n\n" + print " $k: $config_usage{$k}{desc} + default: ", Data::Dumper->Dump([$config_usage{$k}{default}]), ", current: ", Data::Dumper->Dump([$config->{$k}]),"\n" } print "\n\n"; exit @@ -580,7 +495,7 @@ sub config_usage { sub clean_all_unionfs { my ($unionfs_dir) = @_; - print STDERR "Cleaning old unionfs remaining dir in $unionfs_dir\n"; + print {$run{LOG}} "Cleaning old unionfs remaining dir in $unionfs_dir\n"; opendir my $dir, $unionfs_dir or die "FATAL iurt: could not open $unionfs_dir ($!)"; foreach (readdir $dir) { /unionfs\.(\d+)\.(\d+)/ or next; @@ -590,27 +505,29 @@ sub clean_all_unionfs { } sub clean_chroot { - my ($chroot, $only_clean) = @_; + my ($chroot, $run, $only_clean) = @_; if (-d $chroot) { - system("sudo chroot $chroot umount /proc"); + system("sudo umount $chroot/proc"); perform_command("sudo rm -rf $chroot", + $run, $config, mail => $config->{admin}, error => "[REBUILD] Deleting of old chroot $chroot failed", hash => 'chroot_deletion', - debug_mail => $debug, + debug_mail => $run->{debug}, die => 1); } return 1 if $only_clean; mkdir $chroot; perform_command("pushd $chroot && sudo tar xvf $chroot_tar", + $run, $config, mail => $config->{admin}, error => "[REBUILD] creating the initial chroot $chroot failed", hash => 'chroot_init', - debug_mail => $debug, + debug_mail => $run->{debug}, die => 1); dump_rpmmacros("$chroot/home/builder/.rpmmacros") or return; - system("sudo chroot $chroot mount none -t proc /proc") and return; + system("sudo mount none -t proc $chroot/proc") and return; 1 } @@ -632,7 +549,7 @@ sub clean { system(qq{$kill_cmd "$var"}); sleep 1; chomp $ps; - print STDERR "Trying to removed previous blocked processes for $var ($ps)\n"; + print {$run{LOG}} "Trying to removed previous blocked processes for $var ($ps)\n"; return 0 if $i++ > 10 } 1 @@ -640,7 +557,7 @@ sub clean { sub clean_unionfs { my ($unionfs_dir, $run, $union_id) = @_; - system("sudo chroot $unionfs_dir/unionfs.$run.$union_id/ umount /proc") and print STDERR "ERROR iurt: could not umount /proc in $unionfs_dir/unionfs.$run.$union_id\n"; + system("sudo umount $unionfs_dir/unionfs.$run.$union_id/proc") and print {$run{LOG}} "ERROR iurt: could not umount /proc in $unionfs_dir/unionfs.$run.$union_id\n"; print "Cleaning $unionfs_dir/unionfs.$run.$union_id\n"; my $nok = 1; while ($nok) { @@ -650,16 +567,16 @@ sub clean_unionfs { my $last; while (check_mounted($d, $t)) { system("sudo fuser -k $d"); - print STDERR "iurt: umounting $d\n"; + print {$run{LOG}} "iurt: umounting $d\n"; if (system(qq{sudo umount $d &> /dev/null})) { - print STDERR "WARNING iurt: could not umount $d ($!)\n"; + print {$run{LOG}} "WARNING iurt: could not umount $d ($!)\n"; $union_id++; $last = 1; last } } $last and last; - print STDERR "iurt: removing $d\n"; + print {$run{LOG}} "iurt: removing $d\n"; system(qq{sudo rm -rf $d}); $nok = 0 } @@ -667,7 +584,6 @@ sub clean_unionfs { $union_id } - sub check_mounted { my ($mount_point, $type) = @_; open my $mount, '/proc/mounts' or die 'FATAL iurt: could not open /proc/mounts'; @@ -693,7 +609,7 @@ sub check_needed { $ok = 0; push @n, [ $name, $version ]; my $v ||= $version; - print STDERR "ERROR iurt: $srpm needs $name $v to be compiled.\n"; + print {$run{LOG}} "ERROR iurt: $srpm needs $name $v to be compiled.\n"; # try to recompile it once in a while return 1 if ! $cache->{warning}{"install_deps_$srpm"}{$maint}++ % 72 } @@ -703,28 +619,31 @@ sub check_needed { } sub process_queue { - my $dir = "$config->{local_home}/iurt/$distro_tag/$my_arch"; - opendir my $rpmdir, $dir or next; - foreach my $rpm (readdir $rpmdir) { - my ($rarch, $srpm) = update_srpm($dir, $rpm); - $rarch or next; - # recheck if the package has not been uploaded in the meantime - if (! -f "$rpms_dir/$rpm") { - my $ok = copy "$dir/$rpm", "$config->{upload}/RPMS/"; - # try to keep the opportunity to prevent disk full - if (!$ok){ - print "ERROR process_queue: cannot copy $dir/$rpm to $config->{upload}/RPMS/ ($!)\n"; - next - } - } - unlink "$dir/$rpm"; - $cache->{queue}{$srpm} = 1 + my ($config, $run, $wrong_rpm) = @_; + return if !$run->{upload}; + my $dir = "$config->{local_home}/iurt/$run->{distro_tag}/$run->{my_arch}"; + opendir my $rpmdir, $dir or next; + foreach my $rpm (readdir $rpmdir) { + my ($rarch, $srpm) = update_srpm($dir, $rpm, $wrong_rpm); + $rarch or next; + # recheck if the package has not been uploaded in the meantime + my $rpms_dir = "$config->{repository}/$run->{distro}/$run->{my_arch}/media/$run->{media}/"; + if (! -f "$rpms_dir/$rpm") { + my $ok = copy "$dir/$rpm", "$config->{upload}/RPMS/"; + # try to keep the opportunity to prevent disk full + if (!$ok){ + print "ERROR process_queue: cannot copy $dir/$rpm to $config->{upload}/RPMS/ ($!)\n"; + next + } } - closedir $rpmdir; + unlink "$dir/$rpm"; + $cache->{queue}{$srpm} = 1 + } + closedir $rpmdir; } sub update_srpm { - my ($dir, $rpm) = @_; + my ($dir, $rpm, $wrong_rpm) = @_; my ($arch) = $rpm =~ /([^\.]+)\.rpm$/ or return 0; my $srpm = $cache->{rpm_srpm}{$rpm}; if (!$srpm) { @@ -733,13 +652,16 @@ sub update_srpm { $srpm = $hdr->queryformat("%{SOURCERPM}"); $cache->{rpm_srpm}{$rpm} = $srpm } - $srpm = fix_srpm_name($srpm, $rpm); + $srpm = fix_srpm_name($srpm, $rpm, $wrong_rpm); $arch, $srpm } sub dump_cache { my $filename = $cachefile; - return if $debug; + # Right now there are no mechanism of concurrent access/write to the cache. There is + # on global lock for one iurt session. A finer cache access would allow several iurt running + # but the idea is more to have a global parrallel build than several local ones. + return if $run{debug} || !$run{cache}; open my $file, ">$filename.tmp" or die "FATAL iurt dump_cache: cannot open $filename.tmp"; flock($file,LOCK_EX); seek($file, 0, 2); @@ -771,9 +693,9 @@ sub sendmail { sub check_arch { my ($hdr) = @_; my (@exclusive_arch) = $hdr->queryformat('%{EXCLUSIVEARCH}'); - grep { $_ eq $my_arch || $_ eq '(none)' } @exclusive_arch or return 1; + grep { $_ eq $run{my_arch} || $_ eq '(none)' } @exclusive_arch or return 1; my (@exclude_arch) = $hdr->queryformat('%{EXCLUDEARCH}'); - grep { $_ eq $my_arch } @exclusive_arch and return 1 + grep { $_ eq $run{my_arch} } @exclusive_arch and return 1 } sub check_version { @@ -787,17 +709,17 @@ sub check_version { } sub fix_srpm_name { - my ($srpm, $rpm) = @_; + my ($srpm, $rpm, $wrong_rpm) = @_; my $old_srpm = $srpm; if ($srpm =~ s/^lib64/lib/){ - push @wrong_rpm, [ $old_srpm, $rpm ]; + push @$wrong_rpm, [ $old_srpm, $rpm ]; $cache->{rpm_srpm}{$rpm} = $srpm } $srpm } sub perform_command { - my ($command, %opt) = @_; + my ($command, $run, $config, %opt) = @_; $opt{timeout} ||= 300; $opt{freq} ||= 24; print "Timeout $opt{timeout}\n"; @@ -814,7 +736,7 @@ sub perform_command { print "$command\n"; if ($opt{log}) { #$output = `$command 2>&1 2>&1 | tee $opt{log}/$opt{hash}.$run.log`; - system("$command &> $opt{log}/$opt{hash}.$run.log"); + system("$command &> $opt{log}/$opt{hash}.$run->{run}.log"); } else { $output = `$command 2>&1`; } @@ -826,7 +748,7 @@ sub perform_command { return 0 } else { # Keep the run first on the harddrive so that one can check the command status tailing it - if ($opt{log} && open my $log, "$opt{log}/$opt{hash}.$run.log") { + if ($opt{log} && open my $log, "$opt{log}/$opt{hash}.$run->{run}.log") { local $/; $output = <$log> } @@ -841,8 +763,8 @@ sub perform_command { } if ($opt{wait_regexp} && $output =~ /$opt{wait_regexp}/) { $opt{wait_callback}(\%opt, $output) if ref $opt{wait_callback}; - print STDERR "ERROR iurt: $opt{wait_regexp} !\n"; - sendmail($config->{admin}, '' , "$opt{hash} on $my_arch for $media: could not proceed", "$opt{wait_regexp}\n\n$output", 0, 0, $opt{debug_mail}); + print {$run->{LOG}} "ERROR iurt: $opt{wait_regexp} !\n"; + sendmail($config->{admin}, '' , "$opt{hash} on $run->{my_arch} for $run->{media}: could not proceed", "$opt{wait_regexp}\n\n$output", 0, 0, $opt{debug_mail}); if ($opt{die}) { dump_cache(); die "FATAL iurt: $opt{error}." @@ -858,7 +780,7 @@ sub perform_command { } } $cache->{warning}{$opt{hash}}{$opt{mail}}++; - print STDERR "\n$output\n"; + print {$run->{LOG}} "\n$output\n"; if ($opt{die}) { dump_cache(); die "FATAL iurt: $opt{error}." @@ -882,6 +804,21 @@ sub kill_for_good { } } +sub check_chroot { + my ($chroot, $chroot_tar, $run) = @_; + print "iurt: checking basesystem tar\n"; + system(qq{sudo pkill -9 -u root -f "urpmi $urpmi_options --root $chroot"}); + clean_chroot($chroot, $run, 1) or die "FATAL iurt: Could no prepare initial chroot"; + perform_command("sudo $config->{install_chroot_binary} cooker $config->{basesystem_media} $chroot_tar $chroot 501 basesystem tar rpm-build", + $run, $config, + mail => $config->{admin}, + error => "[REBUILD] Creating the inital chroot for $run->{distro_tag} on $run->{my_arch} failed", + hash => 'chroot_inititialization', + timeout => 600, + debug_mail => $run->{debug}, + die => 1); +} + sub dump_rpmmacros { my ($file) = @_; open my $f, qq{| sudo sh -c "cat > $file"} or return 0; @@ -891,3 +828,131 @@ sub dump_rpmmacros { \%vendor $config->{vendor} \%packager $config->{packager}} } + +sub check_pid { + my ($run) = @_; + my $pidfile = $run->{pidfile}; + open my $lock, "$pidfile.lock"; + flock($lock,LOCK_EX); + if (-f $pidfile) { + my (@stat) = stat $pidfile; + open my $test_PID, $pidfile; + my $pid = <$test_PID>; + close $test_PID; + if ($pid && getpgrp $pid != -1) { + my $time = $stat[9]; + if ($time < time - 36000) { + print {$run->{LOG}} "iurt: an other iurt pid $pid is running for a very long time, killing it\n"; + my $i; + while ($i < 5 && getpgrp $pid != -1) { + kill_for_good($pid); + $i++; + sleep 1 + } + } else { + print {$run->{LOG}} "iurt: an other iurt is running for $run->{my_arch}, pid $pid, since ",time - $time," seconds\n"; + exit + } + } else { + print {$run->{LOG}} "iurt: a previous iurt for $run->{my_arch} seems dead, cleaning.\n"; + unlink $pidfile + } + } + open my $PID, ">$pidfile" or die "FATAL iurt: could not open pidfile $pidfile for writing"; + print $PID $$; + close $PID; + + flock($lock,LOCK_UN); + close $lock; +} + +sub check_media { + my ($run, $cache, $config, $srpm_version, $wrong_rpm, $provides, $pack_provide, $maint) = @_; +# We could rely on only parsing the synthesis, hoping that they are correct, however this scan is very fast, so... + my $rpms_dir = "$config->{repository}/$run->{distro}/$run->{my_arch}/media/$run->{media}/"; + print {$run->{LOG}} "iurt: checking current packages in $rpms_dir\n"; + opendir my $rpmdir, $rpms_dir or die "Could not open $rpms_dir: $!"; + foreach my $rpm (readdir $rpmdir) { + my ($rarch, $srpm) = update_srpm($rpms_dir, $rpm, $wrong_rpm); + $rarch or next; + $cache->{queue}{$srpm} = 1; + check_version($srpm) + } + closedir $rpmdir; + + foreach my $m (@{$config->{all_media}}) { + my $synthesis_file = "$config->{repository}/$run->{distro}/$run->{my_arch}/media/$m/media_info/synthesis.hdlist.cz"; + if (-f $synthesis_file) { + print {$run->{LOG}} "Parsing $synthesis_file\n"; + if (open my $syn, "zcat $synthesis_file |") { + my @prov; + my $nb; + while (<$syn>) { + if (/^\@provides@(.*)/) { + foreach my $p (split '@', $1) { + $p =~ /([^[]+)(?:\[(.*)\])?/g; + push @prov, $1; + $provides->{$1} = $2 || 1 + } + } elsif (/\@info\@([^@]+)@/) { + $nb++; + my ($name) = $1 =~ /(.*)-[^-]+-[^-]+\..*$/; + foreach (@prov) { + $pack_provide->{$_} = $name + } + @prov = () + } + } + $nb < $config->{minimum_package_number} and die "FATAL iurt: synthesis files seems corrupted, only $nb packages found." + } else { + die "FATAL iurt: Could not open $synthesis_file\n"; + } + } + } + search_packages(0, $cache, $run, $maint, "$config->{repository}/$run->{distro}/SRPMS/$run->{media}/") +} + +sub search_packages { + my ($clean, $cache, $run, $maint, @dir) = @_; + my ($to_compile, %rep, %done_rpm); + foreach my $dir (@dir) { + print {$run->{LOG}} "iurt: checking SRPMS dir $dir\n"; + opendir my $rpmdir, $dir or next; + foreach my $srpm (readdir $rpmdir) { + # this is for the output of the new svn system + if ($srpm =~ /^\@\d+:(.*)/) { + link "$dir/$srpm", "$dir/$1"; + # unlink "$dir/$srpm"; + $srpm = $1 + } + $srpm =~ /(.*)-[^-]+-[^-]+\.src\.rpm$/ or next; + if ($config->{unwanted_packages} && $srpm =~ /$config->{unwanted_packages}/) { next } + my $ok = 1; + if (check_version($srpm)) { + defined $cache->{failure}{$srpm} and next; + if (!$cache->{queue}{$srpm} && check_needed($srpm)) { + my $hdr = rpm2header("$dir/$srpm"); + check_arch($hdr) and next; + my $changelog = $hdr->queryformat("%{CHANGELOGNAME}"); + my ($mail) = $changelog =~ /<(.*@.*)>/; + $maint{$srpm} = $mail; + print "iurt: will try to compile $srpm\n"; + $to_compile++; + push @{$run->{todo}}, [ $dir , $srpm ] + } + foreach my $arch (@{$config->{supported_arch}}) { + $ok &&= $cache->{queue}{$srpm} + } + } + if ($clean && ($rep{$srpm} || $ok)) { + print "iurt: cleaning $dir/$srpm\n"; + unlink "$dir/build/$srpm"; + unlink "$dir/$srpm" + } + $rep{$srpm} = 1 + } + closedir $rpmdir + } + $to_compile +} + |