Commit 589632e9 authored by Frédéric Buclin's avatar Frédéric Buclin

Bug 661476: sanitycheck.pl should check if all products have components defined.

Also, creating a new product from the web UI asks you to create a component too. r=glob a=LpSolit
parent 664920c7
......@@ -155,6 +155,11 @@ sub remove_from_db {
$dbh->bz_start_transaction();
# Products must have at least one component.
if (scalar(@{$self->product->components}) == 1) {
ThrowUserError('component_is_last', { comp => $self });
}
if ($self->bug_count) {
if (Bugzilla->params->{'allowbugdeletion'}) {
require Bugzilla::Bug;
......
......@@ -143,12 +143,21 @@ sub remove_from_db {
my $self = shift;
my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();
# Products must have at least one version.
if (scalar(@{$self->product->versions}) == 1) {
ThrowUserError('version_is_last', { version => $self });
}
# The version cannot be removed if there are bugs
# associated with it.
if ($self->bug_count) {
ThrowUserError("version_has_bugs", { nb => $self->bug_count });
}
$self->SUPER::remove_from_db();
$dbh->bz_commit_transaction();
}
###############################
......
......@@ -37,6 +37,7 @@ use Bugzilla::Util;
use Bugzilla::Error;
use Bugzilla::Group;
use Bugzilla::Product;
use Bugzilla::Component;
use Bugzilla::Classification;
use Bugzilla::Token;
......@@ -176,7 +177,13 @@ if ($action eq 'new') {
check_token_data($token, 'add_product');
my %create_params = (
Bugzilla::User::match_field ({
'initialowner' => { 'type' => 'single' },
'initialqacontact' => { 'type' => 'single' },
'initialcc' => { 'type' => 'multi' },
});
my %product_create_params = (
classification => $classification_name,
name => $product_name,
description => scalar $cgi->param('description'),
......@@ -186,7 +193,23 @@ if ($action eq 'new') {
create_series => scalar $cgi->param('createseries'),
allows_unconfirmed => scalar $cgi->param('allows_unconfirmed'),
);
my $product = Bugzilla::Product->create(\%create_params);
$dbh->bz_start_transaction();
my $product = Bugzilla::Product->create(\%product_create_params);
my @initial_cc = $cgi->param('initialcc');
my %component_create_params = (
product => $product,
name => trim($cgi->param('component') || ''),
description => scalar $cgi->param('comp_desc'),
initialowner => scalar $cgi->param('initialowner'),
initialqacontact => scalar $cgi->param('initialqacontact'),
initial_cc => \@initial_cc,
create_series => scalar $cgi->param('createseries'),
);
Bugzilla::Component->create(\%component_create_params);
$dbh->bz_commit_transaction();
delete_token($token);
......
......@@ -748,6 +748,26 @@ if (scalar(@invalid_flags)) {
}
###########################################################################
# Check for products with no component
###########################################################################
Status('product_check_start');
my $products_missing_data = $dbh->selectcol_arrayref(
'SELECT DISTINCT products.name
FROM products
LEFT JOIN components
ON components.product_id = products.id
LEFT JOIN versions
ON versions.product_id = products.id
WHERE components.id IS NULL
OR versions.id IS NULL');
if (scalar(@$products_missing_data)) {
Status('product_alert', { name => $_ }, 'alert') foreach @$products_missing_data;
}
###########################################################################
# General bug checks
###########################################################################
......
......@@ -22,16 +22,20 @@
# comp: object; Bugzilla::Component object.
#%]
[%# When called from the "New Product" page, the component description field
# must have a name different from the product description field. %]
[% DEFAULT desc_name = "description" %]
<tr>
<td valign="top">Component:</td>
<th align="right">Component:</th>
<td><input size="64" maxlength="64" name="component"
value="[%- comp.name FILTER html %]"></td>
</tr>
<tr>
<td valign="top">Component Description:</td>
<th align="right">Component Description:</th>
<td>
[% INCLUDE global/textarea.html.tmpl
name = 'description'
name = desc_name
minrows = 4
cols = 64
wrap = 'virtual'
......@@ -40,7 +44,7 @@
</td>
</tr>
<tr>
<td valign="top"><label for="initialowner">Default Assignee:</label></td>
<th align="right"><label for="initialowner">Default Assignee:</label></th>
<td>
[% INCLUDE global/userselect.html.tmpl
name => "initialowner"
......@@ -52,7 +56,7 @@
</tr>
[% IF Param('useqacontact') %]
<tr>
<td valign="top"><label for="initialqacontact">Default QA contact:</label></td>
<th align="right"><label for="initialqacontact">Default QA contact:</label></th>
<td>
[% INCLUDE global/userselect.html.tmpl
name => "initialqacontact"
......@@ -65,9 +69,7 @@
</tr>
[% END %]
<tr>
<td valign="top">
<label for="initialcc">Default CC List:</label>
</td>
<th align="right"><label for="initialcc">Default CC List:</label></th>
<td>
[% INCLUDE global/userselect.html.tmpl
name => "initialcc"
......
......@@ -25,7 +25,8 @@
[% PROCESS global/header.html.tmpl
title = title
style_urls = ['skins/standard/admin.css']
javascript_urls = ['js/util.js']
javascript_urls = ['js/util.js', 'js/field.js']
yui = [ 'autocomplete' ]
%]
[% DEFAULT
......@@ -42,7 +43,7 @@
<tr>
<th align="right">Version:</th>
<td><input size="64" maxlength="255" name="version"
<td><input size="20" maxlength="64" name="version"
value="[% version FILTER html %]">
</td>
</tr>
......@@ -52,6 +53,18 @@
<input type="checkbox" name="createseries" value="1" checked="checked">
</td>
</tr>
<tr>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td colspan="2">
This product must have at least one component.
You will be able to create additional components later:
</td>
</tr>
[% PROCESS "admin/components/edit-common.html.tmpl" desc_name = "comp_desc" %]
</table>
<input type="submit" id="add-product" value="Add">
......
......@@ -25,7 +25,7 @@
[% IF Param('useclassification') %]
<tr>
<th align="right"><b>Classification:</b></th>
<th align="right">Classification:</th>
<td><b>[% classification.name FILTER html %]</b></td>
</tr>
[% END %]
......@@ -43,6 +43,23 @@
</td>
</tr>
<tr>
<th align="right">Open for [% terms.bug %] entry:</th>
<td><input type="checkbox" name="is_active" value="1"
[% ' checked="checked"' IF product.is_active %]>
</td>
</tr>
<tr>
<th align="right">
<label for="allows_unconfirmed">Enable the
[%+ display_value('bug_status', 'UNCONFIRMED') FILTER html %] status
in this product:</label>
</th>
<td><input type="checkbox" id="allows_unconfirmed" name="allows_unconfirmed"
[% ' checked="checked"' IF product.allows_unconfirmed %]>
</td>
</tr>
[% IF Param('usetargetmilestone') -%]
<tr>
<th align="right">Default milestone:</th>
......@@ -63,21 +80,4 @@
</tr>
[% END %]
<tr>
<th align="right">Open for [% terms.bug %] entry:</th>
<td><input type="checkbox" name="is_active" value="1"
[% ' checked="checked"' IF product.is_active %]>
</td>
</tr>
<tr>
<th align="right">
<label for="allows_unconfirmed">Enable the
[%+ display_value('bug_status', 'UNCONFIRMED') FILTER html %] status
in this product:</label>
</th>
<td><input type="checkbox" id="allows_unconfirmed" name="allows_unconfirmed"
[% ' checked="checked"' IF product.allows_unconfirmed %]>
</td>
</tr>
[% Hook.process('rows') %]
......@@ -229,6 +229,13 @@
[% ELSIF san_tag == "profile_login_start" %]
Checking profile logins.
[% ELSIF san_tag == "product_alert" %]
Product <a href="editproducts.cgi?product=[% name FILTER html%]">
[%- name FILTER html %]</a> has no components or no versions.
[% ELSIF san_tag == "product_check_start" %]
Checking products with no components or versions.
[% ELSIF san_tag == "profile_login_alert" %]
Bad profile email address, id=[% id FILTER html %],
&lt;[% email FILTER html %]&gt;.
......
......@@ -796,9 +796,7 @@
[% ELSIF message_tag == "product_created" %]
[% title = "Product Created" %]
The product <em>[% product.name FILTER html %]</em> has been created. You will need to
<a href="editcomponents.cgi?action=add&product=[% product.name FILTER uri %]">
add at least one component</a> before anyone can enter [% terms.bugs %] against this product.
The product <em>[% product.name FILTER html %]</em> has been created.
[% ELSIF message_tag == "product_deleted" %]
[% title = "Product Deleted" %]
......
......@@ -373,6 +373,11 @@
You must reassign those [% terms.bugs %] to another component before you
can delete this one.
[% ELSIF error == "component_is_last" %]
[% title = BLOCK %]Last Component in this Product[% END %]
'[% comp.name FILTER html %]' is the last component of the
'[% comp.product.name FILTER html %]' product. You cannot delete it.
[% ELSIF error == "component_name_too_long" %]
[% title = "Component Name Is Too Long" %]
The name of a component is limited to [% constants.MAX_COMPONENT_SIZE FILTER html %]
......@@ -1630,6 +1635,11 @@
version! You must reassign those [% terms.bugs %] to another version
before you can delete this one.
[% ELSIF error == "version_is_last" %]
[% title = BLOCK %]Last Version in this Product[% END %]
'[% version.name FILTER html %]' is the last version of the
'[% version.product.name FILTER html %]' product. You cannot delete it.
[% ELSIF error == "users_deletion_disabled" %]
[% title = "Deletion not activated" %]
[% admindocslinks = {'useradmin.html' => 'User administration'} %]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment