#!/usr/bin/env perl # $Id: parseBZbugList,v 1.92 2008/08/11 23:47:01 c4chris Exp $ # This script retrieves CSV formatted bug lists and extracts info on various # aspects of package review tickets. FE-ACCEPT blockers are checked to # determine whether closed tickets have their corresponding package in the # development repo and in the owners, and whether still open ticket could # be closed. FE-NEW and FE-REVIEW blockers are checked to verify they are not # closed. # # To run this script, you will need the following data: # # * the URL of packages available in the Fedora development repo (defaults to # http://mirrors.kernel.org/fedora/core/development/source/SRPMS/) # * access to the package db # * a full CVS checkout of Fedora packages # TODO stuff # - Put reviewers with more than 100 packages reviewed in a Hall of Fame and # do not supply review ticket links for those. # - See why count in "Inactive maintainers with open bug reports" is strange. # - Maybe report a count of FE-DEADREVIEW. # - Track packages that do not build on all supported arches, and check they # have an arch dependent BZ tracking ticket. use strict; use Date::Manip; use Getopt::Long; use open ':utf8'; use open ':std'; use File::Temp qw/ tempfile /; use XMLRPC::Lite; use JSON; my $rpc = new XMLRPC::Lite ( proxy => 'https://bugzilla.redhat.com/xmlrpc.cgi' ); # Not sure of the way to increase the timeout on reading... $rpc->transport->timeout(360); my %opt; my @options = ( "help", "repourl=s", "d=s", "cvs=s", "comps=s", "currel=i", "firstrel=i", "u=s", "bu=s", "p=s" ); $main::repourl = "http://mirrors.kernel.org/fedora"; $main::mailURL = "https://admin.fedoraproject.org/accounts/group/dump"; $main::members = "https://admin.fedoraproject.org/accounts/group/dump/packager"; $main::bzOwn = "https://admin.fedoraproject.org/pkgdb/acls/bugzilla?tg_format=json"; $main::cvsDir = "/export/scratch/extras"; $main::currel = 9; $main::firstrel = 7; $main::username = "c4chris"; $main::BZusername = ""; $main::password = ""; if( ! GetOptions( \%opt, @options ) ) { &usage(); } # Override any default settings with arguments that the user has supplied $main::repourl = $opt{"repourl"} if defined $opt{"repourl"}; $main::cvsDir = $opt{"cvs"} if defined $opt{"cvs"}; $main::compsDir = $opt{"comps"} if defined $opt{"comps"}; $main::currel = $opt{"currel"} if defined $opt{"currel"}; $main::firstrel = $opt{"firstrel"} if defined $opt{"firstrel"}; $main::username = $opt{"u"} if defined $opt{"u"}; $main::BZusername = $opt{"bu"} if defined $opt{"bu"}; $main::password = $opt{"p"} if defined $opt{"p"}; &usage() if defined $opt{'help'}; my $TopCount = 50; my $FE_NEW = 163776; my $FE_REVIEW = 163778; my $FE_ACCEPT = 163779; my $FE_NEEDSPONSOR = 177841; my $FE_LEGAL = 182235; my $FE_GUIDELINES = 197974; my $FE_DEADREVIEW = 201449; my $orphans = 'extras-orphan@fedoraproject.org'; my %NAME2REVIEW; my %BZN; my %BZS; my %BZL; my %BZG; my %BZR; my %BZA; my %BZB; my %FEDORA_D; my @FEDORA_R; my @DROPPED_SRPMS; my @COMPS; my @COMPS_M; my $BZOWN; my %OWN_CVS_RECENT; my %MEMBER; my %MEMBER_u; my %CVS_NO_OWNER; my %PKG_LIST; my %BUG_LIST; my %MAINT_LIST; my %OWNER_LIST; my %COUNT_LIST; my %OWNER_STAT; my %BZOWN_BUGS; my %BZOWN_CNT; my %BZREV_BUGS; my %BZREV_CNT; my %INFRASTRUCTURE = ( "buildsystem" => 1, "comps" => 1, "general" => 1, "kadischi" => 1, "mugshot" => 1 ); my %NOTINFEDORA = ( "epel-release" => 1, "GConf2-dbus" => 1, "hulahop" => 1, "olpc-hardware-manager" => 1, "olpc-logos" => 1, "olpc-utils" => 1, "pyxapian" => 1, "sugar" => 1, "sugar-artwork" => 1, "sugar-base" => 1, "sugar-datastore" => 1, "sugar-presence-service" => 1, "xulrunner" => 1 ); # Blacklist a few packages for historical reasons my %DISCARD = ( "alsa-firmware" => 1, "dd_rescue" => 1, "libgsf113" => 1, "php-pecl-sqlite" => 1, "wxPythonGTK2" => 1 ); # Blacklist some packages for comps my %COMPSBLACKLIST = ( "autodownloader" => 1, "theora-exp" => 1, "freetype1" => 1, "paragui" => 1 ); if ($main::mailURL ne "" && $main::password ne "") { local *IN; open IN, "wget -nv -O - \"$main::mailURL?user_name=$main::username&password=$main::password&login=Login\"|" or die "Failed to wget members list : $!"; while ( ) { s/\s+$//; my @F = split /,/; $MEMBER_u{$F[0]} = \@F; } close IN; } if ($main::members ne "" && $main::password ne "") { local *IN; open IN, "wget -nv -O - \"$main::members?user_name=$main::username&password=$main::password&login=Login\"|" or die "Failed to wget members list : $!"; while ( ) { s/\s+$//; my @F = split /,/; $MEMBER{lc $F[1]} = \@F; } close IN; } if (defined $main::bzOwn) { my $obj = jsonToObj(`wget -nv -O - \"$main::bzOwn\"`); $BZOWN = $obj->{'bugzillaAcls'}->{'Fedora'}; } # Grab all Package Review tickets for my $flag ('+', '-', '?', ' ') { my $bA = &runQuery($rpc, $flag); foreach my $bug (@$bA) { # Special case scop $bug->{'assigned_to'} = 'ville.skytta@iki.fi' if $bug->{'assigned_to'} eq 'scop@fedoraproject.org'; $bug->{'reporter'} = 'ville.skytta@iki.fi' if $bug->{'reporter'} eq 'scop@fedoraproject.org'; warn "assigned_to should be an email address: " . $bug->{'assigned_to'} if index($bug->{'assigned_to'}, "@") < 0; warn "reporter should be an email address: " . $bug->{'reporter'} if index($bug->{'reporter'}, "@") < 0; next if $bug->{'short_desc'} =~ /^tracker/i; # Try to guess package name my $name = $bug->{'short_desc'}; next unless $name =~ /(review\s+request|merge\s+review)/i; $name =~ s/^.*review\s+request:?\s+]?\s.*$//g; $name =~ s/:.*$//g; next if $name =~ /TESTING-BUGSPAM/; $bug->{'pkg_name'} = $name; $bug->{'opendate'} = ParseDate($bug->{'opendate'}); $bug->{'changeddate'} = ParseDate($bug->{'changeddate'}); $bug->{'blockedby'} =~ s/[{}]//g; my @B = split /,/, $bug->{'blockedby'}; my $block = 0; my $sponsor = 0; my $legal = 0; my $gl = 0; my $bzb; foreach my $b (@B) { if ($b == $FE_NEW) { $block += 1; $bzb = \%BZN; } if ($b == $FE_REVIEW) { $block += 1; $bzb = \%BZR; } if ($b == $FE_ACCEPT) { $block += 1; $bzb = \%BZA; } if ($b == $FE_NEEDSPONSOR) { $sponsor = 1; } if ($b == $FE_LEGAL) { $legal = 1; } if ($b == $FE_GUIDELINES) { $gl = 1; } } if ($block > 1) { print "Warning: bug $bug->{'bug_id'} blocks several FE_ blockers.\n"; next; } if ($block == 0) { if ($flag eq "+") { $bzb = \%BZA; } elsif ($flag eq "-") { $bzb = \%BZR; } elsif ($flag eq "?") { $bzb = \%BZR; } else { next if $bug->{'bug_status'} eq "CLOSED"; $bzb = \%BZN; } } if ($bug->{'pkg_name'} =~ /^([^(]+)\(-kmod\)$/) { my $pkgName = $1; $bug->{'pkg_name'} = $pkgName; $NAME2REVIEW{"$pkgName-kmod"} = $bug->{'bug_id'}; } $NAME2REVIEW{$bug->{'pkg_name'}} = $bug->{'bug_id'}; $bzb->{$bug->{'bug_id'}} = $bug; if ($sponsor == 1 && $bzb == \%BZN) { $BZS{$bug->{'bug_id'}} = $bug; } if ($legal == 1 && $bzb == \%BZN) { $BZL{$bug->{'bug_id'}} = $bug; } if ($gl == 1 && $bzb == \%BZN) { $BZG{$bug->{'bug_id'}} = $bug; } } } &grabRepoList("$main::repourl/development/source/SRPMS/", \%FEDORA_D); $FEDORA_R[$main::currel + 1] = \%FEDORA_D; for my $i ($main::firstrel .. $main::currel) { $FEDORA_R[$i] = {}; &grabRepoList("$main::repourl/releases/$i/Everything/source/SRPMS/", $FEDORA_R[$i]); &grabRepoList("$main::repourl/updates/$i/SRPMS/", $FEDORA_R[$i]); } # Check comps files for my $i ($main::currel .. ($main::currel + 1)) { print STDERR "Looking for $main::compsDir/comps-f$i.xml.in\n"; if (-s "$main::compsDir/comps-f$i.xml.in") { my %F_RPM; my $s = "releases/$i/Everything"; $s = "development" if $i > $main::currel; &grabRepoList("$main::repourl/$s/i386/os/Packages/", \%F_RPM); if ($i <= $main::currel) { &grabRepoList("$main::repourl/updates/$i/i386/", \%F_RPM); } if ($i == $main::currel + 1) { my @A = keys %F_RPM; $COUNT_LIST{"bin_rpms"} = $#A + 1; } foreach my $k (keys % {$FEDORA_R[$i]}) { $F_RPM{$k} = 1; } $COMPS[$i] = {}; $COMPS_M[$i] = {}; &grabCompsList("$main::compsDir/comps-f$i.xml.in", $COMPS[$i]); &checkComps(\%F_RPM, $COMPS[$i], $COMPS_M[$i], $i); } } # Take a look at CVS stuff if (-d $main::cvsDir) { $main::cvsDir =~ s/\/+$//; my $f = "/tmp/tstmp_$$"; system "touch -d '12 weeks ago' $f"; my $cmd = "find $main::cvsDir -name CVS -prune -o -type f -newer $f -print " . "| sed 's|^$main::cvsDir/||;s|/.*||'|sort -u"; local *IN; open IN, "$cmd |" or die "Couldn't launch find command in CVS: $!"; while ( ) { s/\s+$//; next unless defined $BZOWN->{$_}; $OWN_CVS_RECENT{$_} = 1; } close IN; unlink $f; my @G = glob "$main::cvsDir/*"; foreach $_ (@G) { s/^$main::cvsDir\///; next if /^(CVS|README)$/; if (-d "$main::cvsDir/$_/devel") { $COUNT_LIST{"CVS"} += 1; } else { $DISCARD{$_} = 1 unless defined $FEDORA_D{$_}; next; } if (-f "$main::cvsDir/$_/devel/dead.package") { $DISCARD{$_} = 1 unless defined $FEDORA_D{$_}; } elsif (-f "$main::cvsDir/$_/devel/$_.spec") { } elsif ($_ =~ /^(.*[^0-9])[0-9]+$/ && -f "$main::cvsDir/$_/devel/$1.spec") { } elsif (-f "$main::cvsDir/$_/devel/README") { $DISCARD{$_} = 1 unless defined $FEDORA_D{$_}; } elsif (-f "$main::cvsDir/$_/devel/README.CVS") { $DISCARD{$_} = 1 unless defined $FEDORA_D{$_}; } else { print STDERR "Look in $main::cvsDir/$_/devel/\n"; } next if defined($BZOWN->{$_}) || defined($DISCARD{$_}) || defined($FEDORA_D{$_}); $CVS_NO_OWNER{$_} = 1; } close IN; } # Grab open BZ bug report tickets # We want them all, but have to grab only a few at a time otherwise we get # timeouts or internal server errors my @PKG_L = keys %$BZOWN; my $i = 0; while ($i <= $#PKG_L) { my @A; for my $j (1 .. 256) { push @A, $PKG_L[$i]; $i += 1; last if $i > $#PKG_L; } print STDERR "Running runQueryOpenBugs at $i\n"; my $bA = &runQueryOpenBugs($rpc, \@A); foreach my $bug (@$bA) { # Special case scop $bug->{'assigned_to'} = 'ville.skytta@iki.fi' if $bug->{'assigned_to'} eq 'scop@fedoraproject.org'; $bug->{'reporter'} = 'ville.skytta@iki.fi' if $bug->{'reporter'} eq 'scop@fedoraproject.org'; warn "assigned_to should be an email address: " . $bug->{'assigned_to'} if index($bug->{'assigned_to'}, "@") < 0; warn "reporter should be an email address: " . $bug->{'reporter'} if index($bug->{'reporter'}, "@") < 0; $bug->{'opendate'} = ParseDate($bug->{'opendate'}); $bug->{'changeddate'} = ParseDate($bug->{'changeddate'}); $bug->{'pkg_name'} = $bug->{'component'}; $COUNT_LIST{"openOPEN-BUGS"} += 1; $BZB{$bug->{'bug_id'}} = $bug; } } &checkOpenInOwners(\%BZR, "FE-REVIEW"); &checkOpenInOwners(\%BZN, "FE-NEW"); &checkOwners; my $fourDaysAgo = DateCalc("4 days ago", "today"); my $fourWeeksAgo = DateCalc("4 weeks ago", "today"); my $eightWeeksAgo = DateCalc("8 weeks ago", "today"); &checkAcceptClosed(\%BZA); &checkAcceptOpen(\%BZA); &countOpen(\%BZR, "FE-REVIEW"); &checkNotClosed(\%BZR, "FE-REVIEW"); &checkLowActivity(\%BZR, "FE-REVIEW"); &countOpen(\%BZN, "FE-NEW"); &checkNotClosed(\%BZN, "FE-NEW"); &checkLowActivity(\%BZN, "FE-NEW"); #&checkNoActivity(\%BZN, "FE-NEW"); &countOpen(\%BZS, "FE-NEEDSPONSOR"); &checkLowActivity(\%BZS, "FE-NEEDSPONSOR"); &countOpen(\%BZL, "FE-Legal"); &checkLowActivity(\%BZL, "FE-Legal"); &countOpen(\%BZG, "FE-GUIDELINES"); &checkLowActivity(\%BZG, "FE-GUIDELINES"); &checkLowActivity(\%BZB, "OPEN-BUGS"); &checkBugs(\%BZB); &checkMaintainers(); &checkDropped(); print "= Fedora Package Status of ", &UnixDate("today", "%b %e, %Y"), " =\n"; &displayOwnersWiki; &displayAcceptWiki(\%BZA); &displayNewReviewWiki(\%BZR, "FE-REVIEW", 'reporter'); &displayNewReviewWiki(\%BZN, "FE-NEW", 'reporter'); &displayNewReviewWiki(\%BZS, "FE-NEEDSPONSOR", 'reporter'); &displayNewReviewWiki(\%BZL, "FE-Legal", 'reporter'); &displayNewReviewWiki(\%BZG, "FE-GUIDELINES", 'reporter'); &displayNewReviewWiki(\%BZB, "OPEN-BUGS", 'assigned_to'); &displayCVSWiki(); &displayMaintainersWiki(); &displayDroppedWiki(); &displayCompsWiki; print "\n[[Category:Fedora]]\n"; print STDERR "\n\nFedora Package Status of ", &UnixDate("today", "%b %e, %Y"), "\n"; print STDERR "\nThe full report can be found here:\n"; print STDERR "http://fedoraproject.org/wiki/PackageMaintainers/PackageStatus\n\n"; &displayOwnersMail; &displayAcceptMail; &displayNewReviewMail("FE-REVIEW"); &displayNewReviewMail("FE-NEW"); &displayNewReviewMail("FE-NEEDSPONSOR"); &displayNewReviewMail("FE-Legal"); &displayNewReviewMail("FE-GUIDELINES"); &displayNewReviewMail("OPEN-BUGS"); &displayCVSMail(); &displayMaintainersMail(); &displayDroppedMail(); &displayCompsMail; exit 0; sub checkOwners { my $orphan = 0; my $cnt = 0; my @NO; my @NP; my @NP_R; my @OE; foreach my $k (keys %FEDORA_D) { next if defined $BZOWN->{$k}; push @NO, $k } if ($#NO >= 0) { $COUNT_LIST{"NoOwner"} = $#NO + 1; $PKG_LIST{"NoOwner"} = \@NO; } $OWNER_STAT{$orphans} = [ 0, 0, 0, 0, {} ]; foreach my $k (keys %$BZOWN) { my $owner = $BZOWN->{$k}->{'owner'}; die "Unknown email for $owner" unless defined $MEMBER_u{$owner}; $owner = $ {$MEMBER_u{$owner}}[1]; $cnt += 1; my $s = $OWNER_STAT{$owner}; if (defined $s) { $$s[0] += 1; } else { # We have pkg_cnt, open_bugs, touched_pkgs, touched_bugs, bugs_hash $OWNER_STAT{$owner} = [ 1, 0, 0, 0, {} ]; $s = $OWNER_STAT{$owner}; } if ($owner eq $orphans) { $orphan += 1; push @OE, $k if defined $FEDORA_D{$k}; next; } else { $$s[2] = 1 if defined $OWN_CVS_RECENT{$k}; } unless (defined $FEDORA_D{$k}) { next if defined $DISCARD{$k}; next if defined $INFRASTRUCTURE{$k}; next if defined $NOTINFEDORA{$k}; if (defined $FEDORA_R[$main::currel]->{$k}) { push @NP_R, $k; } else { push @NP, $k; } } } my @TO = sort { my $ca = $OWNER_STAT{$a}; my $cb = $OWNER_STAT{$b}; $$cb[0] <=> $$ca[0]; } keys %OWNER_STAT; $COUNT_LIST{"owner"} = $cnt; $COUNT_LIST{"orphan"} = $orphan; $OWNER_LIST{"package"} = \@TO; $PKG_LIST{"NotDevelNotRel"} = \@NP; $PKG_LIST{"NotDevel"} = \@NP_R; $PKG_LIST{"OrphanDevel"} = \@OE; } sub displayOwnersWiki { print "== About owners ==\n\n"; print "=== Package count ===\n\n"; print "We have $COUNT_LIST{'owner'} packages in bugzilla owners.
\n"; print "We have $COUNT_LIST{'bin_rpms'} binary rpms in the devel repo.
\n"; print "There are $COUNT_LIST{'orphan'} orphans.\n"; print "\n=== Top $TopCount package owners ===\n"; &displayOwnerCntWiki($OWNER_LIST{"package"}, \%OWNER_STAT, 0); print "\n=== Packages not present in the development repo ===\n"; my $a = $PKG_LIST{"NotDevelNotRel"}; if ($#$a >= 0) { my $cnt = $#$a + 1; print "\nWe have $cnt packages not available in devel or release:\n"; &displayPkgListByOwnerWiki($a); } $a = $PKG_LIST{"NotDevel"}; if ($#$a >= 0) { my $cnt = $#$a + 1; print "\nWe have $cnt packages not available in devel "; print "but present in release:\n"; &displayPkgListByOwnerWiki($a); } if ($COUNT_LIST{"openInOwners"} > 0) { print "\n\n=== Packages that have not yet completed review ===\n"; print "\nWe have $COUNT_LIST{'openInOwners'} packages ", "which have not yet been FE-ACCEPT'd...\n"; &displayBLWiki($BUG_LIST{"openInOwnersFE-REVIEW"}, \%BZR, 'reporter'); &displayBLWiki($BUG_LIST{"openInOwnersFE-NEW"}, \%BZN, 'reporter'); } if ($COUNT_LIST{"NoOwner"} > 0) { print "\n\n=== Packages missing in bugzilla owners ===\n"; print "\nWe have $COUNT_LIST{'NoOwner'} packages present in the ", "development repo which have no entry in bugzilla owners:
\n";
    my $p = $PKG_LIST{"NoOwner"};
    print &toLine(join(" ", @$p)), "\n";
    print "
