[bugzilla-gnome-org-extensions] initial import
- From: Krzesimir Nowak <krnowak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [bugzilla-gnome-org-extensions] initial import
- Date: Thu, 20 Nov 2014 22:02:38 +0000 (UTC)
commit 6b29306faf03180d5610541cf64f73154a130b1f
Author: Olav Vitters <olav vitters nl>
Date: Wed Feb 29 10:44:38 2012 +0100
initial import
Config.pm | 5 +
Extension.pm | 17 ++
lib/Util.pm | 275 ++++++++++++++++++++
.../hook/global/code-error-errors.html.tmpl | 24 ++
template/en/default/pages/patchreport.html.tmpl | 77 ++++++
5 files changed, 398 insertions(+), 0 deletions(-)
---
diff --git a/Config.pm b/Config.pm
new file mode 100644
index 0000000..c4b6518
--- /dev/null
+++ b/Config.pm
@@ -0,0 +1,5 @@
+package Bugzilla::Extension::PatchReport;
+use strict;
+use constant NAME => 'PatchReport';
+
+__PACKAGE__->NAME;
diff --git a/Extension.pm b/Extension.pm
new file mode 100644
index 0000000..d7f4d9f
--- /dev/null
+++ b/Extension.pm
@@ -0,0 +1,17 @@
+package Bugzilla::Extension::PatchReport;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Extension::PatchReport::Util;
+
+our $VERSION = '';
+
+sub page_before_template {
+ my ($self, $args) = @_;
+
+ page(%{ $args });
+
+}
+
+
+__PACKAGE__->NAME;
diff --git a/lib/Util.pm b/lib/Util.pm
new file mode 100644
index 0000000..4b2f42e
--- /dev/null
+++ b/lib/Util.pm
@@ -0,0 +1,275 @@
+# (c) Copyright Elijah Newren 2005
+# (c) Copyright Frederic Peters 2009
+# Licensed under whatever Free/Open Source license is necessary to
+# allow this to be in upstream bugzilla (if they want my ugly hacks)
+# and be the most useful to the Gnome Bugsquad (is there a "please
+# bury this code deep beneath the Ocean's bed and pretend one of our
+# people never wrote it" license?). I give permission to the Gnome
+# Foundation board of directors to declare what that means.
+#
+# Sucks to be you to have to work to figure out the license, doesn't
+# it? Well, better you than me. ;-)
+
+package Bugzilla::Extension::PatchReport::Util;
+
+use strict;
+use base qw(Exporter);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Util;
+use Bugzilla::User;
+
+our @EXPORT = qw(
+ page
+);
+
+sub page {
+ my %params = @_;
+ my ($vars, $page) = @params{qw(vars page_id)};
+ if ($page =~ /^patchreport\./) {
+ _page_patch_report($vars);
+ }
+}
+
+sub _page_patch_report {
+ my $vars = shift;
+
+ my $cgi = Bugzilla->cgi;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+
+ my $quoted_product="'%'"; # (string) which product to search, % for all
+ my $quoted_component="'%'"; # (string) which component to search, % for all
+ my $patch_status="none"; # (string) status of patches to search for
+ my $min_days = -1; # (int) Don't show patches younger than this (in days)
+ my $max_days = -1; # (int) Don't show patches older than this (in days)
+ my $submitter; # (int) submitter id
+
+ if (!$dbh->bz_column_info('attachments', 'status')) {
+ ThrowCodeError('patchreport_no_attachments_status')
+ }
+
+ my @products = $cgi->param('product');
+ my @components = $cgi->param('component');
+
+ @products = grep { defined $_ && $_ ne "" } @products;
+ @components = grep { defined $_ && $_ ne "" } @components;
+
+ if (scalar @products) {
+ $quoted_product = join(',', map($dbh->quote($_), @products));
+ }
+ if (scalar @components) {
+ $quoted_component = join(',', map($dbh->quote($_), @components));
+ }
+
+ if (defined $cgi->param('patch-status') && $cgi->param('patch-status') ne ""){
+ $patch_status = $cgi->param('patch-status');
+ }
+ if (defined $cgi->param('min_days') && $cgi->param('min_days') ne ""){
+ $min_days = $cgi->param('min_days');
+ detaint_natural($min_days) || die "min_days parameter must be a number";
+ }
+ if (defined $cgi->param('max_days') && $cgi->param('max_days') ne ""){
+ $max_days = $cgi->param('max_days');
+ detaint_natural($max_days) || die "max_days parameter must be a number";
+ }
+ if (defined $cgi->param('submitter') && $cgi->param('submitter') ne "") {
+ $submitter = login_to_id($cgi->param('submitter'));
+ unless ($submitter > 0) {
+ ThrowUserError('invalid_username', { name => $cgi->param('submitter') });
+ }
+ }
+
+ # Determine the report type...
+ my $type;
+ if ($patch_status eq "none") {
+ $type = "Unreviewed";
+ }
+ elsif ($patch_status eq "obsolete") {
+ $type = "Obsolete";
+ }
+ else {
+ trick_taint($patch_status);
+ $type = $dbh->selectrow_array(
+ "SELECT value
+ FROM attachment_status
+ WHERE attachment_status.value = ?",
+ undef, $patch_status);
+ }
+
+ #
+ # Then collect the needed information
+ #
+ my $stats = get_unreviewed_patches_and_stats($quoted_product,
+ $quoted_component,
+ $patch_status,
+ $min_days,
+ $max_days,
+ $submitter);
+
+ #
+ # Finally, print it all out
+ #
+ $vars->{'patch_type'} = $type;
+ $vars->{'stats'} = $stats;
+}
+
+
+sub get_unreviewed_patches_and_stats {
+ my ($quoted_product, $quoted_component, $patch_status,
+ $min_days, $max_days, $submitter) = (@_);
+
+ my $query;
+ my $dbh = Bugzilla->dbh;
+
+ $query = " SELECT attachments.attach_id, attachments.bug_id,
+ (" . $dbh->sql_to_days('LOCALTIMESTAMP(0)') . "-" .
+ $dbh->sql_to_days('attachments.creation_ts') . ") AS age,
+ substring(attachments.description, 1, 70),
+ products.name AS product, components.name AS component
+ FROM attachments
+ INNER JOIN bugs
+ ON attachments.bug_id = bugs.bug_id
+ INNER JOIN products
+ ON bugs.product_id = products.id
+ INNER JOIN components
+ ON bugs.component_id = components.id
+ WHERE attachments.ispatch = '1'";
+
+ if ($quoted_product && $quoted_product ne "'%'") {
+ trick_taint($quoted_product);
+ $query .= " AND products.name IN ($quoted_product)";
+ }
+ if ($quoted_component && $quoted_component ne "'%'") {
+ trick_taint($quoted_component);
+ $query .= " AND components.name IN ($quoted_component)";
+ }
+ if ($submitter) {
+ # $submitter is a numeric
+ $query .= " AND attachments.submitter_id = $submitter";
+ }
+ if ($min_days && $min_days != -1) {
+ $query .= " AND attachments.creation_ts <= LOCALTIMESTAMP(0) - " .
+ $dbh->sql_interval($min_days, 'DAY');
+ }
+ if ($max_days && $max_days != -1) {
+ $query .= " AND attachments.creation_ts >= LOCALTIMESTAMP(0) - " .
+ $dbh->sql_interval($max_days, 'DAY');
+ }
+ if ($patch_status eq 'obsolete') {
+ $query .= " AND attachments.isobsolete = '1'";
+ } else {
+ $query .= " AND attachments.isobsolete != '1'";
+ }
+ if ($patch_status ne 'obsolete') {
+ $query .= " AND attachments.status = '" . $patch_status . "'";
+ }
+ $query .= " AND (bugs.bug_status = 'UNCONFIRMED'
+ OR bugs.bug_status = 'NEW'
+ OR bugs.bug_status = 'ASSIGNED'
+ OR bugs.bug_status = 'REOPENED')
+ ORDER BY products.name, components.name, attachments.bug_id, attachments.attach_id";
+ open(BLABLABLA, ">/tmp/foobar") || die "Crap!\n";
+ print BLABLABLA "hello world\n" . $query . "\n";
+
+
+ my $sth = $dbh->prepare($query);
+ $sth->execute();
+
+ $query = "SELECT substring(short_desc, 1, 70), priority, bug_severity
+ FROM bugs
+ WHERE bug_id = ?";
+
+ my $sth_Buginfo = $dbh->prepare($query);
+
+ my ($cur_product, $cur_component, $cur_bug) = ('', '', 0);
+ my ($prod_list, $comp_list, $bug_list, $patch_list) = ([], [], [], []);
+ my ($new_product, $new_component);
+ my ($total_count, $prod_count, $comp_count) = (0, 0, 0);
+ my $stats = {
+ 'count' => 0,
+ 'product_list' => []
+ };
+
+ $prod_list = $stats->{product_list};
+ while (my ($attach_id, $bug_id, $age, $desc, $prod, $comp) = $sth->fetchrow_array) {
+
+ # Check if we've moved on to a new product
+ if ($cur_product ne $prod) {
+ if ($cur_product ne '') {
+ $new_product->{count} = $prod_count;
+ $prod_count = 0;
+ $new_component->{count} = $comp_count;
+ $comp_count = 0;
+ }
+
+ $cur_product = $prod;
+ $new_product = {
+ 'name' => $prod,
+ 'component_list' => []
+ };
+
+ push @{$prod_list}, $new_product;
+ $cur_component = '';
+ $comp_list = $new_product->{component_list};
+ }
+
+ # Check if we've moved on to a new component
+ if ($cur_component ne $comp) {
+ if ($cur_component ne '') {
+ $new_component->{count} = $comp_count;
+ $comp_count = 0;
+ }
+ $cur_component = $comp;
+
+ $new_component = {
+ 'name' => $comp,
+ 'bug_list' => []
+ };
+ push @{$comp_list}, $new_component;
+ $cur_bug = 0;
+ $bug_list = $new_component->{bug_list};
+ }
+
+ # Check if we've moved on to a new bug
+ if ($cur_bug ne $bug_id) {
+ $cur_bug = $bug_id;
+
+ $sth_Buginfo->execute($bug_id);
+ my ($bug_desc, $priority, $severity) = $sth_Buginfo->fetchrow_array;
+
+ my $new_bug = {
+ 'id' => $bug_id,
+ 'summary' => $bug_desc,
+ 'priority' => $priority,
+ 'severity' => $severity,
+ 'patch_list' => []
+ };
+ push @{$bug_list}, $new_bug;
+ $patch_list = $new_bug->{patch_list};
+ }
+
+ my $new_patch = {
+ 'id' => $attach_id,
+ 'age' => $age,
+ 'description' => $desc
+ };
+ push @{$patch_list}, $new_patch;
+
+ $total_count++;
+ $prod_count++;
+ $comp_count++;
+
+ # printf "%6d %6d %s %s %s\n", $attach_id, $bug_id, $prod, $comp, $desc;
+ }
+
+ # Update the counts for the final product and component, as well as the total
+ $stats->{count} = $total_count;
+ $new_product->{count} = $prod_count;
+ $new_component->{count} = $comp_count;
+
+ return $stats;
+}
+
diff --git a/template/en/default/hook/global/code-error-errors.html.tmpl
b/template/en/default/hook/global/code-error-errors.html.tmpl
new file mode 100644
index 0000000..bfc6483
--- /dev/null
+++ b/template/en/default/hook/global/code-error-errors.html.tmpl
@@ -0,0 +1,24 @@
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # The Initial Developer of the Original Code is Everything Solved, Inc.
+ # Portions created by the Initial Developer are Copyright (C) 2010
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Max Kanat-Alexander <mkanat bugzilla org>
+ #%]
+
+[% IF error == "patchreport_no_attachments_status" %]
+ [% title = "Missing $terms.Bugzilla Extension: AttachmentStatus" %]
+ Please have the [% terms.Bugzilla %] administrator install the AttachmentsStatus extension.
+[% END %]
diff --git a/template/en/default/pages/patchreport.html.tmpl b/template/en/default/pages/patchreport.html.tmpl
new file mode 100644
index 0000000..5aacb38
--- /dev/null
+++ b/template/en/default/pages/patchreport.html.tmpl
@@ -0,0 +1,77 @@
+[%# 1 0 bugzilla org %]
+[%# -*- mode: html -*- %]
+[%# The contents of this file are subject to the Mozilla Public
+ # License Version 1.1 (the "License"); you may not use this file
+ # except in compliance with the License. You may obtain a copy of
+ # the License at http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is the Bugzilla Bug Tracking System.
+ #
+ # Copyright (C) 2005 Olav Vitters.
+ #
+ #%]
+
+[%# INTERFACE:
+ # This template has no interface.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% title = "Patch Report" %]
+[% PROCESS global/header.html.tmpl
+ h1 = "" %]
+
+ <center><h1>[% patch_type FILTER html %] Patches</h1></center>
+
+[% FOREACH product = stats.product_list %]
+ <h3>[% product.name FILTER html %]<a name="[% product.name FILTER html %]"></a> ([% product.count FILTER
html %])</h3>
+ <ul>
+
+ [% FOREACH component = product.component_list %]
+ <li>Component: [% component.name FILTER html %] ([% component.count FILTER html %])</li>
+ <ul>
+
+ [% FOREACH bug = component.bug_list %]
+ <li>[% terms.Bug %] <a href="show_bug.cgi?id=[% bug.id FILTER uri %]">[% bug.id FILTER html %]</a>:
+ [% bug.summary FILTER html %] ([% "$bug.priority / $bug.severity" FILTER html %])</li>
+ <ul>
+
+ [% FOREACH patch = bug.patch_list %]
+ <li><i>Attachment [% patch.id FILTER html %]</i> ([% patch.age FILTER html %] days)
+ <a href="attachment.cgi?id=[% patch.id FILTER uri %]&action=diff">
+ [% patch.description FILTER html %]</a>
+ </li>
+ [% END %]
+
+ </ul>
+ [% END %]
+
+ </ul>
+ [% END %]
+ </ul>
+[% END %]
+
+[% IF stats.count > 1 %]
+ <p>[% stats.count FILTER html %] [% type FILTER lower FILTER html %] patches found.</p>
+[% ELSIF stats.count == 1 %]
+ <p>[% stats.count FILTER html %] [% type FILTER lower FILTER html %] patch found.</p>
+[% ELSE %]
+ <p>No patches found matching your criteria.</p>
+[% END %]
+
+<!--
+ SOME USEFUL PARAMETERS TO PASS THIS SCRIPT:
+ product (Only show unreviewed patches in this product)
+ component (Only show unreviewed patches in this component)
+ min_days (Don't show patches younger than this)
+ max_days (Don't show patches older than this)
+ -->
+
+<p> If you spot any errors in this page please report it to the bugzilla component of bugzilla.gnome.org.
Thanks.</p>
+
+[% PROCESS global/footer.html.tmpl %]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]