[bugzilla-gnome-org-extensions] initial import



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 %]&amp;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]