\n"; } $a = $PKG_LIST{"OrphanDevel"}; print "\n=== Orphaned packages present in the development repo ===\n"; if ($#$a >= 0) { my $cnt = $#$a + 1; print "\nWe have $cnt orphaned packages available in devel:
\n";
    print &toLine(join(" ", sort @$a)), "\n";
    print "
\n"; } } sub displayCompsWiki { print "== About comps.xml files ==\n\n"; my $rel = $main::currel + 1; while (defined $COMPS[$rel]) { if ($rel > $main::currel) { print "\n=== Fedora devel ===\n\n"; } else { print "\n=== Fedora $rel ===\n\n"; } my $cnt = $COUNT_LIST{"InComps$rel"}; print "We have $cnt packages in comps-f$rel file.
\n"; $cnt = $COUNT_LIST{"CompsMiss$rel"}; if ($cnt > 0) { print "\n=== Packages not present in comps-f$rel ===\n"; print "\nWe have $cnt packages missing:\n"; &displayPkgListByOwnerWiki($PKG_LIST{"CompsMiss$rel"}); } $cnt = $COUNT_LIST{"CompsOver$rel"}; if ($cnt > 0) { print "\n=== Packages listed in comps-f$rel but not available ===\n"; print "\nWe have $cnt packages missing:\n"; &displayPkgListByOwnerWiki($PKG_LIST{"CompsOver$rel"}); } $rel -= 1; } } sub displayOwnerCntWiki { my ($a, $c, $aref, $count, $mark, $buglist) = @_; if (defined $count) { $count -= 1; } else { $count = $TopCount - 1; } print "{| border=\"1\"\n"; for my $i (0 .. $count) { my $n = lc $$a[$i]; my $sponsor = 0; $n =~ s/["]//g; if (defined $MEMBER{$n}) { my $m = $MEMBER{$n}; $n = $$m[2]; if ($mark == 1 && ($$m[3] eq "sponsor" || $$m[3] eq "administrator")) { $sponsor = 1; } } else { $n =~ s/\@/ at /; $n =~ s/\./ dot /g; } my $aa = $c->{$$a[$i]}; $aa = $$aa[$aref] if defined $aref; if (defined $buglist) { my $h = $buglist->{$$a[$i]}; my @A = sort(keys %$h); $aa = "[https://bugzilla.redhat.com/buglist.cgi?bug_id=" . join(",", @A) . " $aa]"; } if ($sponsor == 1) { print "|-\n|style=\"background-color: #80FF80;\" | $n||$aa\n"; } else { print "|-\n|$n||$aa\n"; } } print "|}\n"; } sub displayPkgListByOwnerWiki { my ($a) = @_; my %PO; foreach my $p (@$a) { my $owner = $BZOWN->{$p}->{'owner'}; $owner = $ {$MEMBER_u{$owner}}[1]; my $e = $PO{$owner}; if (defined $e) { push @$e, $p; } else { $PO{$owner} = [ $p ]; } } print "{| border=\"1\"\n"; foreach my $owner (sort(keys %PO)) { my $e = $PO{$owner}; $owner =~ s/\@/ at /; $owner =~ s/\./ dot /g; foreach my $p (sort @$e) { my $summary = $BZOWN->{$p}->{'summary'}; print "|-\n|$owner||$p||$summary\n"; } } print "|}\n"; } sub displayPkgListByOwnerMail { my ($a) = @_; my %PO; foreach my $p (@$a) { my $owner = $BZOWN->{$p}->{'owner'}; $owner = $ {$MEMBER_u{$owner}}[1]; my $e = $PO{$owner}; if (defined $e) { push @$e, $p; } else { $PO{$owner} = [ $p ]; } } foreach my $owner (sort(keys %PO)) { my $e = $PO{$owner}; $owner =~ s/\@/ at /; $owner =~ s/\./ dot /g; foreach my $p (@$e) { printf STDERR " %-42s %s\n", $owner, $p; } } } sub displayOwnersMail { print STDERR "\nOwners stats:\n"; print STDERR " - $COUNT_LIST{'owner'} packages\n"; print STDERR " - $COUNT_LIST{'bin_rpms'} binary rpms in devel\n"; print STDERR " - $COUNT_LIST{'orphan'} orphans\n"; $a = $PKG_LIST{"NotDevelNotRel"}; if ($#$a >= 0) { my $cnt = $#$a + 1; print STDERR " - $cnt packages not available in devel or release\n"; &displayPkgListByOwnerMail($a); } $a = $PKG_LIST{"NotDevel"}; if ($#$a >= 0) { my $cnt = $#$a + 1; print STDERR " - $cnt packages not available in devel "; print STDERR "but present in release\n"; &displayPkgListByOwnerMail($a); } if ($COUNT_LIST{"openInOwners"} > 0) { print STDERR " - $COUNT_LIST{'openInOwners'} packages ", "which have not yet been FE-ACCEPT'd...\n"; &displayBL($BUG_LIST{"openInOwnersFE-REVIEW"}, \%BZR, 'reporter'); &displayBL($BUG_LIST{"openInOwnersFE-NEW"}, \%BZN, 'reporter'); } if ($COUNT_LIST{"NoOwner"} > 0) { print STDERR " - $COUNT_LIST{'NoOwner'} packages present in the ", "development repo which have no owners entry\n"; my $p = $PKG_LIST{"NoOwner"}; my $s = &toLine(join(" ", sort @$p)); $s =~ s/\n/\n /sg; print STDERR " $s\n"; } $a = $PKG_LIST{"OrphanDevel"}; if ($#$a >= 0) { my $cnt = $#$a + 1; print STDERR " - $cnt orphaned packages, yet available in devel\n"; my $s = &toLine(join(" ", sort @$a)); $s =~ s/\n/\n /sg; print STDERR " $s\n"; } } sub displayCompsMail { print STDERR "\nComps.xml files stats:\n"; my $rel = $main::currel + 1; while (defined $COMPS[$rel]) { my $cnt = $COUNT_LIST{"InComps$rel"}; print STDERR " - $cnt packages in comps-f$rel file\n"; $cnt = $COUNT_LIST{"CompsMiss$rel"}; if ($cnt > 0) { print STDERR " - $cnt packages missing from comps-f$rel file\n"; } $cnt = $COUNT_LIST{"CompsOver$rel"}; if ($cnt > 0) { print STDERR " - $cnt packages in comps-f$rel but not in repo\n"; } $rel -= 1; } } sub checkAcceptClosed { my ($BZ) = @_; my @BL; my @BLO; foreach my $b (sort(keys %$BZ)) { my $a = $BZ->{$b}; next unless $a->{'bug_status'} eq "CLOSED"; my $pkg = $a->{'pkg_name'}; unless ($FEDORA_D{$pkg} == 1 || defined($BZOWN->{$pkg})) { $pkg =~ s/-[^-]+-[^-]+$//; } unless ($FEDORA_D{$pkg} == 1 || defined($BZOWN->{$pkg})) { $pkg = $a->{'pkg_name'}; $pkg =~ s/-[^-]+$//; } unless ($FEDORA_D{$pkg} == 1 || defined($BZOWN->{$pkg})) { $pkg = lc $a->{'pkg_name'}; unless ($FEDORA_D{$pkg} == 1 || defined($BZOWN->{$pkg})) { $pkg =~ s/-[^-]+-[^-]+$//; } } unless ($FEDORA_D{$pkg} == 1 || defined($BZOWN->{$pkg})) { $pkg = lcfirst $a->{'pkg_name'}; } unless (defined $BZREV_BUGS{$a->{'assigned_to'}}) { $BZREV_BUGS{$a->{'assigned_to'}} = {}; } $BZREV_BUGS{$a->{'assigned_to'}}->{$b} = 1; unless (defined $BZOWN_BUGS{$a->{'reporter'}}) { $BZOWN_BUGS{$a->{'reporter'}} = {}; } $BZOWN_BUGS{$a->{'reporter'}}->{$b} = 1; $COUNT_LIST{"acceptedClosed"} += 1; next if defined $DISCARD{$pkg}; next if defined $NOTINFEDORA{$pkg}; if (Date_Cmp($a->{'changeddate'}, $fourDaysAgo) < 0) { #print STDERR "Date_Cmp $a->{'changeddate'} < $fourDaysAgo\n"; if ($FEDORA_D{$pkg} == 1) { if (!defined($FEDORA_D{$pkg}) && !defined($BZOWN->{$pkg})) { push @BLO, $b; $COUNT_LIST{"missingOwner"} += 1; } } else { push @BL, $b; $COUNT_LIST{"missing"} += 1; unless (defined $BZOWN->{$pkg}) { push @BLO, $b; $COUNT_LIST{"missingOwner"} += 1; } } } } foreach my $k (keys %BZREV_BUGS) { my $h = $BZREV_BUGS{$k}; my @A = keys %$h; $BZREV_CNT{$k} = $#A + 1; } foreach my $k (keys %BZOWN_BUGS) { my $h = $BZOWN_BUGS{$k}; my @A = keys %$h; $BZOWN_CNT{$k} = $#A + 1; } my @TR = sort {$BZREV_CNT{$b} <=> $BZREV_CNT{$a}} keys %BZREV_CNT; my @TO = sort {$BZOWN_CNT{$b} <=> $BZOWN_CNT{$a}} keys %BZOWN_CNT; $BUG_LIST{"acceptedNoDevel"} = \@BL; $BUG_LIST{"acceptedNoOwn"} = \@BLO; $OWNER_LIST{"BZOwner"} = \@TO; $OWNER_LIST{"BZReviewer"} = \@TR; } sub displayAcceptWiki { my ($BZ) = @_; print "\n\n== About FE-ACCEPT packages ==\n"; print "\n\n=== Package count ===\n"; print "\nWe have $COUNT_LIST{'acceptedClosed'} accepted, closed package reviews\n"; print "\n=== Top $TopCount BZ review requests submitters ===\n"; print "Sponsors are highlighted in green.\n"; &displayOwnerCntWiki($OWNER_LIST{"BZOwner"}, \%BZOWN_CNT, undef, $TopCount, 1, \%BZOWN_BUGS); print "\n=== Top $TopCount BZ review requests reviewers ===\n"; print "Sponsors are highlighted in green.\n"; &displayOwnerCntWiki($OWNER_LIST{"BZReviewer"}, \%BZREV_CNT, undef, $TopCount, 1, \%BZREV_BUGS); print "\n\n=== Potential problems ===\n"; if ($COUNT_LIST{"missing"} > 0) { print "\nWe have $COUNT_LIST{'missing'} accepted, closed packages where I'm unable to ", "find the package in the development repo:\n"; &displayBLWiki($BUG_LIST{"acceptedNoDevel"}, $BZ, 'reporter'); } if ($COUNT_LIST{"missingOwner"} > 0) { print "\nWe have $COUNT_LIST{'missingOwner'} accepted, closed packages where I'm unable to ", "find the package in the bugzilla owners:\n"; &displayBLWiki($BUG_LIST{"acceptedNoOwn"}, $BZ, 'reporter'); } if ($COUNT_LIST{"acceptOpenInactive"} > 0) { print "\n\n=== Inactivity notice ===\n"; print "\nWe have $COUNT_LIST{'acceptOpenInactive'} accepted, open package reviews older than 4 weeks\n"; &displayBLWiki($BUG_LIST{"acceptOpenInactive"}, $BZ, 'reporter'); } if ($COUNT_LIST{"acceptOpenInDevel"} > 0) { print "\n\n=== Some cleanup needed ===\n"; print "\nWe have $COUNT_LIST{'acceptOpenInDevel'} accepted, open package reviews where the package ", "appears to already be in the repo...\n"; &displayBLWiki($BUG_LIST{"acceptOpenInDevel"}, $BZ, 'reporter'); } } sub displayAcceptMail { print STDERR "\nFE-ACCEPT packages stats:\n"; print STDERR " - $COUNT_LIST{'acceptedClosed'} accepted, closed package reviews\n"; if ($COUNT_LIST{"missing"} > 0) { print STDERR " - $COUNT_LIST{'missing'} accepted, closed package reviews not in repo\n"; } if ($COUNT_LIST{"missingOwner"} > 0) { print STDERR " - $COUNT_LIST{'missingOwner'} accepted, closed package reviews not in owners\n"; } if ($COUNT_LIST{"acceptOpenInactive"} > 0) { print STDERR " - $COUNT_LIST{'acceptOpenInactive'} accepted, open package reviews older than 4 weeks;\n"; } if ($COUNT_LIST{"acceptOpenInDevel"} > 0) { print STDERR " - $COUNT_LIST{'acceptOpenInDevel'} accepted, open package reviews ", "with a package already in the repo\n"; } } sub checkAcceptOpen { my ($BZ) = @_; my @BL; my @LATE; foreach my $b (sort(keys %$BZ)) { my $a = $BZ->{$b}; next if $a->{'bug_status'} eq "CLOSED"; my $pkg = $a->{'pkg_name'}; unless ($FEDORA_D{$pkg} == 1) { $pkg = lc $a->{'pkg_name'}; } unless ($FEDORA_D{$pkg} == 1) { $pkg = lcfirst $a->{'pkg_name'}; } if ($FEDORA_D{$pkg} == 1) { $COUNT_LIST{"acceptOpenInDevel"} += 1; push @BL, $b; } if (Date_Cmp($a->{'changeddate'}, $fourWeeksAgo) < 0) { push @LATE, $b; } } $BUG_LIST{"acceptOpenInDevel"} = \@BL; $BUG_LIST{"acceptOpenInactive"} = \@LATE; $COUNT_LIST{"acceptOpenInactive"} = $#LATE + 1; } sub countOpen { my ($BZ, $cur) = @_; foreach my $b (keys %$BZ) { my $a = $BZ->{$b}; next if $a->{'bug_status'} eq "CLOSED"; $COUNT_LIST{"open$cur"} += 1; } } sub checkNotClosed { my ($BZ, $cur) = @_; my @BL; foreach my $b (sort(keys %$BZ)) { my $a = $BZ->{$b}; next unless $a->{'bug_status'} eq "CLOSED"; push @BL, $b; } $COUNT_LIST{"closed$cur"} = $#BL + 1; $BUG_LIST{"closed$cur"} = \@BL; } sub checkLowActivity { my ($BZ, $cur) = @_; my @BL; my @LATE; foreach my $b (sort(keys %$BZ)) { my $a = $BZ->{$b}; next if $a->{'bug_status'} eq "CLOSED"; next if $a->{'short_desc'} =~ /Tracker/; if (Date_Cmp($a->{'changeddate'}, $fourWeeksAgo) < 0) { if (Date_Cmp($a->{'changeddate'}, $eightWeeksAgo) < 0) { push @LATE, $b; } else { push @BL, $b; } } } $COUNT_LIST{"inactive8$cur"} = $#LATE + 1; $COUNT_LIST{"inactive4$cur"} = $#BL + 1; $BUG_LIST{"inactive8$cur"} = \@LATE; $BUG_LIST{"inactive4$cur"} = \@BL; } #sub checkNoActivity { # my ($BZ, $cur) = @_; # my @BL; # foreach my $b (sort(keys %$BZ)) { # my $a = $BZ->{$b}; # next if $a->{'bug_status'} eq "CLOSED"; # next if $a->{'opendate'} ne $a->{'changeddate'}; # if (Date_Cmp($a->{'changeddate'}, $eightWeeksAgo) < 0) { # push @BL, $b; # } # } # if ($#BL >= 0) { # my $cnt = $#BL + 1; # print "\nWe have $cnt $cur tickets 8 weeks old with no comments\n"; # &displayBL(\@BL, $BZ, 'reporter'); # } #} sub usage { print STDERR "Usage: $0 [options] where options are: -help this help note -bu Bugzilla username -comps comps directory [$main::compsDir] -currel current Fedora release number [$main::currel] -cvs CVS directory [$main::cvsDir] -firstrel first Fedora release number [$main::firstrel] -p password (to retrieve members list) -repourl Fedora SRPMS development repo base [$main::repourl] -u username (to retrieve members list) [$main::username]\n"; exit 1; } sub grabRepoList { my ($f, $h) = @_; local *IN; open IN, "wget -nv -O - \"$f\"|" or die "Failed to wget $f : $!"; while ( ) { next unless /{$pkg} = 1; } close IN; } sub grabCompsList { my ($f, $h) = @_; local *IN; open IN, "$f" or die "Failed to open $f : $!"; while ( ) { next unless /]*>([^<]+)<\/packagereq>/; $h->{$1} = 1; } close IN; } sub toLine { my ($s) = @_; my $p1 = 0; my $p2 = $p1 + 72; while ($p2 < length($s)) { my $p3 = rindex $s, " ", $p2; if ($p3 < $p1) { $p2 += 1; next; } substr $s, $p3, 1, "\n"; $p1 = $p3 + 1; $p2 = $p1 + 72; } return $s; } sub displayBL { my ($BL, $BZ, $field) = @_; return if $#$BL < 0; print STDERR " https://bugzilla.redhat.com/buglist.cgi?bug_id=", join(",", @$BL), "\n"; foreach my $b (sort @$BL) { my $a = $BZ->{$b}; my $owner = $a->{$field}; $owner =~ s/["]//g; $owner =~ s/\@/ at /; printf STDERR " %-40s %s\n", $a->{'pkg_name'}, $owner; } } sub displayBLWiki { my ($BL, $BZ, $field) = @_; return if $#$BL < 0; my %O; foreach my $b (@$BL) { my $a = $BZ->{$b}; my $e = $O{$a->{$field}}; if (defined $e) { push @$e, $a; } else { $O{$a->{$field}} = [ $a ]; } } print "{| border=\"1\"\n"; foreach my $n (sort(keys %O)) { my $e = $O{$n}; $n =~ s/["]//g; $n =~ s/\@/ at /; $n =~ s/\./ dot /g; foreach my $a (@$e) { print "|-\n|$n||$a->{'pkg_name'}||[", "https://bugzilla.redhat.com/show_bug.cgi?id=", $a->{'bug_id'}, " ", $a->{'bug_id'}, "]||$a->{'short_desc'}\n"; } } print "|}\n"; } sub displayNewReviewWiki { my ($BZ, $cur, $field) = @_; my $cnt = $COUNT_LIST{"open$cur"}; return unless $cnt > 0; print "\n\n== About $cur packages ==\n"; print "\n\n=== Open ticket count ===\n"; print "\nWe have $cnt open tickets in $cur\n"; if ($COUNT_LIST{"inactive8$cur"} > 0 || $COUNT_LIST{"inactive4$cur"} > 0) { print "\n\n=== Inactivity notice ===\n"; if ($COUNT_LIST{"inactive8$cur"} > 0) { $cnt = $COUNT_LIST{"inactive8$cur"}; print "\nWe have $cnt $cur tickets with no activity in eight weeks\n"; &displayBLWiki($BUG_LIST{"inactive8$cur"}, $BZ, $field); } if ($COUNT_LIST{"inactive4$cur"} > 0) { $cnt = $COUNT_LIST{"inactive4$cur"}; print "\nWe have $cnt $cur tickets with no activity in four weeks\n"; &displayBLWiki($BUG_LIST{"inactive4$cur"}, $BZ, $field); } } if ($COUNT_LIST{"closed$cur"} > 0) { print "\n\n=== Some cleanup needed ===\n"; $cnt = $COUNT_LIST{"closed$cur"}; print "\nWe have $cnt closed tickets still blocking $cur\n"; &displayBLWiki($BUG_LIST{"closed$cur"}, $BZ, $field); } } sub displayNewReviewMail { my ($cur) = @_; my $cnt = $COUNT_LIST{"open$cur"}; return unless $cnt > 0; print STDERR "\n$cur packages stats:\n"; print STDERR " - $cnt open tickets\n"; if ($COUNT_LIST{"inactive8$cur"} > 0) { $cnt = $COUNT_LIST{"inactive8$cur"}; print STDERR " - $cnt tickets with no activity in eight weeks\n"; } if ($COUNT_LIST{"inactive4$cur"} > 0) { $cnt = $COUNT_LIST{"inactive4$cur"}; print STDERR " - $cnt tickets with no activity in four weeks\n"; } if ($COUNT_LIST{"closed$cur"} > 0) { $cnt = $COUNT_LIST{"closed$cur"}; print STDERR " - $cnt closed tickets\n"; } } sub checkOpenInOwners { my ($BZ, $cur) = @_; my @BL; my %OL; foreach my $k (keys %$BZOWN) { $OL{lc $k} = $k; } foreach my $b (sort(keys %$BZ)) { my $a = $BZ->{$b}; next if $a->{'bug_status'} eq "CLOSED"; next if defined $DISCARD{$a->{'pkg_name'}}; next unless defined $OL{lc $a->{'pkg_name'}}; # Do not complain for the Merge Review stuff next if $a->{'short_desc'} =~ /Merge Review:/; push @BL, $b; } $COUNT_LIST{"openInOwners"} += $#BL + 1; $BUG_LIST{"openInOwners$cur"} = \@BL; } sub checkMaintainers { my @PL; my @BL; my @O = keys %OWNER_STAT; foreach my $k (@O) { next if $k eq $orphans; my $a = $OWNER_STAT{$k}; #next unless $$a[2] == 0 && $$a[3] == 0; next unless $$a[2] == 0; if ($$a[1] > 0) { push @BL, $k; } else { push @PL, $k; } } $MAINT_LIST{"bugs"} = \@BL; $MAINT_LIST{"packages"} = \@PL; $COUNT_LIST{'maintainers'} = $#O; # Do not count orphan owner $COUNT_LIST{'maintbugs'} = $#BL + 1; $COUNT_LIST{'maintpkg'} = $#PL + 1; } sub displayCVSWiki { print "\n\n== About CVS repository ==\n\n"; print "\n\n=== Package count ===\n"; print "\nWe have $COUNT_LIST{'CVS'} packages with a devel directory\n"; my @A = sort(keys %CVS_NO_OWNER); if ($#A >= 0) { my $cnt = $#A + 1; print "\n=== Packages in CVS with no entry in owners ===\n"; print "\nWe have $cnt packages in CVS with no owners entry:
\n";
    print join("\n", @A), "
\n"; } @A = sort (keys %DISCARD); if ($#A >= 0) { print "\n=== Packages dropped from Fedora ===\n"; my $cnt = $#A + 1; print "\nWe have $cnt packages dropped:
\n";
    print &toLine(join(" ", sort @A)), "\n";
    print "
\n"; } } sub displayCVSMail { print STDERR "\nCVS stats:\n"; print STDERR " - $COUNT_LIST{'CVS'} packages with a devel directory\n"; my @A = sort(keys %CVS_NO_OWNER); if ($#A >= 0) { my $cnt = $#A + 1; print STDERR " - $cnt packages with no owners entry\n"; my $s = &toLine(join(" ", @A)); $s =~ s/\n/\n /sg; print STDERR " $s\n"; } @A = sort (keys %DISCARD); if ($#A >= 0) { my $cnt = $#A + 1; print STDERR " - $cnt packages were dropped from Fedora\n"; } } sub checkBugs { my ($BZ) = @_; foreach my $b (keys %$BZ) { my $a = $BZ->{$b}; next if $a->{'short_desc'} =~ /Tracker/; my $assignee = $a->{'assigned_to'}; my $s = $OWNER_STAT{$assignee}; unless (defined $s) { my $owner = $BZOWN->{$a->{'pkg_name'}}->{'owner'}; $owner = $ {$MEMBER_u{$owner}}[1]; print STDERR "Change $assignee to $owner\n"; $s = $OWNER_STAT{$owner}; } die "Couldn't find OWNER_STAT for $assignee $a->{'pkg_name'}" unless defined $s; $$s[1] += 1; if (Date_Cmp($a->{'changeddate'}, $eightWeeksAgo) >= 0) { $$s[3] = 1; } $$s[4]->{$b} = $a; } my @TO = sort { my $ca = $OWNER_STAT{$a}; my $cb = $OWNER_STAT{$b}; $$cb[1] <=> $$ca[1]; } keys %OWNER_STAT; $OWNER_LIST{"bugs"} = \@TO; } sub displayMaintainersWiki { print "== About maintainers ==\n\n"; print "=== Maintainers count ===\n\n"; print "We have $COUNT_LIST{'maintainers'} maintainers as bugzilla owners. 0) { print "=== Inactive maintainers with open bug reports ===\n\n"; print "We have $COUNT_LIST{'maintbugs'} maintainers with open bugs that ", "have had no noticeable CVS activity in the last 12 weeks\n"; my $a = $MAINT_LIST{"bugs"}; foreach my $k (sort @$a) { my $e = $OWNER_STAT{$k}; my $bugs = $$e[4]; my @K = keys %$bugs; &displayBLWiki(\@K, $bugs, 'assigned_to'); } } if ($COUNT_LIST{'maintpkg'} > 0) { print "=== Inactive maintainers ===\n\n"; print "We have $COUNT_LIST{'maintpkg'} maintainers that ", "have had no noticeable CVS activity in the last 12 weeks:\n"; print "{| border=\"1\"\n"; my $a = $MAINT_LIST{"packages"}; foreach my $k (sort @$a) { my $n = $k; $n =~ s/\@/ at /; $n =~ s/\./ dot /g; foreach my $o (keys %$BZOWN) { my $owner = $BZOWN->{$o}->{'owner'}; $owner = $ {$MEMBER_u{$owner}}[1]; next unless $owner eq $k; print "|-\n|$n||$o\n"; } } print "|}\n"; } } sub displayMaintainersMail { print STDERR "\nMaintainers stats:\n"; print STDERR " - $COUNT_LIST{'maintainers'} maintainers\n"; if ($COUNT_LIST{'maintbugs'} > 0) { print STDERR " - $COUNT_LIST{'maintbugs'} inactive maintainers with ", "open bugs\n"; } if ($COUNT_LIST{'maintpkg'} > 0) { print STDERR " - $COUNT_LIST{'maintpkg'} inactive maintainers\n"; } } sub checkDropped { my %D; for (my $i = $main::currel; $i >= $main::firstrel; $i--) { foreach my $k (keys %{$FEDORA_R[$i]}) { unless ($FEDORA_D{$k} or $D{$k}) { $DROPPED_SRPMS[$i]->{$k} = 1; $D{$k} = 1; } } } my @PL = keys %D; $PKG_LIST{"Dropped"} = \@PL; $COUNT_LIST{'Dropped'} = $#PL + 1; } sub displayDroppedWiki { return if $COUNT_LIST{'Dropped'} == 0; print "== About dropped packages ==\n\n"; print "We have a total of $COUNT_LIST{'Dropped'} dropped packages.\n"; for (my $i = $main::currel; $i >= $main::firstrel; $i--) { my @A = keys %{$DROPPED_SRPMS[$i]}; if ($#A >= 0) { my $n = $i + 1; $n = "devel" if $n > $main::currel; print "\n=== Fedora packages dropped between release $i and $n ===\n"; my $cnt = $#A + 1; print "\nWe have $cnt packages dropped:
\n";
      print &toLine(join(" ", sort @A)), "\n";
      print "
\n"; } } } sub displayDroppedMail { return if $COUNT_LIST{'Dropped'} == 0; print STDERR "\nDropped Fedora packages:\n"; print STDERR " - $COUNT_LIST{'Dropped'} packages were dropped", " since Fedora $main::firstrel\n"; } sub checkComps { my ($rh, $ch, $mh, $tag) = @_; my $prev; foreach my $k (sort(keys(%$rh))) { next if index($k, "$prev-") == 0; $prev = $k; next if defined $COMPSBLACKLIST{$k}; next if defined $ch->{$k}; next if $k =~ /plugin/i; next if $k =~ /^(lib|compat-|xfce4-|gtk-|kmod-|fonts?-)/i; next if $k =~ /(-devel|lib[s0-9]*|-python|-perl|-servers?|-clients?|-tools?)$/i; next if $k =~ /(-contribs?|-docs?|-x?emacs|-utils?|-fonts?)$/i; my $oa = $BZOWN->{$k}; if (defined $oa) { next if $BZOWN->{$k}->{'summary'} =~ /(binding|library|module|utilit)/i; } $mh->{$k} = -1; } foreach my $k (keys %$ch) { $mh->{$k} = 1 unless defined $rh->{$k}; if (defined $COMPSBLACKLIST{$k}) { warn "$k is blacklisted but still appears in comps.xml file"; } } my @A = keys %$ch; $COUNT_LIST{"InComps$tag"} = $#A + 1; undef @A; foreach my $k (keys %$mh) { push @A, $k if $mh->{$k} == -1; } $COUNT_LIST{"CompsMiss$tag"} = $#A + 1; $PKG_LIST{"CompsMiss$tag"} = \@A; my @B; foreach my $k (keys %$mh) { push @B, $k if $mh->{$k} == 1; } $COUNT_LIST{"CompsOver$tag"} = $#B + 1; $PKG_LIST{"CompsOver$tag"} = \@B; } sub runQuery { my ($rpc, $flag) = @_; my $querydata = { 'column_list' => ['opendate', 'changeddate', 'bug_severity', 'alias', 'assigned_to', 'reporter', 'bug_status', 'resolution', 'component', 'blockedby', 'short_desc'], 'product' => ['Fedora'], 'component' => ['Package Review'], 'field0-0-0' => 'flagtypes.name', 'bug_status' => ["NEW", "VERIFIED", "ASSIGNED", "REOPENED", "NEEDINFO_ENG", "NEEDINFO", "INVESTIGATE", "MODIFIED", "ON_DEV", "UNCONFIRMED", "QA_READY", "ON_QA", "FAILS_QA", "NEEDINFO_REPORTER", "RELEASE_PENDING", "POST"] }; if ($flag eq " ") { $querydata->{'type0-0-0'} = 'notregexp'; $querydata->{'value0-0-0'} = 'fedora-review[-+?]'; } else { $querydata->{'type0-0-0'} = 'equals'; $querydata->{'value0-0-0'} = "fedora-review$flag"; } my $call; while (1) { print STDERR "Running runQuery(rpc, '$flag') all open\n"; eval { $call = $rpc->call('bugzilla.runQuery', $querydata, $main::BZusername, $main::password); if ($call->faultstring) { print STDERR $call->faultstring . "\n"; exit 1; } }; if ($@) { warn $@; } else { last; } } my $result = $call->result; my $res_all = $result->{'bugs'}; $querydata->{'bug_status'} = ["CLOSED"]; while (1) { print STDERR "Running runQuery(rpc, '$flag') closed\n"; eval { $call = $rpc->call('bugzilla.runQuery', $querydata, $main::BZusername, $main::password); if ($call->faultstring) { print STDERR $call->faultstring . "\n"; exit 1; } }; if ($@) { warn $@; } else { last; } } $result = $call->result; my $res2 = $result->{'bugs'}; push @$res_all, @$res2; return $res_all; } sub runQueryOpenBugs { my ($rpc, $pkg) = @_; my $querydata = { 'column_list' => ['opendate', 'changeddate', 'bug_severity', 'alias', 'assigned_to', 'reporter', 'bug_status', 'resolution', 'component', 'blockedby', 'short_desc'], 'product' => ['Fedora'], 'component' => $pkg, 'bug_status' => ["NEW", "VERIFIED", "ASSIGNED", "REOPENED", "MODIFIED"] }; my $call; while (1) { eval { $call = $rpc->call('bugzilla.runQuery', $querydata, $main::BZusername, $main::password); if ($call->faultstring) { print STDERR $call->faultstring . "\n"; exit 1; } }; if ($@) { warn $@; print STDERR "Re-running runQueryOpenBugs(rpc, pkg_array)\n"; } else { last; } } my $result = $call->result; return $result->{'bugs'}; }