1999-10-12 20:58:11 +04:00
|
|
|
#!/usr/bonsaitools/bin/perl -w
|
|
|
|
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
|
|
|
#
|
|
|
|
# The contents of this file are subject to the Mozilla Public License
|
|
|
|
# Version 1.0 (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.
|
|
|
|
#
|
|
|
|
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
|
|
|
|
# Terry Weissman <terry@mozilla.org>
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# Direct any questions on this source code to
|
|
|
|
#
|
|
|
|
# Holger Schurig <holgerschurig@nikocity.de>
|
|
|
|
#
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# Hey, what's this?
|
|
|
|
#
|
|
|
|
# 'checksetup.pl' is a script that is supposed to run during installation
|
|
|
|
# time and also after every upgrade.
|
|
|
|
#
|
|
|
|
# The goal of this script is to make the installation even more easy.
|
|
|
|
# It does so by doing things for you as well as testing for problems
|
|
|
|
# early.
|
|
|
|
#
|
|
|
|
# And you can re-run it whenever you want. Especially after Bugzilla
|
|
|
|
# get's updated you SHOULD rerun it. Because then it may update your
|
|
|
|
# SQL table definitions so that they are again in sync with the code.
|
|
|
|
#
|
|
|
|
# So, currently this module does:
|
|
|
|
#
|
|
|
|
# - check for required perl modules
|
|
|
|
# - set defaults for local configuration variables
|
|
|
|
# - create and populate the data directory after installation
|
|
|
|
# - set the proper rights for the *.cgi, *.html ... etc files
|
|
|
|
# - check if the code can access MySQL
|
|
|
|
# - creates the database 'bugs' if the database does not exist
|
|
|
|
# - creates the tables inside the database if they don't exist
|
|
|
|
# - automatically changes the table definitions of older BugZilla
|
|
|
|
# installations
|
|
|
|
# - populates the groups
|
1999-10-13 00:28:41 +04:00
|
|
|
# - put the first user into all groups so that the system can
|
|
|
|
# be administrated
|
1999-10-12 20:58:11 +04:00
|
|
|
# - changes already existing SQL tables if you change your local
|
|
|
|
# settings, e.g. when you add a new platform
|
|
|
|
#
|
|
|
|
# People that install this module locally are not supposed to modify
|
|
|
|
# this script. This is done by shifting the user settable stuff intp
|
|
|
|
# a local configuration file 'localconfig'. When this file get's
|
|
|
|
# changed and 'checkconfig.pl' will be re-run, then the user changes
|
|
|
|
# will be reflected back into the database.
|
|
|
|
#
|
|
|
|
# Developers however have to modify this file at various places. To
|
|
|
|
# make this easier, I have added some special comments that one can
|
|
|
|
# search for.
|
|
|
|
#
|
|
|
|
# To Search for
|
|
|
|
#
|
|
|
|
# add/delete local configuration variables --LOCAL--
|
|
|
|
# check for more prerequired modules --MODULES--
|
|
|
|
# change the defaults for local configuration vars --LOCAL--
|
|
|
|
# update the assigned file permissions --CHMOD--
|
|
|
|
# add more MySQL-related checks --MYSQL--
|
|
|
|
# change table definitions --TABLE--
|
|
|
|
# add more groups --GROUPS--
|
|
|
|
#
|
|
|
|
# Note: sometimes those special comments occur more then once. For
|
|
|
|
# example, --LOCAL-- is at least 3 times in this code! --TABLE--
|
|
|
|
# also is used more than once. So search for every occurence!
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Global definitions
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
use diagnostics;
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# This are the --LOCAL-- variables defined in 'localconfig'
|
|
|
|
#
|
|
|
|
|
|
|
|
use vars qw(
|
|
|
|
$webservergroup
|
|
|
|
$db_host $db_port $db_name $db_user
|
1999-10-13 00:28:41 +04:00
|
|
|
@severities @priorities @opsys @platforms
|
1999-10-12 20:58:11 +04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Check required module
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Here we check for --MODULES--
|
|
|
|
#
|
|
|
|
|
|
|
|
print "Checking perl modules ...\n";
|
|
|
|
unless (eval "require 5.004") {
|
|
|
|
die "Sorry, you need at least Perl 5.004\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
unless (eval "require DBI") {
|
|
|
|
die "Please install the DBI module. You can do this by running (as root)\n\n",
|
1999-10-13 00:28:41 +04:00
|
|
|
" perl -MCPAN -eshell\n",
|
|
|
|
" install DBI\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
unless (eval "require Data::Dumper") {
|
|
|
|
die "Please install the Data::Dumper module. You can do this by running (as root)\n\n",
|
1999-10-13 00:28:41 +04:00
|
|
|
" perl -MCPAN -eshell\n",
|
|
|
|
" install Data::Dumper\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
unless (eval "require Mysql") {
|
|
|
|
die "Please install the Mysql database driver. You can do this by running (as root)\n\n",
|
1999-10-13 00:28:41 +04:00
|
|
|
" perl -MCPAN -eshell\n",
|
|
|
|
" install Msql-Mysql\n\n",
|
|
|
|
"Be sure to enable the Mysql emulation!";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
unless (eval "require Date::Parse") {
|
|
|
|
die "Please install the Date::Parse module. You can do this by running (as root)\n\n",
|
1999-10-13 00:28:41 +04:00
|
|
|
" perl -MCPAN -eshell\n",
|
|
|
|
" install Date::Parse\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
# The following two modules are optional:
|
|
|
|
my $charts = 0;
|
|
|
|
$charts++ if eval "require GD";
|
|
|
|
$charts++ if eval "require Chart::Base";
|
|
|
|
if ($charts != 2) {
|
|
|
|
print "If you you want to see graphical bug dependency charts, you may install\n",
|
|
|
|
"the optional libgd and the Perl modules GD and Chart::Base, e.g. by\n",
|
|
|
|
"running (as root)\n\n",
|
|
|
|
" perl -MCPAN -eshell\n",
|
|
|
|
" install GD\n",
|
|
|
|
" install Chart::Base\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Check and update local configuration
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# This is quite tricky. But fun!
|
|
|
|
#
|
|
|
|
# First we read the file 'localconfig'. And then we check if the variables
|
|
|
|
# we need to be defined are defined. If not, localconfig will be amended by
|
|
|
|
# the new settings and the user informed to check this. The program then
|
|
|
|
# stops.
|
|
|
|
#
|
|
|
|
# Why do it this way around?
|
|
|
|
#
|
|
|
|
# Assume we will enhance Bugzilla and eventually more local configuration
|
|
|
|
# stuff arises on the horizon.
|
|
|
|
#
|
|
|
|
# But the file 'localconfig' is not in the Bugzilla CVS or tarfile. It should
|
|
|
|
# not be there so that we never overwrite user's local setups accidentally.
|
|
|
|
# Now, we need a new variable. We simply add the necessary stuff to checksetup.
|
|
|
|
# The user get's the new version of Bugzilla from the CVS, runs checksetup
|
|
|
|
# and checksetup finds out "Oh, there is something new". Then it adds some
|
|
|
|
# default value to the user's local setup and informs the user to check that
|
|
|
|
# to see if that is what the user wants.
|
|
|
|
#
|
|
|
|
# Cute, ey?
|
|
|
|
#
|
|
|
|
|
|
|
|
print "Checking user setup ...\n";
|
|
|
|
do 'localconfig';
|
|
|
|
my $newstuff = "";
|
|
|
|
sub LocalVar ($$)
|
|
|
|
{
|
|
|
|
my ($name, $definition) = @_;
|
|
|
|
|
|
|
|
# Is there a cleaner way to test if the variable defined in scalar $name
|
|
|
|
# is defined or not?
|
|
|
|
my $defined = 0;
|
|
|
|
$_ = "\$defined = 1 if defined $name;";
|
|
|
|
eval $_;
|
|
|
|
return if $defined;
|
|
|
|
|
|
|
|
$newstuff .= " " . $name;
|
|
|
|
open FILE, '>>localconfig';
|
|
|
|
print FILE $definition, "\n\n";
|
|
|
|
close FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Set up the defaults for the --LOCAL-- variables below:
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('$webservergroup', '
|
|
|
|
#
|
|
|
|
# This is the group your web server runs on.
|
|
|
|
# If you have a windows box, ignore this setting.
|
|
|
|
# If you do not wish for checksetup to adjust the permissions of anything,
|
|
|
|
# set this to "".
|
|
|
|
# If you set this to anything besides "", you will need to run checksetup.pl
|
|
|
|
# as root.
|
|
|
|
$webservergroup = "nobody";
|
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('$db_host', '
|
|
|
|
#
|
|
|
|
# How to access the SQL database:
|
|
|
|
#
|
1999-10-13 00:28:41 +04:00
|
|
|
$db_host = "localhost"; # where is the database?
|
|
|
|
$db_port = 3306; # which port to use
|
|
|
|
$db_name = "bugs"; # name of the MySQL database
|
|
|
|
$db_user = "bugs"; # user to attach to the MySQL database
|
1999-10-12 20:58:11 +04:00
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('@severities', '
|
|
|
|
#
|
|
|
|
# Which bug and feature-request severities do you want?
|
|
|
|
#
|
|
|
|
@severities = (
|
1999-10-13 00:28:41 +04:00
|
|
|
"blocker",
|
|
|
|
"critical",
|
|
|
|
"major",
|
|
|
|
"normal",
|
|
|
|
"minor",
|
|
|
|
"trivial",
|
|
|
|
"enhancement"
|
1999-10-12 20:58:11 +04:00
|
|
|
);
|
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('@priorities', '
|
|
|
|
#
|
|
|
|
# Which priorities do you want to assign to bugs and feature-request?
|
|
|
|
#
|
|
|
|
@priorities = (
|
1999-10-13 00:28:41 +04:00
|
|
|
"P1",
|
|
|
|
"P2",
|
|
|
|
"P3",
|
|
|
|
"P4",
|
|
|
|
"P5"
|
1999-10-12 20:58:11 +04:00
|
|
|
);
|
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('@opsys', '
|
|
|
|
#
|
|
|
|
# What operatings systems may your products run on?
|
|
|
|
#
|
|
|
|
@opsys = (
|
1999-10-13 00:28:41 +04:00
|
|
|
"All",
|
|
|
|
"Windows 3.1",
|
|
|
|
"Windows 95",
|
|
|
|
"Windows 98",
|
|
|
|
"Windows NT",
|
|
|
|
"Mac System 7",
|
|
|
|
"Mac System 7.5",
|
|
|
|
"Mac System 7.6.1",
|
|
|
|
"Mac System 8.0",
|
|
|
|
"Mac System 8.5",
|
|
|
|
"Mac System 8.6",
|
|
|
|
"AIX",
|
|
|
|
"BSDI",
|
|
|
|
"HP-UX",
|
|
|
|
"IRIX",
|
|
|
|
"Linux",
|
|
|
|
"FreeBSD",
|
|
|
|
"OSF/1",
|
|
|
|
"Solaris",
|
|
|
|
"SunOS",
|
|
|
|
"Neutrino",
|
|
|
|
"OS/2",
|
|
|
|
"BeOS",
|
|
|
|
"OpenVMS",
|
|
|
|
"other"
|
1999-10-12 20:58:11 +04:00
|
|
|
);
|
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LocalVar('@platforms', '
|
|
|
|
#
|
|
|
|
# What hardware platforms may your products run on?
|
|
|
|
#
|
|
|
|
@platforms = (
|
1999-10-13 00:28:41 +04:00
|
|
|
"All",
|
|
|
|
"DEC",
|
|
|
|
"HP",
|
|
|
|
"Macintosh",
|
|
|
|
"PC",
|
|
|
|
"SGI",
|
|
|
|
"Sun",
|
|
|
|
"Other"
|
1999-10-12 20:58:11 +04:00
|
|
|
);
|
|
|
|
');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ($newstuff ne "") {
|
|
|
|
print "This version of Bugzilla contains some variables that you may \n",
|
1999-10-13 00:28:41 +04:00
|
|
|
"to change and adapt to your local settings. Please edit the file\n",
|
|
|
|
"'localconfig' and return checksetup.pl\n\n",
|
|
|
|
"The following variables are new to localconfig since you last ran\n",
|
|
|
|
"checksetup.pl: $newstuff\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Check data directory
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Create initial --DATA-- directory and make the initial empty files there:
|
|
|
|
#
|
|
|
|
|
|
|
|
unless (-d 'data') {
|
|
|
|
print "Creating data directory ...\n";
|
|
|
|
mkdir 'data', 0770;
|
1999-10-13 00:28:41 +04:00
|
|
|
if ($webservergroup eq "") {
|
|
|
|
chmod 0777, 'data';
|
|
|
|
}
|
1999-10-12 20:58:11 +04:00
|
|
|
open FILE, '>>data/comments'; close FILE;
|
|
|
|
open FILE, '>>data/nomail'; close FILE;
|
|
|
|
open FILE, '>>data/mail'; close FILE;
|
1999-10-13 00:28:41 +04:00
|
|
|
chmod 0666, glob('data/*');
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
# Just to be sure ...
|
|
|
|
unlink "data/versioncache";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Set proper rights
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Here we use --CHMOD-- and friends to set the file permissions
|
|
|
|
#
|
|
|
|
# The rationale is that the web server generally runs as nobody and so the cgi
|
|
|
|
# scripts should not be writable for nobody, otherwise someone may be possible
|
|
|
|
# to change the cgi's when exploiting some security flaw somewhere (not
|
|
|
|
# necessarily in Bugzilla!)
|
|
|
|
#
|
|
|
|
# Also, some *.pl files are executable, some are not.
|
|
|
|
#
|
|
|
|
# +++ Can anybody tell me what a Windows Perl would do with this code?
|
|
|
|
#
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
if ($webservergroup) {
|
1999-10-15 02:32:44 +04:00
|
|
|
mkdir 'shadow', 0770 unless -d 'shadow';
|
1999-10-13 00:28:41 +04:00
|
|
|
# Funny! getgrname returns the GID if fed with NAME ...
|
|
|
|
my $webservergid = getgrnam($webservergroup);
|
|
|
|
chown 0, $webservergid, glob('*');
|
|
|
|
chmod 0640, glob('*');
|
1999-10-12 20:58:11 +04:00
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
chmod 0750, glob('*.cgi'),
|
|
|
|
'processmail',
|
|
|
|
'whineatnews.pl',
|
|
|
|
'collectstats.pl',
|
|
|
|
'checksetup.pl';
|
1999-10-12 20:58:11 +04:00
|
|
|
|
1999-10-15 02:32:44 +04:00
|
|
|
chmod 0770, 'data', 'shadow';
|
1999-10-13 00:28:41 +04:00
|
|
|
chmod 0666, glob('data/*');
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Check MySQL setup
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Check if we have access to --MYSQL--
|
|
|
|
#
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
# This settings are not yet changeable, because other code depends on
|
|
|
|
# the fact that we use MySQL and not, say, PostgreSQL.
|
1999-10-12 20:58:11 +04:00
|
|
|
|
|
|
|
my $db_base = 'mysql';
|
1999-10-13 00:28:41 +04:00
|
|
|
my $db_pass = ''; # Password to attach to the MySQL database
|
1999-10-12 20:58:11 +04:00
|
|
|
|
|
|
|
use DBI;
|
|
|
|
|
|
|
|
# get a handle to the low-level DBD driver
|
|
|
|
my $drh = DBI->install_driver($db_base)
|
|
|
|
or die "Can't connect to the $db_base. Is the database installed and up and running?\n";
|
|
|
|
|
|
|
|
# Do we have the database itself?
|
|
|
|
my @databases = $drh->func($db_host, $db_port, '_ListDBs');
|
|
|
|
unless (grep /^$db_name$/, @databases) {
|
|
|
|
print "Creating database $db_name ...\n";
|
|
|
|
$drh->func('createdb', $db_name, 'admin')
|
1999-10-13 00:28:41 +04:00
|
|
|
or die "The '$db_name' database does not exist. I tried to create the database,\n",
|
|
|
|
"but that didn't work, probably because of access rigths. Read the README\n",
|
|
|
|
"file and the documentation of $db_base to make sure that everything is\n",
|
|
|
|
"set up correctly.\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
# now get a handle to the database:
|
|
|
|
my $connectstring = "dbi:$db_base:$db_name:host=$db_host:port=$db_port";
|
|
|
|
my $dbh = DBI->connect($connectstring, $db_user, $db_pass)
|
|
|
|
or die "Can't connect to the table '$connectstring'.\n",
|
1999-10-13 00:28:41 +04:00
|
|
|
"Have you read Bugzilla's README? Have you read the doc of '$db_name'?\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
|
|
|
|
END { $dbh->disconnect if $dbh }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Table definitions
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# The following hash stores all --TABLE-- definitions. This will be used
|
|
|
|
# to automatically create those tables that don't exist. The code is
|
|
|
|
# safer than the make*.sh shell scripts used to be, because they won't
|
|
|
|
# delete existing tables.
|
|
|
|
#
|
|
|
|
# If you want intentionally do this, yon can always drop a table and re-run
|
|
|
|
# checksetup, e.g. like this:
|
|
|
|
#
|
|
|
|
# $ mysql bugs
|
|
|
|
# mysql> drop table votes;
|
|
|
|
# mysql> exit;
|
|
|
|
# $ ./checksetup.pl
|
|
|
|
#
|
|
|
|
# If you change one of those field definitions, then also go below to the
|
|
|
|
# next occurence of the string --TABLE-- (near the end of this file) to
|
|
|
|
# add the code that updates older installations automatically.
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
my %table;
|
|
|
|
|
|
|
|
$table{bugs_activity} =
|
|
|
|
'bug_id mediumint not null,
|
|
|
|
who mediumint not null,
|
|
|
|
bug_when datetime not null,
|
|
|
|
field varchar(64) not null,
|
|
|
|
oldvalue tinytext,
|
|
|
|
newvalue tinytext,
|
|
|
|
|
|
|
|
index (bug_id),
|
|
|
|
index (bug_when),
|
|
|
|
index (field)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{attachments} =
|
|
|
|
'attach_id mediumint not null auto_increment primary key,
|
|
|
|
bug_id mediumint not null,
|
|
|
|
creation_ts timestamp,
|
|
|
|
description mediumtext not null,
|
|
|
|
mimetype mediumtext not null,
|
|
|
|
ispatch tinyint,
|
|
|
|
filename mediumtext not null,
|
|
|
|
thedata longblob not null,
|
|
|
|
submitter_id mediumint not null,
|
|
|
|
|
|
|
|
index(bug_id),
|
|
|
|
index(creation_ts)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{bugs} =
|
|
|
|
'bug_id mediumint not null auto_increment primary key,
|
|
|
|
groupset bigint not null,
|
|
|
|
assigned_to mediumint not null, # This is a comment.
|
|
|
|
bug_file_loc text,
|
|
|
|
bug_severity enum($severities) not null,
|
|
|
|
bug_status enum("NEW", "ASSIGNED", "REOPENED", "RESOLVED", "VERIFIED", "CLOSED") not null,
|
|
|
|
creation_ts datetime not null,
|
|
|
|
delta_ts timestamp,
|
|
|
|
short_desc mediumtext,
|
|
|
|
long_desc mediumtext,
|
|
|
|
op_sys enum($opsys) not null,
|
|
|
|
priority enum($priorities) not null,
|
|
|
|
product varchar(64) not null,
|
|
|
|
rep_platform enum($platforms),
|
|
|
|
reporter mediumint not null,
|
|
|
|
version varchar(16) not null,
|
|
|
|
component varchar(50) not null,
|
|
|
|
resolution enum("", "FIXED", "INVALID", "WONTFIX", "LATER", "REMIND", "DUPLICATE", "WORKSFORME") not null,
|
|
|
|
target_milestone varchar(20) not null,
|
|
|
|
qa_contact mediumint not null,
|
|
|
|
status_whiteboard mediumtext not null,
|
|
|
|
votes mediumint not null,
|
|
|
|
|
|
|
|
index (assigned_to),
|
|
|
|
index (creation_ts),
|
|
|
|
index (delta_ts),
|
|
|
|
index (bug_severity),
|
|
|
|
index (bug_status),
|
|
|
|
index (op_sys),
|
|
|
|
index (priority),
|
|
|
|
index (product),
|
|
|
|
index (reporter),
|
|
|
|
index (version),
|
|
|
|
index (component),
|
|
|
|
index (resolution),
|
|
|
|
index (target_milestone),
|
|
|
|
index (qa_contact),
|
|
|
|
index (votes)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{cc} =
|
|
|
|
'bug_id mediumint not null,
|
|
|
|
who mediumint not null,
|
|
|
|
|
|
|
|
index(bug_id),
|
|
|
|
index(who)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{components} =
|
|
|
|
'value tinytext,
|
|
|
|
program varchar(64),
|
1999-10-13 00:28:41 +04:00
|
|
|
initialowner tinytext not null, # Should arguably be a mediumint!
|
1999-10-12 20:58:11 +04:00
|
|
|
initialqacontact tinytext not null, # Should arguably be a mediumint!
|
|
|
|
description mediumtext not null';
|
|
|
|
|
|
|
|
|
|
|
|
$table{dependencies} =
|
|
|
|
'blocked mediumint not null,
|
|
|
|
dependson mediumint not null,
|
|
|
|
|
|
|
|
index(blocked),
|
|
|
|
index(dependson)';
|
|
|
|
|
|
|
|
|
|
|
|
# Group bits must be a power of two. Groups are identified by a bit; sets of
|
|
|
|
# groups are indicated by or-ing these values together.
|
|
|
|
#
|
|
|
|
# isbuggroup is nonzero if this is a group that controls access to a set
|
|
|
|
# of bugs. In otherword, the groupset field in the bugs table should only
|
|
|
|
# have this group's bit set if isbuggroup is nonzero.
|
|
|
|
#
|
|
|
|
# User regexp is which email addresses are initially put into this group.
|
|
|
|
# This is only used when an email account is created; otherwise, profiles
|
|
|
|
# may be individually tweaked to add them in and out of groups.
|
|
|
|
|
|
|
|
$table{groups} =
|
|
|
|
'bit bigint not null,
|
|
|
|
name varchar(255) not null,
|
|
|
|
description text not null,
|
|
|
|
isbuggroup tinyint not null,
|
|
|
|
userregexp tinytext not null,
|
|
|
|
|
|
|
|
unique(bit),
|
|
|
|
unique(name)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{logincookies} =
|
|
|
|
'cookie mediumint not null auto_increment primary key,
|
|
|
|
userid mediumint not null,
|
|
|
|
cryptpassword varchar(64),
|
|
|
|
hostname varchar(128),
|
|
|
|
lastused timestamp,
|
|
|
|
|
|
|
|
index(lastused)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{products} =
|
|
|
|
'product varchar(64),
|
|
|
|
description mediumtext,
|
|
|
|
milestoneurl tinytext not null,
|
|
|
|
disallownew tinyint not null,
|
|
|
|
votesperuser smallint not null';
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
$table{profiles} =
|
|
|
|
'userid mediumint not null auto_increment primary key,
|
|
|
|
login_name varchar(255) not null,
|
|
|
|
password varchar(16),
|
|
|
|
cryptpassword varchar(64),
|
|
|
|
realname varchar(255),
|
|
|
|
groupset bigint not null,
|
|
|
|
emailnotification enum("ExcludeSelfChanges", "CConly", "All") not null default "ExcludeSelfChanges",
|
|
|
|
|
|
|
|
index(login_name)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{versions} =
|
|
|
|
'value tinytext,
|
|
|
|
program varchar(64)';
|
|
|
|
|
|
|
|
|
|
|
|
$table{votes} =
|
|
|
|
'who mediumint not null,
|
|
|
|
bug_id mediumint not null,
|
|
|
|
count smallint not null,
|
|
|
|
|
|
|
|
index(who),
|
|
|
|
index(bug_id)';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Create tables
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
# The current DBI::mysql tells me to use this:
|
|
|
|
#my @tables = map { $_ =~ s/.*\.//; $_ } $dbh->tables();
|
|
|
|
# but that doesn't work on a freshly created database, so I still use
|
|
|
|
my @tables = $dbh->func('_ListTables');
|
|
|
|
#print 'Tables: ', join " ", @tables, "\n";
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
# add lines here if you add more --LOCAL-- config vars that end up in the enums:
|
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
my $severities = '"' . join('", "', @severities) . '"';
|
|
|
|
my $priorities = '"' . join('", "', @priorities) . '"';
|
|
|
|
my $opsys = '"' . join('", "', @opsys) . '"';
|
|
|
|
my $platforms = '"' . join('", "', @platforms) . '"';
|
|
|
|
|
|
|
|
# go throught our %table hash and create missing tables
|
|
|
|
while (my ($tabname, $fielddef) = each %table) {
|
|
|
|
next if grep /^$tabname$/, @tables;
|
|
|
|
print "Creating table $tabname ...\n";
|
1999-10-13 00:28:41 +04:00
|
|
|
|
|
|
|
# add lines here if you add more --LOCAL-- config vars that end up in
|
|
|
|
# the enums:
|
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
$fielddef =~ s/\$severities/$severities/;
|
|
|
|
$fielddef =~ s/\$priorities/$priorities/;
|
|
|
|
$fielddef =~ s/\$opsys/$opsys/;
|
|
|
|
$fielddef =~ s/\$platforms/$platforms/;
|
|
|
|
|
|
|
|
$dbh->do("CREATE TABLE $tabname (\n$fielddef\n)")
|
1999-10-13 00:28:41 +04:00
|
|
|
or die "Could not create table '$tabname'. Please check your '$db_base' access.\n";
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Populate groups table
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# This subroutine checks if a group exist. If not, it will be automatically
|
|
|
|
# created with the next available bit set
|
|
|
|
#
|
|
|
|
|
|
|
|
sub AddGroup ($$)
|
|
|
|
{
|
|
|
|
my ($name, $desc) = @_;
|
|
|
|
|
|
|
|
# does the group exist?
|
|
|
|
my $sth = $dbh->prepare("SELECT name FROM groups WHERE name='$name'");
|
|
|
|
$sth->execute;
|
|
|
|
return if $sth->rows;
|
|
|
|
|
|
|
|
# get highest bit number
|
|
|
|
$sth = $dbh->prepare("SELECT bit FROM groups ORDER BY bit DESC");
|
|
|
|
$sth->execute;
|
|
|
|
my @row = $sth->fetchrow_array;
|
|
|
|
|
|
|
|
# normalize bits
|
|
|
|
my $bit;
|
|
|
|
if (defined $row[0]) {
|
1999-10-13 00:28:41 +04:00
|
|
|
$bit = $row[0] << 1;
|
1999-10-12 20:58:11 +04:00
|
|
|
} else {
|
1999-10-13 00:28:41 +04:00
|
|
|
$bit = 1;
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
print "Adding group $name ...\n";
|
|
|
|
$sth = $dbh->prepare('INSERT INTO groups
|
1999-10-13 00:28:41 +04:00
|
|
|
(bit, name, description, userregexp)
|
|
|
|
VALUES (?, ?, ?, ?)');
|
1999-10-12 20:58:11 +04:00
|
|
|
$sth->execute($bit, $name, $desc, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# BugZilla uses --GROUPS-- to assign various rights to it's users.
|
|
|
|
#
|
|
|
|
|
|
|
|
AddGroup 'tweakparams', 'Can tweak operating parameters';
|
|
|
|
AddGroup 'editgroupmembers', 'Can put people in and out of groups that they are members of.';
|
|
|
|
AddGroup 'creategroups', 'Can create and destroy groups.';
|
|
|
|
AddGroup 'editcomponents', 'Can create, destroy, and edit components.';
|
1999-10-13 00:28:41 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Create initial test product if there are no products present.
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
my $sth = $dbh->prepare("SELECT product FROM products");
|
|
|
|
$sth->execute;
|
1999-10-13 00:28:41 +04:00
|
|
|
unless ($sth->rows) {
|
1999-10-12 20:58:11 +04:00
|
|
|
print "Creating initial dummy product 'TestProduct' ...\n";
|
1999-10-13 00:28:41 +04:00
|
|
|
$dbh->do('INSERT INTO products(product, description) VALUES ("TestProduct",
|
1999-10-14 21:34:00 +04:00
|
|
|
"This is a test product. This ought to be blown away and ' .
|
|
|
|
'replaced with real stuff in a finished installation of ' .
|
|
|
|
'bugzilla.")');
|
1999-10-13 00:28:41 +04:00
|
|
|
$dbh->do('INSERT INTO versions (value, program) VALUES ("other", "TestProduct")');
|
1999-10-14 21:34:00 +04:00
|
|
|
$dbh->do('INSERT INTO components (value, program, description) VALUES (' .
|
|
|
|
'"TestComponent", "TestProduct", ' .
|
|
|
|
'"This is a test component in the test product database. ' .
|
|
|
|
'This ought to be blown away and replaced with real stuff in ' .
|
|
|
|
'a finished installation of bugzilla.")');
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
# Detect changed local settings
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Check if the enums in the bugs table return the same values that are defined
|
|
|
|
# in the various locally changeable variables. If this is true, then alter the
|
|
|
|
# table definition.
|
|
|
|
#
|
|
|
|
|
|
|
|
sub GetFieldDef ($$)
|
|
|
|
{
|
|
|
|
my ($table, $field) = @_;
|
|
|
|
my $sth = $dbh->prepare("SHOW COLUMNS FROM $table");
|
|
|
|
$sth->execute;
|
|
|
|
|
|
|
|
while (my $ref = $sth->fetchrow_arrayref) {
|
|
|
|
next if $$ref[0] ne $field;
|
|
|
|
return $ref;
|
1999-10-13 00:28:41 +04:00
|
|
|
}
|
1999-10-12 20:58:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
sub CheckEnumField ($$@)
|
|
|
|
{
|
|
|
|
my ($table, $field, @against) = @_;
|
|
|
|
|
|
|
|
my $ref = GetFieldDef($table, $field);
|
|
|
|
#print "0: $$ref[0] 1: $$ref[1] 2: $$ref[2] 3: $$ref[3] 4: $$ref[4]\n";
|
1999-10-13 00:28:41 +04:00
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
$_ = "enum('" . join("','", @against) . "')";
|
|
|
|
if ($$ref[1] ne $_) {
|
|
|
|
print "Updating field $field in table $table ...\n";
|
|
|
|
$_ .= " NOT NULL" if $$ref[3];
|
|
|
|
$dbh->do("ALTER TABLE $table
|
|
|
|
CHANGE $field
|
|
|
|
$field $_");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# This code changes the enum types of some SQL tables whenever you change
|
|
|
|
# some --LOCAL-- variables
|
|
|
|
#
|
|
|
|
|
|
|
|
CheckEnumField('bugs', 'bug_severity', @severities);
|
|
|
|
CheckEnumField('bugs', 'priority', @priorities);
|
|
|
|
CheckEnumField('bugs', 'op_sys', @opsys);
|
|
|
|
CheckEnumField('bugs', 'rep_platform', @platforms);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
###########################################################################
|
|
|
|
# Promote first user into every group
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# Assume you just logged in. Now how can you administrate the system? Just
|
|
|
|
# execute checksetup.pl again. If there is only 1 user in bugzilla, then
|
|
|
|
# this user is promoted into every group.
|
|
|
|
#
|
|
|
|
|
|
|
|
$sth = $dbh->prepare("SELECT login_name FROM profiles");
|
|
|
|
$sth->execute;
|
|
|
|
# when we have exactly one user ...
|
|
|
|
if ($sth->rows == 1) {
|
|
|
|
my @row = $sth->fetchrow_array;
|
|
|
|
print "Putting user $row[0] into every group ...\n";
|
|
|
|
# are this enought f's for now? :-)
|
|
|
|
$dbh->do("update profiles set groupset=0xffffffffffff");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-10-12 20:58:11 +04:00
|
|
|
###########################################################################
|
|
|
|
# Update the tables to the current definition
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
#
|
|
|
|
# As time passes, fields in tables get deleted, added, changed and so on.
|
|
|
|
# So we need some helper subroutines to make this possible:
|
|
|
|
#
|
|
|
|
|
|
|
|
sub ChangeFieldType ($$$)
|
|
|
|
{
|
|
|
|
my ($table, $field, $newtype) = @_;
|
|
|
|
|
|
|
|
my $ref = GetFieldDef($table, $field);
|
|
|
|
#print "0: $$ref[0] 1: $$ref[1] 2: $$ref[2] 3: $$ref[3] 4: $$ref[4]\n";
|
|
|
|
|
|
|
|
if ($$ref[1] ne $newtype) {
|
|
|
|
print "Updating field type $field in table $table ...\n";
|
|
|
|
$newtype .= " NOT NULL" if $$ref[3];
|
|
|
|
$dbh->do("ALTER TABLE $table
|
|
|
|
CHANGE $field
|
|
|
|
$field $newtype");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub RenameField ($$$)
|
|
|
|
{
|
|
|
|
my ($table, $field, $newname) = @_;
|
|
|
|
|
|
|
|
my $ref = GetFieldDef($table, $field);
|
1999-10-13 00:28:41 +04:00
|
|
|
return unless $ref; # already fixed?
|
1999-10-12 20:58:11 +04:00
|
|
|
#print "0: $$ref[0] 1: $$ref[1] 2: $$ref[2] 3: $$ref[3] 4: $$ref[4]\n";
|
|
|
|
|
|
|
|
if ($$ref[1] ne $newname) {
|
|
|
|
print "Updating field $field in table $table ...\n";
|
|
|
|
my $type = $$ref[1];
|
|
|
|
$type .= " NOT NULL" if $$ref[3];
|
|
|
|
$dbh->do("ALTER TABLE $table
|
|
|
|
CHANGE $field
|
|
|
|
$newname $type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub AddField ($$$)
|
|
|
|
{
|
|
|
|
my ($table, $field, $definition) = @_;
|
|
|
|
|
|
|
|
my $ref = GetFieldDef($table, $field);
|
|
|
|
return if $ref; # already added?
|
|
|
|
|
|
|
|
print "Adding new field $field to table $table ...\n";
|
|
|
|
$dbh->do("ALTER TABLE $table
|
|
|
|
ADD COLUMN $field $definition");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub DropField ($$)
|
|
|
|
{
|
|
|
|
my ($table, $field) = @_;
|
|
|
|
|
|
|
|
my $ref = GetFieldDef($table, $field);
|
|
|
|
return unless $ref; # already dropped?
|
|
|
|
|
|
|
|
print "Deleting unused field $field from table $table ...\n";
|
|
|
|
$dbh->do("ALTER TABLE $table
|
|
|
|
DROP COLUMN $field");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 5/12/99 Added a pref to control how much email you get. This needs a new
|
|
|
|
# column in the profiles table, so feed the following to mysql:
|
|
|
|
|
1999-10-13 00:28:41 +04:00
|
|
|
AddField('profiles', 'emailnotification', 'enum("ExcludeSelfChanges", "CConly",
|
|
|
|
"All") not null default "ExcludeSelfChanges"');
|
1999-10-12 20:58:11 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 6/22/99 Added an entry to the attachments table to record who the
|
|
|
|
# submitter was. Nothing uses this yet, but it still should be recorded.
|
|
|
|
|
|
|
|
AddField('attachments', 'submitter_id', 'mediumint not null');
|
|
|
|
|
|
|
|
#
|
|
|
|
# One could even populate this field automatically, e.g. with
|
|
|
|
#
|
|
|
|
# unless (GetField('attachments', 'submitter_id') {
|
|
|
|
# AddField ...
|
|
|
|
# populate
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# For now I was too lazy, so you should read the README :-)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 9/15/99 Apparently, newer alphas of MySQL won't allow you to have "when"
|
|
|
|
# as a column name. So, I have had to rename a column in the bugs_activity
|
|
|
|
# table. You must feed the below to mysql or you won't work at all.
|
|
|
|
|
|
|
|
RenameField ('bugs', 'when', 'bug_when');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 10/11/99 Restructured voting database to add a cached value in each bug
|
|
|
|
# recording how many total votes that bug has. While I'm at it, I removed
|
|
|
|
# the unused "area" field from the bugs database. It is distressing to
|
|
|
|
# realize that the bugs table has reached the maximum number of indices
|
|
|
|
# allowed by MySQL (16), which may make future enhancements awkward.
|
|
|
|
|
|
|
|
DropField('bugs', 'area');
|
|
|
|
AddField('bugs', 'votes', 'mediumint not null, add index (votes)');
|
|
|
|
AddField('products', 'votesperuser', 'mediumint not null');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The product name used to be very different in various tables.
|
|
|
|
#
|
|
|
|
# It was varchar(16) in bugs
|
|
|
|
# tinytext in components
|
|
|
|
# tinytext in products
|
|
|
|
# tinytext in versions
|
|
|
|
#
|
|
|
|
# tinytext is equivalent to varchar(255), which is quite huge, so I change
|
|
|
|
# them all to varchar(64).
|
|
|
|
|
|
|
|
ChangeFieldType ('bugs', 'product', 'varchar(64)');
|
|
|
|
ChangeFieldType ('components', 'program', 'varchar(64)');
|
|
|
|
ChangeFieldType ('products', 'product', 'varchar(64)');
|
|
|
|
ChangeFieldType ('versions', 'program', 'varchar(64)');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# If you had to change the --TABLE-- definition in any way, then add your
|
|
|
|
# differential change code *** A B O V E *** this comment.
|
|
|
|
#
|
|
|
|
# That is: if you add a new field, you first search for the first occurence
|
|
|
|
# of --TABLE-- and add your field to into the table hash. This new setting
|
|
|
|
# would be honored for every new installation. Then add your
|
|
|
|
# AddField/DropField/ChangeFieldType/RenameField code above. This would then
|
|
|
|
# be honored by everyone who updates his Bugzilla installation.
|
|
|
|
#
|