summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rwxr-xr-x[-rw-r--r--]contrib/.cvsignore0
-rwxr-xr-x[-rw-r--r--]contrib/bugzilla-queue0
-rwxr-xr-x[-rw-r--r--]contrib/bugzilla-submit/bugdata.txt0
-rwxr-xr-x[-rw-r--r--]contrib/bugzilla-submit/bugzilla-submit.xml0
-rwxr-xr-x[-rw-r--r--]contrib/cmdline/query.conf0
-rwxr-xr-x[-rw-r--r--]contrib/console.pl0
-rwxr-xr-x[-rw-r--r--]contrib/cvs-update.pl0
-rwxr-xr-x[-rw-r--r--]contrib/extension-convert.pl0
-rwxr-xr-xcontrib/gnats2bz.pl1067
-rwxr-xr-xcontrib/gnatsparse/README62
-rwxr-xr-xcontrib/gnatsparse/gnatsparse.py807
-rwxr-xr-xcontrib/gnatsparse/magic.py712
-rwxr-xr-xcontrib/gnatsparse/specialuu.py104
-rwxr-xr-x[-rw-r--r--]contrib/jb2bz.py0
-rwxr-xr-x[-rw-r--r--]contrib/merge-users.pl0
-rwxr-xr-x[-rw-r--r--]contrib/sendbugmail.pl0
-rwxr-xr-x[-rw-r--r--]contrib/sendunsentbugmail.pl0
-rwxr-xr-x[-rw-r--r--]contrib/yp_nomail.sh0
18 files changed, 0 insertions, 2752 deletions
diff --git a/contrib/.cvsignore b/contrib/.cvsignore
index 03c88fd7a..03c88fd7a 100644..100755
--- a/contrib/.cvsignore
+++ b/contrib/.cvsignore
diff --git a/contrib/bugzilla-queue b/contrib/bugzilla-queue
index 3e00cce24..3e00cce24 100644..100755
--- a/contrib/bugzilla-queue
+++ b/contrib/bugzilla-queue
diff --git a/contrib/bugzilla-submit/bugdata.txt b/contrib/bugzilla-submit/bugdata.txt
index fc880165c..fc880165c 100644..100755
--- a/contrib/bugzilla-submit/bugdata.txt
+++ b/contrib/bugzilla-submit/bugdata.txt
diff --git a/contrib/bugzilla-submit/bugzilla-submit.xml b/contrib/bugzilla-submit/bugzilla-submit.xml
index 5c818e268..5c818e268 100644..100755
--- a/contrib/bugzilla-submit/bugzilla-submit.xml
+++ b/contrib/bugzilla-submit/bugzilla-submit.xml
diff --git a/contrib/cmdline/query.conf b/contrib/cmdline/query.conf
index 87390cd3f..87390cd3f 100644..100755
--- a/contrib/cmdline/query.conf
+++ b/contrib/cmdline/query.conf
diff --git a/contrib/console.pl b/contrib/console.pl
index e9d06cd94..e9d06cd94 100644..100755
--- a/contrib/console.pl
+++ b/contrib/console.pl
diff --git a/contrib/cvs-update.pl b/contrib/cvs-update.pl
index 32cb5861b..32cb5861b 100644..100755
--- a/contrib/cvs-update.pl
+++ b/contrib/cvs-update.pl
diff --git a/contrib/extension-convert.pl b/contrib/extension-convert.pl
index 88718cf83..88718cf83 100644..100755
--- a/contrib/extension-convert.pl
+++ b/contrib/extension-convert.pl
diff --git a/contrib/gnats2bz.pl b/contrib/gnats2bz.pl
deleted file mode 100755
index 27f3ad84a..000000000
--- a/contrib/gnats2bz.pl
+++ /dev/null
@@ -1,1067 +0,0 @@
-#!/usr/bin/perl -w
-# -*- Mode: perl; indent-tabs-mode: nil -*-
-#
-# 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 Gnats To Bugzilla Conversion Utility.
-#
-# The Initial Developer of the Original Code is Tom
-# Schutter. Portions created by Tom Schutter are
-# Copyright (C) 1999 Tom Schutter. All
-# Rights Reserved.
-#
-# Contributor(s): Tom Schutter <tom@platte.com>
-#
-# Perl script to convert a GNATS database to a Bugzilla database.
-# This script generates a file that contains SQL commands for MySQL.
-# This script DOES NOT MODIFY the GNATS database.
-# This script DOES NOT MODIFY the Bugzilla database.
-#
-# Usage procedure:
-# 1) Regenerate the GNATS index file. It sometimes has inconsistencies,
-# and this script relies on it being correct. Use the GNATS command:
-# gen-index --numeric --outfile=$GNATS_DIR/gnats-db/gnats-adm/index
-# 2) Modify variables at the beginning of this script to match
-# what your site requires.
-# 3) Modify translate_pr() and write_bugs() below to fixup mapping from
-# your GNATS policies to Bugzilla. For example, how do the
-# Severity/Priority fields map to bug_severity/priority?
-# 4) Run this script.
-# 5) Fix the problems in the GNATS database identified in the output
-# script file gnats2bz_cleanup.sh. Fixing problems may be a job
-# for a custom perl script. If you make changes to GNATS, goto step 2.
-# 6) Examine the statistics in the output file gnats2bz_stats.txt.
-# These may indicate some more cleanup that is needed. For example,
-# you may find that there are invalid "State"s, or not a consistent
-# scheme for "Release"s. If you make changes to GNATS, goto step 2.
-# 7) Examine the output data file gnats2bz_data.sql. If problems
-# exist, goto step 2.
-# 8) Create a new, empty Bugzilla database.
-# 9) Import the data using the command:
-# mysql -uroot -p'ROOT_PASSWORD' bugs < gnats2bz_data.sql
-# 10) Update the shadow directory with the command:
-# cd $BUGZILLA_DIR; ./processmail regenerate
-# 11) Run a sanity check by visiting the sanitycheck.cgi page.
-# 12) Manually verify that the database is ok. If it is not, goto step 2.
-#
-# Important notes:
-# Confidential is not mapped or exported.
-# Submitter-Id is not mapped or exported.
-#
-# Design decisions:
-# This script generates a SQL script file rather than dumping the data
-# directly into the database. This is to allow the user to check
-# and/or modify the results before they are put into the database.
-# The PR number is very important and must be maintained as the Bugzilla
-# bug number, because there are many references to the PR number, such
-# as in code comments, CVS comments, customer communications, etc.
-# Reading ENUMERATED and TEXT fields:
-# 1) All leading and trailing whitespace is stripped.
-# Reading MULTITEXT fields:
-# 1) All leading blank lines are stripped.
-# 2) All trailing whitespace is stripped.
-# 3) Indentation is preserved.
-# Audit-Trail is not mapped to bugs_activity table, because there
-# is no place to put the "Why" text, which can have a fair amount
-# of information content.
-#
-# 15 January 2002 - changes from Andrea Dell'Amico <adellam@link.it>
-#
-# * Adapted to the new database structure: now long_descs is a
-# separate table.
-# * Set a default for the target milestone, otherwise bugzilla
-# doesn't work with the imported database if milestones are used.
-# * In gnats version 3.113 records are separated by "|" and not ":".
-# * userid "1" is for the bugzilla administrator, so it's better to
-# start from 2.
-#
-
-use strict;
-
-# Suffix to be appended to username to make it an email address.
-my($username_suffix) = "\@platte.com";
-
-# Default organization that should be ignored and not passed on to Bugzilla.
-# Only bugs that are reported outside of the default organization will have
-# their Originator,Organization fields passed on.
-# The assumption here is that if the Organization is identical to the
-# $default_organization, then the Originator will most likely be only an
-# alias for the From field in the mail header.
-my($default_organization) = "Platte River Associates|platte";
-
-# Username for reporter field if unable to determine from mail header
-my($gnats_username) = "gnats\@platte.com";
-
-# Flag indicating if cleanup file should use edit-pr or ${EDITOR}.
-# Using edit-pr is safer, but may be too slow if there are too many
-# PRs that need cleanup. If you use ${EDITOR}, then you must make
-# sure that you have exclusive access to the database, and that you
-# do not screw up any fields.
-my($cleanup_with_edit_pr) = 0;
-
-# Component name and description for bugs imported from GNATS.
-my($default_component) = "GNATS Import";
-my($default_component_description) = "Bugs imported from GNATS.";
-
-# First generated userid. Start from 2: 1 is used for the bugzilla
-# administrator.
-my($userid_base) = 2;
-
-# Output filenames.
-my($cleanup_pathname) = "gnats2bz_cleanup.sh";
-my($stats_pathname) = "gnats2bz_stats.txt";
-my($data_pathname) = "gnats2bz_data.sql";
-
-# List of ENUMERATED and TEXT fields.
-my(@text_fields) = qw(Number Category Synopsis Confidential Severity
- Priority Responsible State Class Submitter-Id
- Arrival-Date Originator Release);
-
-# List of MULTITEXT fields.
-my(@multitext_fields) = qw(Mail-Header Organization Environment Description
- How-To-Repeat Fix Audit-Trail Unformatted);
-
-# List of fields to report statistics for.
-my(@statistics_fields) = qw(Category Confidential Severity Priority
- Responsible State Class Submitter-Id Originator
- Organization Release Environment);
-
-# Array to hold list of GNATS PRs.
-my(@pr_list);
-
-# Array to hold list of GNATS categories.
-my(@categories_list);
-
-# Array to hold list of GNATS responsible users.
-my(@responsible_list);
-
-# Array to hold list of usernames.
-my(@username_list);
-# Put the gnats_username in first.
-get_userid($gnats_username);
-
-# Hash to hold list of versions.
-my(%versions_table);
-
-# Hash to hold contents of PR.
-my(%pr_data);
-
-# String to hold duplicate fields found during read of PR.
-my($pr_data_dup_fields) = "";
-
-# String to hold badly labeled fields found during read of PR.
-# This usually happens when the user does not separate the field name
-# from the field data with whitespace.
-my($pr_data_bad_fields) = " ";
-
-# Hash to hold statistics (note that this a hash of hashes).
-my(%pr_stats);
-
-# Process commmand line.
-my($gnats_db_dir) = @ARGV;
-defined($gnats_db_dir) || die "gnats-db dir not specified";
-(-d $gnats_db_dir) || die "$gnats_db_dir is not a directory";
-
-# Load @pr_list from GNATS index file.
-my($index_pathname) = $gnats_db_dir . "/gnats-adm/index";
-(-f $index_pathname) || die "$index_pathname not found";
-print "Reading $index_pathname...\n";
-if (!load_index($index_pathname)) {
- return(0);
-}
-
-# Load @category_list from GNATS categories file.
-my($categories_pathname) = $gnats_db_dir . "/gnats-adm/categories";
-(-f $categories_pathname) || die "$categories_pathname not found";
-print "Reading $categories_pathname...\n";
-if (!load_categories($categories_pathname)) {
- return(0);
-}
-
-# Load @responsible_list from GNATS responsible file.
-my($responsible_pathname) = $gnats_db_dir . "/gnats-adm/responsible";
-(-f $responsible_pathname) || die "$responsible_pathname not found";
-print "Reading $responsible_pathname...\n";
-if (!load_responsible($responsible_pathname)) {
- return(0);
-}
-
-# Open cleanup file.
-open(CLEANUP, ">$cleanup_pathname") ||
- die "Unable to open $cleanup_pathname: $!";
-chmod(0744, $cleanup_pathname) || warn "Unable to chmod $cleanup_pathname: $!";
-print CLEANUP "#!/bin/sh\n";
-print CLEANUP "# List of PRs that have problems found by gnats2bz.pl.\n";
-
-# Open data file.
-open(DATA, ">$data_pathname") || die "Unable to open $data_pathname: $!";
-print DATA "-- Exported data from $gnats_db_dir by gnats2bz.pl.\n";
-print DATA "-- Load it into a Bugzilla database using the command:\n";
-print DATA "-- mysql -uroot -p'ROOT_PASSWORD' bugs < gnats2bz_data.sql\n";
-print DATA "--\n";
-
-# Loop over @pr_list.
-my($pr);
-foreach $pr (@pr_list) {
- print "Processing $pr...\n";
- if (!read_pr("$gnats_db_dir/$pr")) {
- next;
- }
-
- translate_pr();
-
- check_pr($pr);
-
- collect_stats();
-
- update_versions();
-
- write_bugs();
-
- write_longdescs();
-
-}
-
-write_non_bugs_tables();
-
-close(CLEANUP) || die "Unable to close $cleanup_pathname: $!";
-close(DATA) || die "Unable to close $data_pathname: $!";
-
-print "Generating $stats_pathname...\n";
-report_stats();
-
-sub load_index {
- my($pathname) = @_;
- my($record);
- my(@fields);
-
- open(INDEX, $pathname) || die "Unable to open $pathname: $!";
-
- while ($record = <INDEX>) {
- @fields = split(/\|/, $record);
- push(@pr_list, $fields[0]);
- }
-
- close(INDEX) || die "Unable to close $pathname: $!";
-
- return(1);
-}
-
-sub load_categories {
- my($pathname) = @_;
- my($record);
-
- open(CATEGORIES, $pathname) || die "Unable to open $pathname: $!";
-
- while ($record = <CATEGORIES>) {
- if ($record =~ /^#/) {
- next;
- }
- push(@categories_list, [split(/:/, $record)]);
- }
-
- close(CATEGORIES) || die "Unable to close $pathname: $!";
-
- return(1);
-}
-
-sub load_responsible {
- my($pathname) = @_;
- my($record);
-
- open(RESPONSIBLE, $pathname) || die "Unable to open $pathname: $!";
-
- while ($record = <RESPONSIBLE>) {
- if ($record =~ /^#/) {
- next;
- }
- push(@responsible_list, [split(/\|/, $record)]);
- }
-
- close(RESPONSIBLE) || die "Unable to close $pathname: $!";
-
- return(1);
-}
-
-sub read_pr {
- my($pr_filename) = @_;
- my($multitext) = "Mail-Header";
- my($field, $mail_header);
-
- # Empty the hash.
- %pr_data = ();
-
- # Empty the list of duplicate fields.
- $pr_data_dup_fields = "";
-
- # Empty the list of badly labeled fields.
- $pr_data_bad_fields = "";
-
- unless (open(PR, $pr_filename)) {
- warn "error opening $pr_filename: $!";
- return(0);
- }
-
- LINELOOP: while (<PR>) {
- chomp;
-
- if ($multitext eq "Unformatted") {
- # once we reach "Unformatted", rest of file goes there
- $pr_data{$multitext} = append_multitext($pr_data{$multitext}, $_);
- next LINELOOP;
- }
-
- # Handle ENUMERATED and TEXT fields.
- foreach $field (@text_fields) {
- if (/^>$field:($|\s+)/) {
- $pr_data{$field} = $'; # part of string after match
- $pr_data{$field} =~ s/\s+$//; # strip trailing whitespace
- $multitext = "";
- next LINELOOP;
- }
- }
-
- # Handle MULTITEXT fields.
- foreach $field (@multitext_fields) {
- if (/^>$field:\s*$/) {
- $_ = $'; # set to part of string after match part
- if (defined($pr_data{$field})) {
- if ($pr_data_dup_fields eq "") {
- $pr_data_dup_fields = $field;
- } else {
- $pr_data_dup_fields = "$pr_data_dup_fields $field";
- }
- }
- $pr_data{$field} = $_;
- $multitext = $field;
- next LINELOOP;
- }
- }
-
- # Check for badly labeled fields.
- foreach $field ((@text_fields, @multitext_fields)) {
- if (/^>$field:/) {
- if ($pr_data_bad_fields eq "") {
- $pr_data_bad_fields = $field;
- } else {
- $pr_data_bad_fields = "$pr_data_bad_fields $field";
- }
- }
- }
-
- # Handle continued MULTITEXT field.
- $pr_data{$multitext} = append_multitext($pr_data{$multitext}, $_);
- }
-
- close(PR) || warn "error closing $pr_filename: $!";
-
- # Strip trailing newlines from MULTITEXT fields.
- foreach $field (@multitext_fields) {
- if (defined($pr_data{$field})) {
- $pr_data{$field} =~ s/\s+$//;
- }
- }
-
- return(1);
-}
-
-sub append_multitext {
- my($original, $addition) = @_;
-
- if (defined($original) && $original ne "") {
- return "$original\n$addition";
- } else {
- return $addition;
- }
-}
-
-sub check_pr {
- my($pr) = @_;
- my($error_list) = "";
-
- if ($pr_data_dup_fields ne "") {
- $error_list = append_error($error_list, "Multiple '$pr_data_dup_fields'");
- }
-
- if ($pr_data_bad_fields ne "") {
- $error_list = append_error($error_list, "Bad field labels '$pr_data_bad_fields'");
- }
-
- if (!defined($pr_data{"Description"}) || $pr_data{"Description"} eq "") {
- $error_list = append_error($error_list, "Description empty");
- }
-
- if (defined($pr_data{"Unformatted"}) && $pr_data{"Unformatted"} ne "") {
- $error_list = append_error($error_list, "Unformatted text");
- }
-
- if (defined($pr_data{"Release"}) && length($pr_data{"Release"}) > 16) {
- $error_list = append_error($error_list, "Release > 16 chars");
- }
-
- if (defined($pr_data{"Fix"}) && $pr_data{"Fix"} =~ /State-Changed-/) {
- $error_list = append_error($error_list, "Audit in Fix field");
- }
-
- if (defined($pr_data{"Arrival-Date"})) {
- if ($pr_data{"Arrival-Date"} eq "") {
- $error_list = append_error($error_list, "Arrival-Date empty");
-
- } elsif (unixdate2datetime($pr, $pr_data{"Arrival-Date"}) eq "") {
- $error_list = append_error($error_list, "Arrival-Date format");
- }
- }
-
- # More checks should go here.
-
- if ($error_list ne "") {
- if ($cleanup_with_edit_pr) {
- my(@parts) = split("/", $pr);
- my($pr_num) = $parts[1];
- print CLEANUP "echo \"$error_list\"; edit-pr $pr_num\n";
- } else {
- print CLEANUP "echo \"$error_list\"; \${EDITOR} $pr\n";
- }
- }
-}
-
-sub append_error {
- my($original, $addition) = @_;
-
- if ($original ne "") {
- return "$original, $addition";
- } else {
- return $addition;
- }
-}
-
-sub translate_pr {
- # This function performs GNATS -> Bugzilla translations that should
- # happen before collect_stats().
-
- if (!defined($pr_data{"Organization"})) {
- $pr_data{"Originator"} = "";
- }
- if ($pr_data{"Organization"} =~ /$default_organization/) {
- $pr_data{"Originator"} = "";
- $pr_data{"Organization"} = "";
- }
- $pr_data{"Organization"} =~ s/^\s+//g; # strip leading whitespace
-
- if (!defined($pr_data{"Release"}) ||
- $pr_data{"Release"} eq "" ||
- $pr_data{"Release"} =~ /^unknown-1.0$/
- ) {
- $pr_data{"Release"} = "unknown";
- }
-
- if (defined($pr_data{"Responsible"})) {
- $pr_data{"Responsible"} =~ /\w+/;
- $pr_data{"Responsible"} = "$&$username_suffix";
- }
-
- my($rep_platform, $op_sys) = ("All", "All");
- if (defined($pr_data{"Environment"})) {
- if ($pr_data{"Environment"} =~ /[wW]in.*NT/) {
- $rep_platform = "PC";
- $op_sys = "Windows NT";
- } elsif ($pr_data{"Environment"} =~ /[wW]in.*95/) {
- $rep_platform = "PC";
- $op_sys = "Windows 95";
- } elsif ($pr_data{"Environment"} =~ /[wW]in.*98/) {
- $rep_platform = "PC";
- $op_sys = "Windows 98";
- } elsif ($pr_data{"Environment"} =~ /OSF/) {
- $rep_platform = "DEC";
- $op_sys = "OSF/1";
- } elsif ($pr_data{"Environment"} =~ /AIX/) {
- $rep_platform = "RS/6000";
- $op_sys = "AIX";
- } elsif ($pr_data{"Environment"} =~ /IRIX/) {
- $rep_platform = "SGI";
- $op_sys = "IRIX";
- } elsif ($pr_data{"Environment"} =~ /SunOS.*5\.\d/) {
- $rep_platform = "Sun";
- $op_sys = "Solaris";
- } elsif ($pr_data{"Environment"} =~ /SunOS.*4\.\d/) {
- $rep_platform = "Sun";
- $op_sys = "SunOS";
- }
- }
-
- $pr_data{"Environment"} = "$rep_platform:$op_sys";
-}
-
-sub collect_stats {
- my($field, $value);
-
- foreach $field (@statistics_fields) {
- $value = $pr_data{$field};
- if (!defined($value)) {
- $value = "";
- }
- if (defined($pr_stats{$field}{$value})) {
- $pr_stats{$field}{$value}++;
- } else {
- $pr_stats{$field}{$value} = 1;
- }
- }
-}
-
-sub report_stats {
- my($field, $value, $count);
-
- open(STATS, ">$stats_pathname") ||
- die "Unable to open $stats_pathname: $!";
- print STATS "Statistics of $gnats_db_dir collated by gnats2bz.pl.\n";
-
- my($field_stats);
- while (($field, $field_stats) = each(%pr_stats)) {
- print STATS "\n$field:\n";
- while (($value, $count) = each(%$field_stats)) {
- print STATS " $value: $count\n";
- }
- }
-
- close(STATS) || die "Unable to close $stats_pathname: $!";
-}
-
-sub get_userid {
- my($responsible) = @_;
- my($username, $userid);
-
- if (!defined($responsible)) {
- return(-1);
- }
-
- # Search for current username in the list.
- $userid = $userid_base;
- foreach $username (@username_list) {
- if ($username eq $responsible) {
- return($userid);
- }
- $userid++;
- }
-
- push(@username_list, $responsible);
- return($userid);
-}
-
-sub update_versions {
-
- if (!defined($pr_data{"Release"}) || !defined($pr_data{"Category"})) {
- return;
- }
-
- my($curr_product) = $pr_data{"Category"};
- my($curr_version) = $pr_data{"Release"};
-
- if ($curr_version eq "") {
- return;
- }
-
- if (!defined($versions_table{$curr_product})) {
- $versions_table{$curr_product} = [ ];
- }
-
- my($version_list) = $versions_table{$curr_product};
- my($version);
- foreach $version (@$version_list) {
- if ($version eq $curr_version) {
- return;
- }
- }
-
- push(@$version_list, $curr_version);
-}
-
-sub write_bugs {
- my($bug_id) = $pr_data{"Number"};
-
- my($userid) = get_userid($pr_data{"Responsible"});
-
- # Mapping from Class,Severity to bug_severity
- # At our site, the Severity,Priority fields have degenerated
- # into a 9-level priority field.
- my($bug_severity) = "normal";
- if ($pr_data{"Class"} eq "change-request") {
- $bug_severity = "enhancement";
- } elsif (defined($pr_data{"Synopsis"})) {
- if ($pr_data{"Synopsis"} =~ /crash|assert/i) {
- $bug_severity = "critical";
- } elsif ($pr_data{"Synopsis"} =~ /wrong|error/i) {
- $bug_severity = "major";
- }
- }
- $bug_severity = SqlQuote($bug_severity);
-
- # Mapping from Severity,Priority to priority
- # At our site, the Severity,Priority fields have degenerated
- # into a 9-level priority field.
- my($priority) = "Highest";
- if (defined($pr_data{"Severity"}) && defined($pr_data{"Severity"})) {
- if ($pr_data{"Severity"} eq "critical") {
- if ($pr_data{"Priority"} eq "high") {
- $priority = "Highest";
- } else {
- $priority = "High";
- }
- } elsif ($pr_data{"Severity"} eq "serious") {
- if ($pr_data{"Priority"} eq "low") {
- $priority = "Low";
- } else {
- $priority = "Normal";
- }
- } else {
- if ($pr_data{"Priority"} eq "high") {
- $priority = "Low";
- } else {
- $priority = "Lowest";
- }
- }
- }
- $priority = SqlQuote($priority);
-
- # Map State,Class to bug_status,resolution
- my($bug_status, $resolution);
- if ($pr_data{"State"} eq "open" || $pr_data{"State"} eq "analyzed") {
- $bug_status = "ASSIGNED";
- $resolution = "";
- } elsif ($pr_data{"State"} eq "feedback") {
- $bug_status = "RESOLVED";
- $resolution = "FIXED";
- } elsif ($pr_data{"State"} eq "closed") {
- $bug_status = "CLOSED";
- if (defined($pr_data{"Class"}) && $pr_data{"Class"} =~ /^duplicate/) {
- $resolution = "DUPLICATE";
- } elsif (defined($pr_data{"Class"}) && $pr_data{"Class"} =~ /^mistaken/) {
- $resolution = "INVALID";
- } else {
- $resolution = "FIXED";
- }
- } elsif ($pr_data{"State"} eq "suspended") {
- $bug_status = "RESOLVED";
- $resolution = "WONTFIX";
- } else {
- $bug_status = "NEW";
- $resolution = "";
- }
- $bug_status = SqlQuote($bug_status);
- $resolution = SqlQuote($resolution);
-
- my($creation_ts) = "";
- if (defined($pr_data{"Arrival-Date"}) && $pr_data{"Arrival-Date"} ne "") {
- $creation_ts = unixdate2datetime($bug_id, $pr_data{"Arrival-Date"});
- }
- $creation_ts = SqlQuote($creation_ts);
-
- my($delta_ts) = "";
- if (defined($pr_data{"Audit-Trail"})) {
- # note that (?:.|\n)+ is greedy, so this should match the
- # last Changed-When
- if ($pr_data{"Audit-Trail"} =~ /(?:.|\n)+-Changed-When: (.+)/) {
- $delta_ts = unixdate2timestamp($bug_id, $1);
- }
- }
- if ($delta_ts eq "") {
- if (defined($pr_data{"Arrival-Date"}) && $pr_data{"Arrival-Date"} ne "") {
- $delta_ts = unixdate2timestamp($bug_id, $pr_data{"Arrival-Date"});
- }
- }
- $delta_ts = SqlQuote($delta_ts);
-
- my($short_desc) = SqlQuote($pr_data{"Synopsis"});
-
- my($rep_platform, $op_sys) = split(/\|/, $pr_data{"Environment"});
- $rep_platform = SqlQuote($rep_platform);
- $op_sys = SqlQuote($op_sys);
-
- my($reporter) = get_userid($gnats_username);
- if (
- defined($pr_data{"Mail-Header"}) &&
- $pr_data{"Mail-Header"} =~ /From ([\w.]+\@[\w.]+)/
- ) {
- $reporter = get_userid($1);
- }
-
- my($version) = "";
- if (defined($pr_data{"Release"})) {
- $version = substr($pr_data{"Release"}, 0, 16);
- }
- $version = SqlQuote($version);
-
- my($product) = "";
- if (defined($pr_data{"Category"})) {
- $product = $pr_data{"Category"};
- }
- $product = SqlQuote($product);
-
- my($component) = SqlQuote($default_component);
-
- my($target_milestone) = "0";
- # $target_milestone = SqlQuote($target_milestone);
-
- my($qa_contact) = "0";
-
- # my($bug_file_loc) = "";
- # $bug_file_loc = SqlQuote($bug_file_loc);
-
- # my($status_whiteboard) = "";
- # $status_whiteboard = SqlQuote($status_whiteboard);
-
- print DATA "\ninsert into bugs (\n";
- print DATA " bug_id, assigned_to, bug_severity, priority, bug_status, creation_ts, delta_ts,\n";
- print DATA " short_desc,\n";
- print DATA " rep_platform, op_sys, reporter, version,\n";
- print DATA " product, component, resolution, target_milestone, qa_contact\n";
- print DATA ") values (\n";
- print DATA " $bug_id, $userid, $bug_severity, $priority, $bug_status, $creation_ts, $delta_ts,\n";
- print DATA " $short_desc,\n";
- print DATA " $rep_platform, $op_sys, $reporter, $version,\n";
- print DATA " $product, $component, $resolution, $target_milestone, $qa_contact\n";
- print DATA ");\n";
-}
-
-sub write_longdescs {
-
- my($bug_id) = $pr_data{"Number"};
- my($who) = get_userid($pr_data{"Responsible"});;
- my($bug_when) = "";
- if (defined($pr_data{"Arrival-Date"}) && $pr_data{"Arrival-Date"} ne "") {
- $bug_when = unixdate2datetime($bug_id, $pr_data{"Arrival-Date"});
- }
- $bug_when = SqlQuote($bug_when);
- my($thetext) = $pr_data{"Description"};
- if (defined($pr_data{"How-To-Repeat"}) && $pr_data{"How-To-Repeat"} ne "") {
- $thetext =
- $thetext . "\n\nHow-To-Repeat:\n" . $pr_data{"How-To-Repeat"};
- }
- if (defined($pr_data{"Fix"}) && $pr_data{"Fix"} ne "") {
- $thetext = $thetext . "\n\nFix:\n" . $pr_data{"Fix"};
- }
- if (defined($pr_data{"Originator"}) && $pr_data{"Originator"} ne "") {
- $thetext = $thetext . "\n\nOriginator:\n" . $pr_data{"Originator"};
- }
- if (defined($pr_data{"Organization"}) && $pr_data{"Organization"} ne "") {
- $thetext = $thetext . "\n\nOrganization:\n" . $pr_data{"Organization"};
- }
- if (defined($pr_data{"Audit-Trail"}) && $pr_data{"Audit-Trail"} ne "") {
- $thetext = $thetext . "\n\nAudit-Trail:\n" . $pr_data{"Audit-Trail"};
- }
- if (defined($pr_data{"Unformatted"}) && $pr_data{"Unformatted"} ne "") {
- $thetext = $thetext . "\n\nUnformatted:\n" . $pr_data{"Unformatted"};
- }
- $thetext = SqlQuote($thetext);
-
- print DATA "\ninsert into longdescs (\n";
- print DATA " bug_id, who, bug_when, thetext\n";
- print DATA ") values (\n";
- print DATA " $bug_id, $who, $bug_when, $thetext\n";
- print DATA ");\n";
-
-}
-
-sub write_non_bugs_tables {
-
- my($categories_record);
- foreach $categories_record (@categories_list) {
- my($component) = SqlQuote($default_component);
- my($product) = SqlQuote(@$categories_record[0]);
- my($description) = SqlQuote(@$categories_record[1]);
- my($initialowner) = SqlQuote(@$categories_record[2] . $username_suffix);
-
- print DATA "\ninsert into products (\n";
- print DATA
- " product, description, milestoneurl, isactive\n";
- print DATA ") values (\n";
- print DATA
- " $product, $description, '', 1\n";
- print DATA ");\n";
-
- print DATA "\ninsert into components (\n";
- print DATA
- " value, program, initialowner, initialqacontact, description\n";
- print DATA ") values (\n";
- print DATA
- " $component, $product, $initialowner, '', $description\n";
- print DATA ");\n";
-
- print DATA "\ninsert into milestones (\n";
- print DATA
- " value, product, sortkey\n";
- print DATA ") values (\n";
- print DATA
- " 0, $product, 0\n";
- print DATA ");\n";
- }
-
- my($username);
- my($userid) = $userid_base;
- my($password) = "password";
- my($realname);
- my($groupset) = 0;
- foreach $username (@username_list) {
- $realname = map_username_to_realname($username);
- $username = SqlQuote($username);
- $realname = SqlQuote($realname);
- print DATA "\ninsert into profiles (\n";
- print DATA
- " userid, login_name, cryptpassword, realname, groupset\n";
- print DATA ") values (\n";
- print DATA
- " $userid, $username, encrypt('$password'), $realname, $groupset\n";
- print DATA ");\n";
- $userid++;
- }
-
- my($product);
- my($version_list);
- while (($product, $version_list) = each(%versions_table)) {
- $product = SqlQuote($product);
-
- my($version);
- foreach $version (@$version_list) {
- $version = SqlQuote($version);
-
- print DATA "\ninsert into versions (value, program) ";
- print DATA "values ($version, $product);\n";
- }
- }
-
-}
-
-sub map_username_to_realname() {
- my($username) = @_;
- my($name, $realname);
-
- # get the portion before the @
- $name = $username;
- $name =~ s/\@.*//;
-
- my($responsible_record);
- foreach $responsible_record (@responsible_list) {
- if (@$responsible_record[0] eq $name) {
- return(@$responsible_record[1]);
- }
- if (defined(@$responsible_record[2])) {
- if (@$responsible_record[2] eq $username) {
- return(@$responsible_record[1]);
- }
- }
- }
-
- return("");
-}
-
-sub detaint_string {
- my ($str) = @_;
- $str =~ m/^(.*)$/s;
- $str = $1;
-}
-
-sub SqlQuote {
- my ($str) = (@_);
- $str =~ s/([\\\'])/\\$1/g;
- $str =~ s/\0/\\0/g;
- # If it's been SqlQuote()ed, then it's safe, so we tell -T that.
- $str = detaint_string($str);
- return "'$str'";
-}
-
-sub unixdate2datetime {
- my($bugid, $unixdate) = @_;
- my($year, $month, $day, $hour, $min, $sec);
-
- if (!split_unixdate($bugid, $unixdate, \$year, \$month, \$day, \$hour, \$min, \$sec)) {
- return("");
- }
-
- return("$year-$month-$day $hour:$min:$sec");
-}
-
-sub unixdate2timestamp {
- my($bugid, $unixdate) = @_;
- my($year, $month, $day, $hour, $min, $sec);
-
- if (!split_unixdate($bugid, $unixdate, \$year, \$month, \$day, \$hour, \$min, \$sec)) {
- return("");
- }
-
- return("$year$month$day$hour$min$sec");
-}
-
-sub split_unixdate {
- # "Tue Jun 6 14:50:00 1995"
- # "Mon Nov 20 17:03:11 [MST] 1995"
- # "12/13/94"
- # "jan 1, 1995"
- my($bugid, $unixdate, $year, $month, $day, $hour, $min, $sec) = @_;
- my(@parts);
-
- $$hour = "00";
- $$min = "00";
- $$sec = "00";
-
- @parts = split(/ +/, $unixdate);
- if (@parts >= 5) {
- # year
- $$year = $parts[4];
- if ($$year =~ /[A-Z]{3}/) {
- # Must be timezone, try next field.
- $$year = $parts[5];
- }
- if ($$year =~ /\D/) {
- warn "$bugid: Error processing year part '$$year' of date '$unixdate'\n";
- return(0);
- }
- if ($$year < 30) {
- $$year = "20" . $$year;
- } elsif ($$year < 100) {
- $$year = "19" . $$year;
- } elsif ($$year < 1970 || $$year > 2029) {
- warn "$bugid: Error processing year part '$$year' of date '$unixdate'\n";
- return(0);
- }
-
- # month
- $$month = $parts[1];
- if ($$month =~ /\D/) {
- if (!month2number($month)) {
- warn "$bugid: Error processing month part '$$month' of date '$unixdate'\n";
- return(0);
- }
-
- } elsif ($$month < 1 || $$month > 12) {
- warn "$bugid: Error processing month part '$$month' of date '$unixdate'\n";
- return(0);
-
- } elsif (length($$month) == 1) {
- $$month = "0" . $$month;
- }
-
- # day
- $$day = $parts[2];
- if ($$day < 1 || $$day > 31) {
- warn "$bugid: Error processing day part '$day' of date '$unixdate'\n";
- return(0);
-
- } elsif (length($$day) == 1) {
- $$day = "0" . $$day;
- }
-
- @parts = split(/:/, $parts[3]);
- $$hour = $parts[0];
- $$min = $parts[1];
- $$sec = $parts[2];
-
- return(1);
-
- } elsif (@parts == 3) {
- # year
- $$year = $parts[2];
- if ($$year =~ /\D/) {
- warn "$bugid: Error processing year part '$$year' of date '$unixdate'\n";
- return(0);
- }
- if ($$year < 30) {
- $$year = "20" . $$year;
- } elsif ($$year < 100) {
- $$year = "19" . $$year;
- } elsif ($$year < 1970 || $$year > 2029) {
- warn "$bugid: Error processing year part '$$year' of date '$unixdate'\n";
- return(0);
- }
-
- # month
- $$month = $parts[0];
- if ($$month =~ /\D/) {
- if (!month2number($month)) {
- warn "$bugid: Error processing month part '$$month' of date '$unixdate'\n";
- return(0);
- }
-
- } elsif ($$month < 1 || $$month > 12) {
- warn "$bugid: Error processing month part '$$month' of date '$unixdate'\n";
- return(0);
-
- } elsif (length($$month) == 1) {
- $$month = "0" . $$month;
- }
-
- # day
- $$day = $parts[1];
- $$day =~ s/,//;
- if ($$day < 1 || $$day > 31) {
- warn "$bugid: Error processing day part '$day' of date '$unixdate'\n";
- return(0);
-
- } elsif (length($$day) == 1) {
- $$day = "0" . $$day;
- }
-
- return(1);
- }
-
- @parts = split(/:/, $unixdate);
- if (@parts == 3 && length($unixdate) <= 8) {
- $$year = "19" . $parts[2];
-
- $$month = $parts[0];
- if (length($$month) == 1) {
- $$month = "0" . $$month;
- }
-
- $$day = $parts[1];
- if (length($$day) == 1) {
- $$day = "0" . $$day;
- }
-
- return(1);
- }
-
- warn "$bugid: Error processing date '$unixdate'\n";
- return(0);
-}
-
-sub month2number {
- my($month) = @_;
-
- if ($$month =~ /jan/i) {
- $$month = "01";
- } elsif ($$month =~ /feb/i) {
- $$month = "02";
- } elsif ($$month =~ /mar/i) {
- $$month = "03";
- } elsif ($$month =~ /apr/i) {
- $$month = "04";
- } elsif ($$month =~ /may/i) {
- $$month = "05";
- } elsif ($$month =~ /jun/i) {
- $$month = "06";
- } elsif ($$month =~ /jul/i) {
- $$month = "07";
- } elsif ($$month =~ /aug/i) {
- $$month = "08";
- } elsif ($$month =~ /sep/i) {
- $$month = "09";
- } elsif ($$month =~ /oct/i) {
- $$month = "10";
- } elsif ($$month =~ /nov/i) {
- $$month = "11";
- } elsif ($$month =~ /dec/i) {
- $$month = "12";
- } else {
- return(0);
- }
-
- return(1);
-}
-
diff --git a/contrib/gnatsparse/README b/contrib/gnatsparse/README
deleted file mode 100755
index f7cf01c68..000000000
--- a/contrib/gnatsparse/README
+++ /dev/null
@@ -1,62 +0,0 @@
-gnatsparse
-==========
-
-Author: Daniel Berlin <dan@dberlin.org>
-
-gnatsparse is a simple Python program that imports a GNATS database
-into a Bugzilla system. It is based on the gnats2bz.pl Perl script
-but it's a rewrite at the same time. Its parser is based on gnatsweb,
-which gives a 10 times speed improvement compared to the previous code.
-
-Features
---------
-
-* Chunks audit trail into separate comments, with the right From's, times, etc.
-
-* Handles followup emails that are in the report, with the right From's, times,
-etc.
-
-* Properly handles duplicates, adding the standard bugzilla duplicate message.
-
-* Extracts and handles gnatsweb attachments, as well as uuencoded attachments
-appearing in either followup emails, the how-to-repeat field, etc. Replaces
-them with a message to look at the attachments list, and adds the standard
-"Created an attachment" message that bugzilla uses. Handling them includes
-giving them the right name and mime-type. "attachments" means multiple
-uuencoded things/gnatsweb attachments are handled properly.
-
-* Handles reopened bug reports.
-
-* Builds the cc list from the people who have commented on the report,
-and the reporter.
-
-Requirements
-------------
-
-It requires python 2.2+, it won't work with 1.5.2 (Linux distributions
-ship with 2.2+ these days, so that shouldn't be an issue).
-
-Documentation
--------------
-
-Documentation can be found inside the scripts. The source code is self
-documenting.
-
-Issues for someone trying to use it to convert a gnats install
------------------------------------
-
-1. We have three custom fields bugzilla doesn't ship with,
-gcchost, gcctarget, and gccbuild.
-We removed two bugzilla fields, rep_platform and op_sys.
-If you use the latter instead of the former, you'll need to
-update the script to account for this.
-2. Because gcc attachments consist of preprocessed source, all attachments
-inserted into the attachment database are compressed with zlib.compress.
-This requires associated bugzilla changes to decompress before sending to
-the browser.
-Unless you want to make those changes (it's roughly 3 lines), you'll
-need to remove the zlib.compress call.
-3. You will need to come up with your own release to version mapping and
-install it.
-4. Obviously, any extra gnats fields you have added will have to
-be handled in some manner.
diff --git a/contrib/gnatsparse/gnatsparse.py b/contrib/gnatsparse/gnatsparse.py
deleted file mode 100755
index 9eef18b89..000000000
--- a/contrib/gnatsparse/gnatsparse.py
+++ /dev/null
@@ -1,807 +0,0 @@
-try:
-# Using Psyco makes it about 25% faster, but there's a bug in psyco in
-# handling of eval causing it to use unlimited memory with the magic
-# file enabled.
-# import psyco
-# psyco.full()
-# from psyco.classes import *
- pass
-except:
- pass
-import re
-import base64
-import cStringIO
-import specialuu
-import array
-import email.Utils
-import zlib
-import magic
-
-# Comment out if you don't want magic detection
-magicf = magic.MagicFile()
-
-# Open our output file
-outfile = open("gnats2bz_data.sql", "w")
-
-# List of GNATS fields
-fieldnames = ("Number", "Category", "Synopsis", "Confidential", "Severity",
- "Priority", "Responsible", "State", "Quarter", "Keywords",
- "Date-Required", "Class", "Submitter-Id", "Arrival-Date",
- "Closed-Date", "Last-Modified", "Originator", "Release",
- "Organization", "Environment", "Description", "How-To-Repeat",
- "Fix", "Release-Note", "Audit-Trail", "Unformatted")
-
-# Dictionary telling us which GNATS fields are multiline
-multilinefields = {"Organization":1, "Environment":1, "Description":1,
- "How-To-Repeat":1, "Fix":1, "Release-Note":1,
- "Audit-Trail":1, "Unformatted":1}
-
-# Mapping of GCC release to version. Our version string is updated every
-# so we need to funnel all release's with 3.4 in the string to be version
-# 3.4 for bug tracking purposes
-# The key is a regex to match, the value is the version it corresponds
-# with
-releasetovermap = {r"3\.4":"3.4", r"3\.3":"3.3", r"3\.2\.2":"3.2.2",
- r"3\.2\.1":"3.2.1", r"3\.2":"3.2", r"3\.1\.2":"3.1.2",
- r"3\.1\.1":"3.1.1", r"3\.1":"3.1", r"3\.0\.4":"3.0.4",
- r"3\.0\.3":"3.0.3", r"3\.0\.2":"3.0.2", r"3\.0\.1":"3.0.1",
- r"3\.0":"3.0", r"2\.95\.4":"2.95.4", r"2\.95\.3":"2.95.3",
- r"2\.95\.2":"2.95.2", r"2\.95\.1":"2.95.1",
- r"2\.95":"2.95", r"2\.97":"2.97",
- r"2\.96.*[rR][eE][dD].*[hH][aA][tT]":"2.96 (redhat)",
- r"2\.96":"2.96"}
-
-# These map the field name to the field id bugzilla assigns. We need
-# the id when doing bug activity.
-fieldids = {"State":8, "Responsible":15}
-
-# These are the keywords we use in gcc bug tracking. They are transformed
-# into bugzilla keywords. The format here is <keyword>-><bugzilla keyword id>
-keywordids = {"wrong-code":1, "ice-on-legal-code":2, "ice-on-illegal-code":3,
- "rejects-legal":4, "accepts-illegal":5, "pessimizes-code":6}
-
-# Map from GNATS states to Bugzilla states. Duplicates and reopened bugs
-# are handled when parsing the audit trail, so no need for them here.
-state_lookup = {"":"NEW", "open":"ASSIGNED", "analyzed":"ASSIGNED",
- "feedback":"WAITING", "closed":"CLOSED",
- "suspended":"SUSPENDED"}
-
-# Table of versions that exist in the bugs, built up as we go along
-versions_table = {}
-
-# Delimiter gnatsweb uses for attachments
-attachment_delimiter = "----gnatsweb-attachment----\n"
-
-# Here starts the various regular expressions we use
-# Matches an entire GNATS single line field
-gnatfieldre = re.compile(r"""^([>\w\-]+)\s*:\s*(.*)\s*$""")
-
-# Matches the name of a GNATS field
-fieldnamere = re.compile(r"""^>(.*)$""")
-
-# Matches the useless part of an envelope
-uselessre = re.compile(r"""^(\S*?):\s*""", re.MULTILINE)
-
-# Matches the filename in a content disposition
-dispositionre = re.compile("(\\S+);\\s*filename=\"([^\"]+)\"")
-
-# Matches the last changed date in the entire text of a bug
-# If you have other editable fields that get audit trail entries, modify this
-# The field names are explicitly listed in order to speed up matching
-lastdatere = re.compile(r"""^(?:(?:State|Responsible|Priority|Severity)-Changed-When: )(.+?)$""", re.MULTILINE)
-
-# Matches the From line of an email or the first line of an audit trail entry
-# We use this re to find the begin lines of all the audit trail entries
-# The field names are explicitly listed in order to speed up matching
-fromtore=re.compile(r"""^(?:(?:State|Responsible|Priority|Severity)-Changed-From-To: |From: )""", re.MULTILINE)
-
-# These re's match the various parts of an audit trail entry
-changedfromtore=re.compile(r"""^(\w+?)-Changed-From-To: (.+?)$""", re.MULTILINE)
-changedbyre=re.compile(r"""^\w+?-Changed-By: (.+?)$""", re.MULTILINE)
-changedwhenre=re.compile(r"""^\w+?-Changed-When: (.+?)$""", re.MULTILINE)
-changedwhyre=re.compile(r"""^\w+?-Changed-Why:\s*(.*?)$""", re.MULTILINE)
-
-# This re matches audit trail text saying that the current bug is a duplicate of another
-duplicatere=re.compile(r"""(?:")?Dup(?:licate)?(?:d)?(?:")? of .*?(\d+)""", re.IGNORECASE | re.MULTILINE)
-
-# Get the text of a From: line
-fromre=re.compile(r"""^From: (.*?)$""", re.MULTILINE)
-
-# Get the text of a Date: Line
-datere=re.compile(r"""^Date: (.*?)$""", re.MULTILINE)
-
-# Map of the responsible file to email addresses
-responsible_map = {}
-# List of records in the responsible file
-responsible_list = []
-# List of records in the categories file
-categories_list = []
-# List of pr's in the index
-pr_list = []
-# Map usernames to user ids
-usermapping = {}
-# Start with this user id
-userid_base = 2
-
-# Name of gnats user
-gnats_username = "gnats@gcc.gnu.org"
-# Name of unassigned user
-unassigned_username = "unassigned@gcc.gnu.org"
-
-gnats_db_dir = "."
-product = "gcc"
-productdesc = "GNU Compiler Connection"
-milestoneurl = "http://gcc/gnu.org"
-defaultmilestone = "3.4"
-
-def write_non_bug_tables():
- """ Write out the non-bug related tables, such as products, profiles, etc."""
- # Set all non-unconfirmed bugs's everconfirmed flag
- print >>outfile, "update bugs set everconfirmed=1 where bug_status != 'UNCONFIRMED';"
-
- # Set all bugs assigned to the unassigned user to NEW
- print >>outfile, "update bugs set bug_status='NEW',assigned_to='NULL' where bug_status='ASSIGNED' AND assigned_to=3;"
-
- # Insert the products
- print >>outfile, "\ninsert into products ("
- print >>outfile, " product, description, milestoneurl, isactive,"
- print >>outfile, " defaultmilestone, votestoconfirm) values ("
- print >>outfile, " '%s', '%s', '%s', 1, '%s', 1);" % (product,
- productdesc,
- milestoneurl,
- defaultmilestone)
-
- # Insert the components
- for category in categories_list:
- component = SqlQuote(category[0])
- productstr = SqlQuote(product)
- description = SqlQuote(category[1])
- initialowner = SqlQuote("3")
- print >>outfile, "\ninsert into components (";
- print >>outfile, " value, program, initialowner, initialqacontact,"
- print >>outfile, " description) values ("
- print >>outfile, " %s, %s, %s, '', %s);" % (component, productstr,
- initialowner, description)
-
- # Insert the versions
- for productstr, version_list in versions_table.items():
- productstr = SqlQuote(productstr)
- for version in version_list:
- version = SqlQuote(version)
- print >>outfile, "\ninsert into versions (value, program) "
- print >>outfile, " values (%s, %s);" % (version, productstr)
-
- # Insert the users
- for username, userid in usermapping.items():
- realname = map_username_to_realname(username)
- username = SqlQuote(username)
- realname = SqlQuote(realname)
- print >>outfile, "\ninsert into profiles ("
- print >>outfile, " userid, login_name, password, cryptpassword, realname, groupset"
- print >>outfile, ") values ("
- print >>outfile, "%s,%s,'password',encrypt('password'), %s, 0);" % (userid, username, realname)
- print >>outfile, "update profiles set groupset=1 << 32 where login_name like '%\@gcc.gnu.org';"
-
-def unixdate2datetime(unixdate):
- """ Convert a unix date to a datetime value """
- year, month, day, hour, min, sec, x, x, x, x = email.Utils.parsedate_tz(unixdate)
- return "%d-%02d-%02d %02d:%02d:%02d" % (year,month,day,hour,min,sec)
-
-def unixdate2timestamp(unixdate):
- """ Convert a unix date to a timestamp value """
- year, month, day, hour, min, sec, x, x, x, x = email.Utils.parsedate_tz(unixdate)
- return "%d%02d%02d%02d%02d%02d" % (year,month,day,hour,min,sec)
-
-def SqlQuote(str):
- """ Perform SQL quoting on a string """
- return "'%s'" % str.replace("'", """''""").replace("\\", "\\\\").replace("\0","\\0")
-
-def convert_gccver_to_ver(gccver):
- """ Given a gcc version, convert it to a Bugzilla version. """
- for k in releasetovermap.keys():
- if re.search(".*%s.*" % k, gccver) is not None:
- return releasetovermap[k]
- result = re.search(r""".*(\d\.\d) \d+ \(experimental\).*""", gccver)
- if result is not None:
- return result.group(1)
- return "unknown"
-
-def load_index(fname):
- """ Load in the GNATS index file """
- global pr_list
- ifp = open(fname)
- for record in ifp.xreadlines():
- fields = record.split("|")
- pr_list.append(fields[0])
- ifp.close()
-
-def load_categories(fname):
- """ Load in the GNATS categories file """
- global categories_list
- cfp = open(fname)
- for record in cfp.xreadlines():
- if re.search("^#", record) is not None:
- continue
- categories_list.append(record.split(":"))
- cfp.close()
-
-def map_username_to_realname(username):
- """ Given a username, find the real name """
- name = username
- name = re.sub("@.*", "", name)
- for responsible_record in responsible_list:
- if responsible_record[0] == name:
- return responsible_record[1]
- if len(responsible_record) > 2:
- if responsible_record[2] == username:
- return responsible_record[1]
- return ""
-
-
-def get_userid(responsible):
- """ Given an email address, get the user id """
- global responsible_map
- global usermapping
- global userid_base
- if responsible is None:
- return -1
- responsible = responsible.lower()
- responsible = re.sub("sources.redhat.com", "gcc.gnu.org", responsible)
- if responsible_map.has_key(responsible):
- responsible = responsible_map[responsible]
- if usermapping.has_key(responsible):
- return usermapping[responsible]
- else:
- usermapping[responsible] = userid_base
- userid_base += 1
- return usermapping[responsible]
-
-def load_responsible(fname):
- """ Load in the GNATS responsible file """
- global responsible_map
- global responsible_list
- rfp = open(fname)
- for record in rfp.xreadlines():
- if re.search("^#", record) is not None:
- continue
- split_record = record.split(":")
- responsible_map[split_record[0]] = split_record[2].rstrip()
- responsible_list.append(record.split(":"))
- rfp.close()
-
-def split_csl(list):
- """ Split a comma separated list """
- newlist = re.split(r"""\s*,\s*""", list)
- return newlist
-
-def fix_email_addrs(addrs):
- """ Perform various fixups and cleaning on an e-mail address """
- addrs = split_csl(addrs)
- trimmed_addrs = []
- for addr in addrs:
- addr = re.sub(r"""\(.*\)""","",addr)
- addr = re.sub(r""".*<(.*)>.*""","\\1",addr)
- addr = addr.rstrip()
- addr = addr.lstrip()
- trimmed_addrs.append(addr)
- addrs = ", ".join(trimmed_addrs)
- return addrs
-
-class Bugzillabug(object):
- """ Class representing a bugzilla bug """
- def __init__(self, gbug):
- """ Initialize a bugzilla bug from a GNATS bug. """
- self.bug_id = gbug.bug_id
- self.long_descs = []
- self.bug_ccs = [get_userid("gcc-bugs@gcc.gnu.org")]
- self.bug_activity = []
- self.attachments = gbug.attachments
- self.gnatsfields = gbug.fields
- self.need_unformatted = gbug.has_unformatted_attach == 0
- self.need_unformatted &= gbug.fields.has_key("Unformatted")
- self.translate_pr()
- self.update_versions()
- if self.fields.has_key("Audit-Trail"):
- self.parse_audit_trail()
- self.write_bug()
-
- def parse_fromto(type, string):
- """ Parses the from and to parts of a changed-from-to line """
- fromstr = ""
- tostr = ""
-
- # Some slightly messed up changed lines have unassigned-new,
- # instead of unassigned->new. So we make the > optional.
- result = re.search(r"""(.*)-(?:>?)(.*)""", string)
-
- # Only know how to handle parsing of State and Responsible
- # changed-from-to right now
- if type == "State":
- fromstr = state_lookup[result.group(1)]
- tostr = state_lookup[result.group(2)]
- elif type == "Responsible":
- if result.group(1) != "":
- fromstr = result.group(1)
- if result.group(2) != "":
- tostr = result.group(2)
- if responsible_map.has_key(fromstr):
- fromstr = responsible_map[fromstr]
- if responsible_map.has_key(tostr):
- tostr = responsible_map[tostr]
- return (fromstr, tostr)
- parse_fromto = staticmethod(parse_fromto)
-
- def parse_audit_trail(self):
- """ Parse a GNATS audit trail """
- trail = self.fields["Audit-Trail"]
- # Begin to split the audit trail into pieces
- result = fromtore.finditer(trail)
- starts = []
- ends = []
- pieces = []
- # Make a list of the pieces
- for x in result:
- pieces.append (x)
- # Find the start and end of each piece
- if len(pieces) > 0:
- for x in xrange(len(pieces)-1):
- starts.append(pieces[x].start())
- ends.append(pieces[x+1].start())
- starts.append(pieces[-1].start())
- ends.append(len(trail))
- pieces = []
- # Now make the list of actual text of the pieces
- for x in xrange(len(starts)):
- pieces.append(trail[starts[x]:ends[x]])
- # And parse the actual pieces
- for piece in pieces:
- result = changedfromtore.search(piece)
- # See what things we actually have inside this entry, and
- # handle them appropriately
- if result is not None:
- type = result.group(1)
- changedfromto = result.group(2)
- # If the bug was reopened, mark it as such
- if changedfromto.find("closed->analyzed") != -1:
- if self.fields["bug_status"] == "'NEW'":
- self.fields["bug_status"] = "'REOPENED'"
- if type == "State" or type == "Responsible":
- oldstate, newstate = self.parse_fromto (type, changedfromto)
- result = changedbyre.search(piece)
- if result is not None:
- changedby = result.group(1)
- result = changedwhenre.search(piece)
- if result is not None:
- changedwhen = result.group(1)
- changedwhen = unixdate2datetime(changedwhen)
- changedwhen = SqlQuote(changedwhen)
- result = changedwhyre.search(piece)
- changedwhy = piece[result.start(1):]
- #changedwhy = changedwhy.lstrip()
- changedwhy = changedwhy.rstrip()
- changedby = get_userid(changedby)
- # Put us on the cc list if we aren't there already
- if changedby != self.fields["userid"] \
- and changedby not in self.bug_ccs:
- self.bug_ccs.append(changedby)
- # If it's a duplicate, mark it as such
- result = duplicatere.search(changedwhy)
- if result is not None:
- newtext = "*** This bug has been marked as a duplicate of %s ***" % result.group(1)
- newtext = SqlQuote(newtext)
- self.long_descs.append((self.bug_id, changedby,
- changedwhen, newtext))
- self.fields["bug_status"] = "'RESOLVED'"
- self.fields["resolution"] = "'DUPLICATE'"
- self.fields["userid"] = changedby
- else:
- newtext = "%s-Changed-From-To: %s\n%s-Changed-Why: %s\n" % (type, changedfromto, type, changedwhy)
- newtext = SqlQuote(newtext)
- self.long_descs.append((self.bug_id, changedby,
- changedwhen, newtext))
- if type == "State" or type == "Responsible":
- newstate = SqlQuote("%s" % newstate)
- oldstate = SqlQuote("%s" % oldstate)
- fieldid = fieldids[type]
- self.bug_activity.append((newstate, oldstate, fieldid, changedby, changedwhen))
-
- else:
- # It's an email
- result = fromre.search(piece)
- if result is None:
- continue
- fromstr = result.group(1)
- fromstr = fix_email_addrs(fromstr)
- fromstr = get_userid(fromstr)
- result = datere.search(piece)
- if result is None:
- continue
- datestr = result.group(1)
- datestr = SqlQuote(unixdate2timestamp(datestr))
- if fromstr != self.fields["userid"] \
- and fromstr not in self.bug_ccs:
- self.bug_ccs.append(fromstr)
- self.long_descs.append((self.bug_id, fromstr, datestr,
- SqlQuote(piece)))
-
-
-
- def write_bug(self):
- """ Output a bug to the data file """
- fields = self.fields
- print >>outfile, "\ninsert into bugs("
- print >>outfile, " bug_id, assigned_to, bug_severity, priority, bug_status, creation_ts, delta_ts,"
- print >>outfile, " short_desc,"
- print >>outfile, " reporter, version,"
- print >>outfile, " product, component, resolution, target_milestone, qa_contact,"
- print >>outfile, " gccbuild, gcctarget, gcchost, keywords"
- print >>outfile, " ) values ("
- print >>outfile, "%s, %s, %s, %s, %s, %s, %s," % (self.bug_id, fields["userid"], fields["bug_severity"], fields["priority"], fields["bug_status"], fields["creation_ts"], fields["delta_ts"])
- print >>outfile, "%s," % (fields["short_desc"])
- print >>outfile, "%s, %s," % (fields["reporter"], fields["version"])
- print >>outfile, "%s, %s, %s, %s, 0," %(fields["product"], fields["component"], fields["resolution"], fields["target_milestone"])
- print >>outfile, "%s, %s, %s, %s" % (fields["gccbuild"], fields["gcctarget"], fields["gcchost"], fields["keywords"])
- print >>outfile, ");"
- if self.fields["keywords"] != 0:
- print >>outfile, "\ninsert into keywords (bug_id, keywordid) values ("
- print >>outfile, " %s, %s);" % (self.bug_id, fields["keywordid"])
- for id, who, when, text in self.long_descs:
- print >>outfile, "\ninsert into longdescs ("
- print >>outfile, " bug_id, who, bug_when, thetext) values("
- print >>outfile, " %s, %s, %s, %s);" % (id, who, when, text)
- for name, data, who in self.attachments:
- print >>outfile, "\ninsert into attachments ("
- print >>outfile, " bug_id, filename, description, mimetype, ispatch, submitter_id) values ("
- ftype = None
- # It's *magic*!
- if name.endswith(".ii") == 1:
- ftype = "text/x-c++"
- elif name.endswith(".i") == 1:
- ftype = "text/x-c"
- else:
- ftype = magicf.detect(cStringIO.StringIO(data))
- if ftype is None:
- ftype = "application/octet-stream"
-
- print >>outfile, "%s,%s,%s, %s,0, %s,%s);" %(self.bug_id, SqlQuote(name), SqlQuote(name), SqlQuote (ftype), who)
- print >>outfile, "\ninsert into attach_data ("
- print >>outfile, "\n(id, thedata) values (last_insert_id(),"
- print >>outfile, "%s);" % (SqlQuote(zlib.compress(data)))
- for newstate, oldstate, fieldid, changedby, changedwhen in self.bug_activity:
- print >>outfile, "\ninsert into bugs_activity ("
- print >>outfile, " bug_id, who, bug_when, fieldid, added, removed) values ("
- print >>outfile, " %s, %s, %s, %s, %s, %s);" % (self.bug_id,
- changedby,
- changedwhen,
- fieldid,
- newstate,
- oldstate)
- for cc in self.bug_ccs:
- print >>outfile, "\ninsert into cc(bug_id, who) values (%s, %s);" %(self.bug_id, cc)
- def update_versions(self):
- """ Update the versions table to account for the version on this bug """
- global versions_table
- if self.fields.has_key("Release") == 0 \
- or self.fields.has_key("Category") == 0:
- return
- curr_product = "gcc"
- curr_version = self.fields["Release"]
- if curr_version == "":
- return
- curr_version = convert_gccver_to_ver (curr_version)
- if versions_table.has_key(curr_product) == 0:
- versions_table[curr_product] = []
- for version in versions_table[curr_product]:
- if version == curr_version:
- return
- versions_table[curr_product].append(curr_version)
- def translate_pr(self):
- """ Transform a GNATS PR into a Bugzilla bug """
- self.fields = self.gnatsfields
- if (self.fields.has_key("Organization") == 0) \
- or self.fields["Organization"].find("GCC"):
- self.fields["Originator"] = ""
- self.fields["Organization"] = ""
- self.fields["Organization"].lstrip()
- if (self.fields.has_key("Release") == 0) \
- or self.fields["Release"] == "" \
- or self.fields["Release"].find("unknown-1.0") != -1:
- self.fields["Release"]="unknown"
- if self.fields.has_key("Responsible"):
- result = re.search(r"""\w+""", self.fields["Responsible"])
- self.fields["Responsible"] = "%s%s" % (result.group(0), "@gcc.gnu.org")
- self.fields["gcchost"] = ""
- self.fields["gcctarget"] = ""
- self.fields["gccbuild"] = ""
- if self.fields.has_key("Environment"):
- result = re.search("^host: (.+?)$", self.fields["Environment"],
- re.MULTILINE)
- if result is not None:
- self.fields["gcchost"] = result.group(1)
- result = re.search("^target: (.+?)$", self.fields["Environment"],
- re.MULTILINE)
- if result is not None:
- self.fields["gcctarget"] = result.group(1)
- result = re.search("^build: (.+?)$", self.fields["Environment"],
- re.MULTILINE)
- if result is not None:
- self.fields["gccbuild"] = result.group(1)
- self.fields["userid"] = get_userid(self.fields["Responsible"])
- self.fields["bug_severity"] = "normal"
- if self.fields["Class"] == "change-request":
- self.fields["bug_severity"] = "enhancement"
- elif self.fields.has_key("Severity"):
- if self.fields["Severity"] == "critical":
- self.fields["bug_severity"] = "critical"
- elif self.fields["Severity"] == "serious":
- self.fields["bug_severity"] = "major"
- elif self.fields.has_key("Synopsis"):
- if re.search("crash|assert", self.fields["Synopsis"]):
- self.fields["bug_severity"] = "critical"
- elif re.search("wrong|error", self.fields["Synopsis"]):
- self.fields["bug_severity"] = "major"
- self.fields["bug_severity"] = SqlQuote(self.fields["bug_severity"])
- self.fields["keywords"] = 0
- if keywordids.has_key(self.fields["Class"]):
- self.fields["keywords"] = self.fields["Class"]
- self.fields["keywordid"] = keywordids[self.fields["Class"]]
- self.fields["keywords"] = SqlQuote(self.fields["keywords"])
- self.fields["priority"] = "P1"
- if self.fields.has_key("Severity") and self.fields.has_key("Priority"):
- severity = self.fields["Severity"]
- priority = self.fields["Priority"]
- if severity == "critical":
- if priority == "high":
- self.fields["priority"] = "Highest"
- else:
- self.fields["priority"] = "High"
- elif severity == "serious":
- if priority == "low":
- self.fields["priority"] = "Low"
- else:
- self.fields["priority"] = "Normal"
- else:
- if priority == "high":
- self.fields["priority"] = "Low"
- else:
- self.fields["priority"] = "Lowest"
- self.fields["priority"] = SqlQuote(self.fields["priority"])
- state = self.fields["State"]
- if (state == "open" or state == "analyzed") and self.fields["userid"] != 3:
- self.fields["bug_status"] = "ASSIGNED"
- self.fields["resolution"] = ""
- elif state == "feedback":
- self.fields["bug_status"] = "WAITING"
- self.fields["resolution"] = ""
- elif state == "closed":
- self.fields["bug_status"] = "CLOSED"
- if self.fields.has_key("Class"):
- theclass = self.fields["Class"]
- if theclass.find("duplicate") != -1:
- self.fields["resolution"]="DUPLICATE"
- elif theclass.find("mistaken") != -1:
- self.fields["resolution"]="INVALID"
- else:
- self.fields["resolution"]="FIXED"
- else:
- self.fields["resolution"]="FIXED"
- elif state == "suspended":
- self.fields["bug_status"] = "SUSPENDED"
- self.fields["resolution"] = ""
- elif state == "analyzed" and self.fields["userid"] == 3:
- self.fields["bug_status"] = "NEW"
- self.fields["resolution"] = ""
- else:
- self.fields["bug_status"] = "UNCONFIRMED"
- self.fields["resolution"] = ""
- self.fields["bug_status"] = SqlQuote(self.fields["bug_status"])
- self.fields["resolution"] = SqlQuote(self.fields["resolution"])
- self.fields["creation_ts"] = ""
- if self.fields.has_key("Arrival-Date") and self.fields["Arrival-Date"] != "":
- self.fields["creation_ts"] = unixdate2datetime(self.fields["Arrival-Date"])
- self.fields["creation_ts"] = SqlQuote(self.fields["creation_ts"])
- self.fields["delta_ts"] = ""
- if self.fields.has_key("Audit-Trail"):
- result = lastdatere.findall(self.fields["Audit-Trail"])
- result.reverse()
- if len(result) > 0:
- self.fields["delta_ts"] = unixdate2timestamp(result[0])
- if self.fields["delta_ts"] == "":
- if self.fields.has_key("Arrival-Date") and self.fields["Arrival-Date"] != "":
- self.fields["delta_ts"] = unixdate2timestamp(self.fields["Arrival-Date"])
- self.fields["delta_ts"] = SqlQuote(self.fields["delta_ts"])
- self.fields["short_desc"] = SqlQuote(self.fields["Synopsis"])
- if self.fields.has_key("Reply-To") and self.fields["Reply-To"] != "":
- self.fields["reporter"] = get_userid(self.fields["Reply-To"])
- elif self.fields.has_key("Mail-Header"):
- result = re.search(r"""From .*?([\w.]+@[\w.]+)""", self.fields["Mail-Header"])
- if result:
- self.fields["reporter"] = get_userid(result.group(1))
- else:
- self.fields["reporter"] = get_userid(gnats_username)
- else:
- self.fields["reporter"] = get_userid(gnats_username)
- long_desc = self.fields["Description"]
- long_desc2 = ""
- for field in ["Release", "Environment", "How-To-Repeat"]:
- if self.fields.has_key(field) and self.fields[field] != "":
- long_desc += ("\n\n%s:\n" % field) + self.fields[field]
- if self.fields.has_key("Fix") and self.fields["Fix"] != "":
- long_desc2 = "Fix:\n" + self.fields["Fix"]
- if self.need_unformatted == 1 and self.fields["Unformatted"] != "":
- long_desc += "\n\nUnformatted:\n" + self.fields["Unformatted"]
- if long_desc != "":
- self.long_descs.append((self.bug_id, self.fields["reporter"],
- self.fields["creation_ts"],
- SqlQuote(long_desc)))
- if long_desc2 != "":
- self.long_descs.append((self.bug_id, self.fields["reporter"],
- self.fields["creation_ts"],
- SqlQuote(long_desc2)))
- for field in ["gcchost", "gccbuild", "gcctarget"]:
- self.fields[field] = SqlQuote(self.fields[field])
- self.fields["version"] = ""
- if self.fields["Release"] != "":
- self.fields["version"] = convert_gccver_to_ver (self.fields["Release"])
- self.fields["version"] = SqlQuote(self.fields["version"])
- self.fields["product"] = SqlQuote("gcc")
- self.fields["component"] = "invalid"
- if self.fields.has_key("Category"):
- self.fields["component"] = self.fields["Category"]
- self.fields["component"] = SqlQuote(self.fields["component"])
- self.fields["target_milestone"] = "---"
- if self.fields["version"].find("3.4") != -1:
- self.fields["target_milestone"] = "3.4"
- self.fields["target_milestone"] = SqlQuote(self.fields["target_milestone"])
- if self.fields["userid"] == 2:
- self.fields["userid"] = "\'NULL\'"
-
-class GNATSbug(object):
- """ Represents a single GNATS PR """
- def __init__(self, filename):
- self.attachments = []
- self.has_unformatted_attach = 0
- fp = open (filename)
- self.fields = self.parse_pr(fp.xreadlines())
- self.bug_id = int(self.fields["Number"])
- if self.fields.has_key("Unformatted"):
- self.find_gnatsweb_attachments()
- if self.fields.has_key("How-To-Repeat"):
- self.find_regular_attachments("How-To-Repeat")
- if self.fields.has_key("Fix"):
- self.find_regular_attachments("Fix")
-
- def get_attacher(fields):
- if fields.has_key("Reply-To") and fields["Reply-To"] != "":
- return get_userid(fields["Reply-To"])
- else:
- result = None
- if fields.has_key("Mail-Header"):
- result = re.search(r"""From .*?([\w.]+\@[\w.]+)""",
- fields["Mail-Header"])
- if result is not None:
- reporter = get_userid(result.group(1))
- else:
- reporter = get_userid(gnats_username)
- get_attacher = staticmethod(get_attacher)
- def find_regular_attachments(self, which):
- fields = self.fields
- while re.search("^begin [0-7]{3}", fields[which],
- re.DOTALL | re.MULTILINE):
- outfp = cStringIO.StringIO()
- infp = cStringIO.StringIO(fields[which])
- filename, start, end = specialuu.decode(infp, outfp, quiet=0)
- fields[which]=fields[which].replace(fields[which][start:end],
- "See attachments for %s\n" % filename)
- self.attachments.append((filename, outfp.getvalue(),
- self.get_attacher(fields)))
-
- def decode_gnatsweb_attachment(self, attachment):
- result = re.split(r"""\n\n""", attachment, 1)
- if len(result) == 1:
- return -1
- envelope, body = result
- envelope = uselessre.split(envelope)
- envelope.pop(0)
- # Turn the list of key, value into a dict of key => value
- attachinfo = dict([(envelope[i], envelope[i+1]) for i in xrange(0,len(envelope),2)])
- for x in attachinfo.keys():
- attachinfo[x] = attachinfo[x].rstrip()
- if (attachinfo.has_key("Content-Type") == 0) or \
- (attachinfo.has_key("Content-Disposition") == 0):
- raise ValueError, "Unable to parse file attachment"
- result = dispositionre.search(attachinfo["Content-Disposition"])
- filename = result.group(2)
- filename = re.sub(".*/","", filename)
- filename = re.sub(".*\\\\","", filename)
- attachinfo["filename"]=filename
- result = re.search("""(\S+);.*""", attachinfo["Content-Type"])
- if result is not None:
- attachinfo["Content-Type"] = result.group(1)
- if attachinfo.has_key("Content-Transfer-Encoding"):
- if attachinfo["Content-Transfer-Encoding"] == "base64":
- attachinfo["data"] = base64.decodestring(body)
- else:
- attachinfo["data"]=body
-
- return (attachinfo["filename"], attachinfo["data"],
- self.get_attacher(self.fields))
-
- def find_gnatsweb_attachments(self):
- fields = self.fields
- attachments = re.split(attachment_delimiter, fields["Unformatted"])
- fields["Unformatted"] = attachments.pop(0)
- for attachment in attachments:
- result = self.decode_gnatsweb_attachment (attachment)
- if result != -1:
- self.attachments.append(result)
- self.has_unformatted_attach = 1
- def parse_pr(lines):
- #fields = {"envelope":[]}
- fields = {"envelope":array.array("c")}
- hdrmulti = "envelope"
- for line in lines:
- line = line.rstrip('\n')
- line += '\n'
- result = gnatfieldre.search(line)
- if result is None:
- if hdrmulti != "":
- if fields.has_key(hdrmulti):
- #fields[hdrmulti].append(line)
- fields[hdrmulti].fromstring(line)
- else:
- #fields[hdrmulti] = [line]
- fields[hdrmulti] = array.array("c", line)
- continue
- hdr, arg = result.groups()
- ghdr = "*not valid*"
- result = fieldnamere.search(hdr)
- if result != None:
- ghdr = result.groups()[0]
- if ghdr in fieldnames:
- if multilinefields.has_key(ghdr):
- hdrmulti = ghdr
- #fields[ghdr] = [""]
- fields[ghdr] = array.array("c")
- else:
- hdrmulti = ""
- #fields[ghdr] = [arg]
- fields[ghdr] = array.array("c", arg)
- elif hdrmulti != "":
- #fields[hdrmulti].append(line)
- fields[hdrmulti].fromstring(line)
- if hdrmulti == "envelope" and \
- (hdr == "Reply-To" or hdr == "From" \
- or hdr == "X-GNATS-Notify"):
- arg = fix_email_addrs(arg)
- #fields[hdr] = [arg]
- fields[hdr] = array.array("c", arg)
- if fields.has_key("Reply-To") and len(fields["Reply-To"]) > 0:
- fields["Reply-To"] = fields["Reply-To"]
- else:
- fields["Reply-To"] = fields["From"]
- if fields.has_key("From"):
- del fields["From"]
- if fields.has_key("X-GNATS-Notify") == 0:
- fields["X-GNATS-Notify"] = array.array("c")
- #fields["X-GNATS-Notify"] = ""
- for x in fields.keys():
- fields[x] = fields[x].tostring()
- #fields[x] = "".join(fields[x])
- for x in fields.keys():
- if multilinefields.has_key(x):
- fields[x] = fields[x].rstrip()
-
- return fields
- parse_pr = staticmethod(parse_pr)
-load_index("%s/gnats-adm/index" % gnats_db_dir)
-load_categories("%s/gnats-adm/categories" % gnats_db_dir)
-load_responsible("%s/gnats-adm/responsible" % gnats_db_dir)
-get_userid(gnats_username)
-get_userid(unassigned_username)
-for x in pr_list:
- print "Processing %s..." % x
- a = GNATSbug ("%s/%s" % (gnats_db_dir, x))
- b = Bugzillabug(a)
-write_non_bug_tables()
-outfile.close()
diff --git a/contrib/gnatsparse/magic.py b/contrib/gnatsparse/magic.py
deleted file mode 100755
index 049a7e19b..000000000
--- a/contrib/gnatsparse/magic.py
+++ /dev/null
@@ -1,712 +0,0 @@
-# Found on a russian zope mailing list, and modified to fix bugs in parsing
-# the magic file and string making
-# -- Daniel Berlin <dberlin@dberlin.org>
-import sys, struct, time, re, exceptions, pprint, stat, os, pwd, grp
-
-_mew = 0
-
-# _magic='/tmp/magic'
-# _magic='/usr/share/magic.mime'
-_magic='/usr/share/magic.mime'
-mime = 1
-
-_ldate_adjust = lambda x: time.mktime( time.gmtime(x) )
-
-BUFFER_SIZE = 1024 * 128 # 128K should be enough...
-
-class MagicError(exceptions.Exception): pass
-
-def _handle(fmt='@x',adj=None): return fmt, struct.calcsize(fmt), adj
-
-KnownTypes = {
- # 'byte':_handle('@b'),
- 'byte':_handle('@B'),
- 'ubyte':_handle('@B'),
-
- 'string':('s',0,None),
- 'pstring':_handle('p'),
-
-# 'short':_handle('@h'),
-# 'beshort':_handle('>h'),
-# 'leshort':_handle('<h'),
- 'short':_handle('@H'),
- 'beshort':_handle('>H'),
- 'leshort':_handle('<H'),
- 'ushort':_handle('@H'),
- 'ubeshort':_handle('>H'),
- 'uleshort':_handle('<H'),
-
- 'long':_handle('@l'),
- 'belong':_handle('>l'),
- 'lelong':_handle('<l'),
- 'ulong':_handle('@L'),
- 'ubelong':_handle('>L'),
- 'ulelong':_handle('<L'),
-
- 'date':_handle('=l'),
- 'bedate':_handle('>l'),
- 'ledate':_handle('<l'),
- 'ldate':_handle('=l',_ldate_adjust),
- 'beldate':_handle('>l',_ldate_adjust),
- 'leldate':_handle('<l',_ldate_adjust),
-}
-
-_mew_cnt = 0
-def mew(x):
- global _mew_cnt
- if _mew :
- if x=='.' :
- _mew_cnt += 1
- if _mew_cnt % 64 == 0 : sys.stderr.write( '\n' )
- sys.stderr.write( '.' )
- else:
- sys.stderr.write( '\b'+x )
-
-def has_format(s):
- n = 0
- l = None
- for c in s :
- if c == '%' :
- if l == '%' : n -= 1
- else : n += 1
- l = c
- return n
-
-def read_asciiz(file,size=None,pos=None):
- s = []
- if pos :
- mew('s')
- file.seek( pos, 0 )
- mew('z')
- if size is not None :
- s = [file.read( size ).split('\0')[0]]
- else:
- while 1 :
- c = file.read(1)
- if (not c) or (ord(c)==0) or (c=='\n') : break
- s.append (c)
- mew('Z')
- return ''.join(s)
-
-def a2i(v,base=0):
- if v[-1:] in 'lL' : v = v[:-1]
- return int( v, base )
-
-_cmap = {
- '\\' : '\\',
- '0' : '\0',
-}
-for c in range(ord('a'),ord('z')+1) :
- try : e = eval('"\\%c"' % chr(c))
- except ValueError : pass
- else : _cmap[chr(c)] = e
-else:
- del c
- del e
-
-def make_string(s):
- return eval( '"'+s.replace('"','\\"')+'"')
-
-class MagicTestError(MagicError): pass
-
-class MagicTest:
- def __init__(self,offset,mtype,test,message,line=None,level=None):
- self.line, self.level = line, level
- self.mtype = mtype
- self.mtest = test
- self.subtests = []
- self.mask = None
- self.smod = None
- self.nmod = None
- self.offset, self.type, self.test, self.message = \
- offset,mtype,test,message
- if self.mtype == 'true' : return # XXX hack to enable level skips
- if test[-1:]=='\\' and test[-2:]!='\\\\' :
- self.test += 'n' # looks like someone wanted EOL to match?
- if mtype[:6]=='string' :
- if '/' in mtype : # for strings
- self.type, self.smod = \
- mtype[:mtype.find('/')], mtype[mtype.find('/')+1:]
- else:
- for nm in '&+-' :
- if nm in mtype : # for integer-based
- self.nmod, self.type, self.mask = (
- nm,
- mtype[:mtype.find(nm)],
- # convert mask to int, autodetect base
- int( mtype[mtype.find(nm)+1:], 0 )
- )
- break
- self.struct, self.size, self.cast = KnownTypes[ self.type ]
- def __str__(self):
- return '%s %s %s %s' % (
- self.offset, self.mtype, self.mtest, self.message
- )
- def __repr__(self):
- return 'MagicTest(%s,%s,%s,%s,line=%s,level=%s,subtests=\n%s%s)' % (
- `self.offset`, `self.mtype`, `self.mtest`, `self.message`,
- `self.line`, `self.level`,
- '\t'*self.level, pprint.pformat(self.subtests)
- )
- def run(self,file):
- result = ''
- do_close = 0
- try:
- if type(file) == type('x') :
- file = open( file, 'r', BUFFER_SIZE )
- do_close = 1
-# else:
-# saved_pos = file.tell()
- if self.mtype != 'true' :
- data = self.read(file)
- last = file.tell()
- else:
- data = last = None
- if self.check( data ) :
- result = self.message+' '
- if has_format( result ) : result %= data
- for test in self.subtests :
- m = test.run(file)
- if m is not None : result += m
- return make_string( result )
- finally:
- if do_close :
- file.close()
-# else:
-# file.seek( saved_pos, 0 )
- def get_mod_and_value(self):
- if self.type[-6:] == 'string' :
- # "something like\tthis\n"
- if self.test[0] in '=<>' :
- mod, value = self.test[0], make_string( self.test[1:] )
- else:
- mod, value = '=', make_string( self.test )
- else:
- if self.test[0] in '=<>&^' :
- mod, value = self.test[0], a2i(self.test[1:])
- elif self.test[0] == 'x':
- mod = self.test[0]
- value = 0
- else:
- mod, value = '=', a2i(self.test)
- return mod, value
- def read(self,file):
- mew( 's' )
- file.seek( self.offset(file), 0 ) # SEEK_SET
- mew( 'r' )
- try:
- data = rdata = None
- # XXX self.size might be 0 here...
- if self.size == 0 :
- # this is an ASCIIZ string...
- size = None
- if self.test != '>\\0' : # magic's hack for string read...
- value = self.get_mod_and_value()[1]
- size = (value=='\0') and None or len(value)
- rdata = data = read_asciiz( file, size=size )
- else:
- rdata = file.read( self.size )
- if not rdata or (len(rdata)!=self.size) : return None
- data = struct.unpack( self.struct, rdata )[0] # XXX hack??
- except:
- print >>sys.stderr, self
- print >>sys.stderr, '@%s struct=%s size=%d rdata=%s' % (
- self.offset, `self.struct`, self.size,`rdata`)
- raise
- mew( 'R' )
- if self.cast : data = self.cast( data )
- if self.mask :
- try:
- if self.nmod == '&' : data &= self.mask
- elif self.nmod == '+' : data += self.mask
- elif self.nmod == '-' : data -= self.mask
- else: raise MagicTestError(self.nmod)
- except:
- print >>sys.stderr,'data=%s nmod=%s mask=%s' % (
- `data`, `self.nmod`, `self.mask`
- )
- raise
- return data
- def check(self,data):
- mew('.')
- if self.mtype == 'true' :
- return '' # not None !
- mod, value = self.get_mod_and_value()
- if self.type[-6:] == 'string' :
- # "something like\tthis\n"
- if self.smod :
- xdata = data
- if 'b' in self.smod : # all blanks are optional
- xdata = ''.join( data.split() )
- value = ''.join( value.split() )
- if 'c' in self.smod : # all blanks are optional
- xdata = xdata.upper()
- value = value.upper()
- # if 'B' in self.smod : # compact blanks
- ### XXX sorry, i don't understand this :-(
- # data = ' '.join( data.split() )
- # if ' ' not in data : return None
- else:
- xdata = data
- try:
- if mod == '=' : result = data == value
- elif mod == '<' : result = data < value
- elif mod == '>' : result = data > value
- elif mod == '&' : result = data & value
- elif mod == '^' : result = (data & (~value)) == 0
- elif mod == 'x' : result = 1
- else : raise MagicTestError(self.test)
- if result :
- zdata, zval = `data`, `value`
- if self.mtype[-6:]!='string' :
- try: zdata, zval = hex(data), hex(value)
- except: zdata, zval = `data`, `value`
- if 0 : print >>sys.stderr, '%s @%s %s:%s %s %s => %s (%s)' % (
- '>'*self.level, self.offset,
- zdata, self.mtype, `mod`, zval, `result`,
- self.message
- )
- return result
- except:
- print >>sys.stderr,'mtype=%s data=%s mod=%s value=%s' % (
- `self.mtype`, `data`, `mod`, `value`
- )
- raise
- def add(self,mt):
- if not isinstance(mt,MagicTest) :
- raise MagicTestError((mt,'incorrect subtest type %s'%(type(mt),)))
- if mt.level == self.level+1 :
- self.subtests.append( mt )
- elif self.subtests :
- self.subtests[-1].add( mt )
- elif mt.level > self.level+1 :
- # it's possible to get level 3 just after level 1 !!! :-(
- level = self.level + 1
- while level < mt.level :
- xmt = MagicTest(None,'true','x','',line=self.line,level=level)
- self.add( xmt )
- level += 1
- else:
- self.add( mt ) # retry...
- else:
- raise MagicTestError((mt,'incorrect subtest level %s'%(`mt.level`,)))
- def last_test(self):
- return self.subtests[-1]
-#end class MagicTest
-
-class OffsetError(MagicError): pass
-
-class Offset:
- pos_format = {'b':'<B','B':'>B','s':'<H','S':'>H','l':'<I','L':'>I',}
- pattern0 = re.compile(r''' # mere offset
- ^
- &? # possible ampersand
- ( 0 # just zero
- | [1-9]{1,1}[0-9]* # decimal
- | 0[0-7]+ # octal
- | 0x[0-9a-f]+ # hex
- )
- $
- ''', re.X|re.I
- )
- pattern1 = re.compile(r''' # indirect offset
- ^\(
- (?P<base>&?0 # just zero
- |&?[1-9]{1,1}[0-9]* # decimal
- |&?0[0-7]* # octal
- |&?0x[0-9A-F]+ # hex
- )
- (?P<type>
- \. # this dot might be alone
- [BSL]? # one of this chars in either case
- )?
- (?P<sign>
- [-+]{0,1}
- )?
- (?P<off>0 # just zero
- |[1-9]{1,1}[0-9]* # decimal
- |0[0-7]* # octal
- |0x[0-9a-f]+ # hex
- )?
- \)$''', re.X|re.I
- )
- def __init__(self,s):
- self.source = s
- self.value = None
- self.relative = 0
- self.base = self.type = self.sign = self.offs = None
- m = Offset.pattern0.match( s )
- if m : # just a number
- if s[0] == '&' :
- self.relative, self.value = 1, int( s[1:], 0 )
- else:
- self.value = int( s, 0 )
- return
- m = Offset.pattern1.match( s )
- if m : # real indirect offset
- try:
- self.base = m.group('base')
- if self.base[0] == '&' :
- self.relative, self.base = 1, int( self.base[1:], 0 )
- else:
- self.base = int( self.base, 0 )
- if m.group('type') : self.type = m.group('type')[1:]
- self.sign = m.group('sign')
- if m.group('off') : self.offs = int( m.group('off'), 0 )
- if self.sign == '-' : self.offs = 0 - self.offs
- except:
- print >>sys.stderr, '$$', m.groupdict()
- raise
- return
- raise OffsetError(`s`)
- def __call__(self,file=None):
- if self.value is not None : return self.value
- pos = file.tell()
- try:
- if not self.relative : file.seek( self.offset, 0 )
- frmt = Offset.pos_format.get( self.type, 'I' )
- size = struct.calcsize( frmt )
- data = struct.unpack( frmt, file.read( size ) )
- if self.offs : data += self.offs
- return data
- finally:
- file.seek( pos, 0 )
- def __str__(self): return self.source
- def __repr__(self): return 'Offset(%s)' % `self.source`
-#end class Offset
-
-class MagicFileError(MagicError): pass
-
-class MagicFile:
- def __init__(self,filename=_magic):
- self.file = None
- self.tests = []
- self.total_tests = 0
- self.load( filename )
- self.ack_tests = None
- self.nak_tests = None
- def __del__(self):
- self.close()
- def load(self,filename=None):
- self.open( filename )
- self.parse()
- self.close()
- def open(self,filename=None):
- self.close()
- if filename is not None :
- self.filename = filename
- self.file = open( self.filename, 'r', BUFFER_SIZE )
- def close(self):
- if self.file :
- self.file.close()
- self.file = None
- def parse(self):
- line_no = 0
- for line in self.file.xreadlines() :
- line_no += 1
- if not line or line[0]=='#' : continue
- line = line.lstrip().rstrip('\r\n')
- if not line or line[0]=='#' : continue
- try:
- x = self.parse_line( line )
- if x is None :
- print >>sys.stderr, '#[%04d]#'%line_no, line
- continue
- except:
- print >>sys.stderr, '###[%04d]###'%line_no, line
- raise
- self.total_tests += 1
- level, offset, mtype, test, message = x
- new_test = MagicTest(offset,mtype,test,message,
- line=line_no,level=level)
- try:
- if level == 0 :
- self.tests.append( new_test )
- else:
- self.tests[-1].add( new_test )
- except:
- if 1 :
- print >>sys.stderr, 'total tests=%s' % (
- `self.total_tests`,
- )
- print >>sys.stderr, 'level=%s' % (
- `level`,
- )
- print >>sys.stderr, 'tests=%s' % (
- pprint.pformat(self.tests),
- )
- raise
- else:
- while self.tests[-1].level > 0 :
- self.tests.pop()
- def parse_line(self,line):
- # print >>sys.stderr, 'line=[%s]' % line
- if (not line) or line[0]=='#' : return None
- level = 0
- offset = mtype = test = message = ''
- mask = None
- # get optional level (count leading '>')
- while line and line[0]=='>' :
- line, level = line[1:], level+1
- # get offset
- while line and not line[0].isspace() :
- offset, line = offset+line[0], line[1:]
- try:
- offset = Offset(offset)
- except:
- print >>sys.stderr, 'line=[%s]' % line
- raise
- # skip spaces
- line = line.lstrip()
- # get type
- c = None
- while line :
- last_c, c, line = c, line[0], line[1:]
- if last_c!='\\' and c.isspace() :
- break # unescaped space - end of field
- else:
- mtype += c
- if last_c == '\\' :
- c = None # don't fuck my brain with sequential backslashes
- # skip spaces
- line = line.lstrip()
- # get test
- c = None
- while line :
- last_c, c, line = c, line[0], line[1:]
- if last_c!='\\' and c.isspace() :
- break # unescaped space - end of field
- else:
- test += c
- if last_c == '\\' :
- c = None # don't fuck my brain with sequential backslashes
- # skip spaces
- line = line.lstrip()
- # get message
- message = line
- if mime and line.find("\t") != -1:
- message=line[0:line.find("\t")]
- #
- # print '>>', level, offset, mtype, test, message
- return level, offset, mtype, test, message
- def detect(self,file):
- self.ack_tests = 0
- self.nak_tests = 0
- answers = []
- for test in self.tests :
- message = test.run( file )
- if message :
- self.ack_tests += 1
- answers.append( message )
- else:
- self.nak_tests += 1
- if answers :
- return '; '.join( answers )
-#end class MagicFile
-
-def username(uid):
- try:
- return pwd.getpwuid( uid )[0]
- except:
- return '#%s'%uid
-
-def groupname(gid):
- try:
- return grp.getgrgid( gid )[0]
- except:
- return '#%s'%gid
-
-def get_file_type(fname,follow):
- t = None
- if not follow :
- try:
- st = os.lstat( fname ) # stat that entry, don't follow links!
- except os.error, why :
- pass
- else:
- if stat.S_ISLNK(st[stat.ST_MODE]) :
- t = 'symbolic link'
- try:
- lnk = os.readlink( fname )
- except:
- t += ' (unreadable)'
- else:
- t += ' to '+lnk
- if t is None :
- try:
- st = os.stat( fname )
- except os.error, why :
- return "can't stat `%s' (%s)." % (why.filename,why.strerror)
-
- dmaj, dmin = (st.st_rdev>>8)&0x0FF, st.st_rdev&0x0FF
-
- if 0 : pass
- elif stat.S_ISSOCK(st.st_mode) : t = 'socket'
- elif stat.S_ISLNK (st.st_mode) : t = follow and 'symbolic link' or t
- elif stat.S_ISREG (st.st_mode) : t = 'file'
- elif stat.S_ISBLK (st.st_mode) : t = 'block special (%d/%d)'%(dmaj,dmin)
- elif stat.S_ISDIR (st.st_mode) : t = 'directory'
- elif stat.S_ISCHR (st.st_mode) : t = 'character special (%d/%d)'%(dmaj,dmin)
- elif stat.S_ISFIFO(st.st_mode) : t = 'pipe'
- else: t = '<unknown>'
-
- if st.st_mode & stat.S_ISUID :
- t = 'setuid(%d=%s) %s'%(st.st_uid,username(st.st_uid),t)
- if st.st_mode & stat.S_ISGID :
- t = 'setgid(%d=%s) %s'%(st.st_gid,groupname(st.st_gid),t)
- if st.st_mode & stat.S_ISVTX :
- t = 'sticky '+t
-
- return t
-
-HELP = '''%s [options] [files...]
-
-Options:
-
- -?, --help -- this help
- -m, --magic=<file> -- use this magic <file> instead of %s
- -f, --files=<namefile> -- read filenames for <namefile>
-* -C, --compile -- write "compiled" magic file
- -b, --brief -- don't prepend filenames to output lines
-+ -c, --check -- check the magic file
- -i, --mime -- output MIME types
-* -k, --keep-going -- don't stop st the first match
- -n, --flush -- flush stdout after each line
- -v, --verson -- print version and exit
-* -z, --compressed -- try to look inside compressed files
- -L, --follow -- follow symlinks
- -s, --special -- don't skip special files
-
-* -- not implemented so far ;-)
-+ -- implemented, but in another way...
-'''
-
-def main():
- import getopt
- global _magic
- try:
- brief = 0
- flush = 0
- follow= 0
- mime = 0
- check = 0
- special=0
- try:
- opts, args = getopt.getopt(
- sys.argv[1:],
- '?m:f:CbciknvzLs',
- ( 'help',
- 'magic=',
- 'names=',
- 'compile',
- 'brief',
- 'check',
- 'mime',
- 'keep-going',
- 'flush',
- 'version',
- 'compressed',
- 'follow',
- 'special',
- )
- )
- except getopt.error, why:
- print >>sys.stderr, sys.argv[0], why
- return 1
- else:
- files = None
- for o,v in opts :
- if o in ('-?','--help'):
- print HELP % (
- sys.argv[0],
- _magic,
- )
- return 0
- elif o in ('-f','--files='):
- files = v
- elif o in ('-m','--magic='):
- _magic = v[:]
- elif o in ('-C','--compile'):
- pass
- elif o in ('-b','--brief'):
- brief = 1
- elif o in ('-c','--check'):
- check = 1
- elif o in ('-i','--mime'):
- mime = 1
- if os.path.exists( _magic+'.mime' ) :
- _magic += '.mime'
- print >>sys.stderr,sys.argv[0]+':',\
- "Using regular magic file `%s'" % _magic
- elif o in ('-k','--keep-going'):
- pass
- elif o in ('-n','--flush'):
- flush = 1
- elif o in ('-v','--version'):
- print 'VERSION'
- return 0
- elif o in ('-z','--compressed'):
- pass
- elif o in ('-L','--follow'):
- follow = 1
- elif o in ('-s','--special'):
- special = 1
- else:
- if files :
- files = map(lambda x: x.strip(), v.split(','))
- if '-' in files and '-' in args :
- error( 1, 'cannot use STDIN simultaneously for file list and data' )
- for file in files :
- for name in (
- (file=='-')
- and sys.stdin
- or open(file,'r',BUFFER_SIZE)
- ).xreadlines():
- name = name.strip()
- if name not in args :
- args.append( name )
- try:
- if check : print >>sys.stderr, 'Loading magic database...'
- t0 = time.time()
- m = MagicFile(_magic)
- t1 = time.time()
- if check :
- print >>sys.stderr, \
- m.total_tests, 'tests loaded', \
- 'for', '%.2f' % (t1-t0), 'seconds'
- print >>sys.stderr, len(m.tests), 'tests at top level'
- return 0 # XXX "shortened" form ;-)
-
- mlen = max( map(len, args) )+1
- for arg in args :
- if not brief : print (arg + ':').ljust(mlen),
- ftype = get_file_type( arg, follow )
- if (special and ftype.find('special')>=0) \
- or ftype[-4:] == 'file' :
- t0 = time.time()
- try:
- t = m.detect( arg )
- except (IOError,os.error), why:
- t = "can't read `%s' (%s)" % (why.filename,why.strerror)
- if ftype[-4:] == 'file' : t = ftype[:-4] + t
- t1 = time.time()
- print t and t or 'data'
- if 0 : print \
- '#\t%d tests ok, %d tests failed for %.2f seconds'%\
- (m.ack_tests, m.nak_tests, t1-t0)
- else:
- print mime and 'application/x-not-regular-file' or ftype
- if flush : sys.stdout.flush()
- # print >>sys.stderr, 'DONE'
- except:
- if check : return 1
- raise
- else:
- return 0
- finally:
- pass
-
-if __name__ == '__main__' :
- sys.exit( main() )
-# vim:ai
-# EOF #
diff --git a/contrib/gnatsparse/specialuu.py b/contrib/gnatsparse/specialuu.py
deleted file mode 100755
index b729d9c59..000000000
--- a/contrib/gnatsparse/specialuu.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#! /usr/bin/env python2.2
-
-# Copyright 1994 by Lance Ellinghouse
-# Cathedral City, California Republic, United States of America.
-# All Rights Reserved
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Lance Ellinghouse
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
-# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
-# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# Modified by Jack Jansen, CWI, July 1995:
-# - Use binascii module to do the actual line-by-line conversion
-# between ascii and binary. This results in a 1000-fold speedup. The C
-# version is still 5 times faster, though.
-# - Arguments more compliant with python standard
-
-"""Implementation of the UUencode and UUdecode functions.
-
-encode(in_file, out_file [,name, mode])
-decode(in_file [, out_file, mode])
-"""
-
-import binascii
-import os
-import sys
-from types import StringType
-
-__all__ = ["Error", "decode"]
-
-class Error(Exception):
- pass
-
-def decode(in_file, out_file=None, mode=None, quiet=0):
- """Decode uuencoded file"""
- #
- # Open the input file, if needed.
- #
- if in_file == '-':
- in_file = sys.stdin
- elif isinstance(in_file, StringType):
- in_file = open(in_file)
- #
- # Read until a begin is encountered or we've exhausted the file
- #
- while 1:
- hdr = in_file.readline()
- if not hdr:
- raise Error, 'No valid begin line found in input file'
- if hdr[:5] != 'begin':
- continue
- hdrfields = hdr.split(" ", 2)
- if len(hdrfields) == 3 and hdrfields[0] == 'begin':
- try:
- int(hdrfields[1], 8)
- start_pos = in_file.tell() - len (hdr)
- break
- except ValueError:
- pass
- if out_file is None:
- out_file = hdrfields[2].rstrip()
- if os.path.exists(out_file):
- raise Error, 'Cannot overwrite existing file: %s' % out_file
- if mode is None:
- mode = int(hdrfields[1], 8)
- #
- # Open the output file
- #
- if out_file == '-':
- out_file = sys.stdout
- elif isinstance(out_file, StringType):
- fp = open(out_file, 'wb')
- try:
- os.path.chmod(out_file, mode)
- except AttributeError:
- pass
- out_file = fp
- #
- # Main decoding loop
- #
- s = in_file.readline()
- while s and s.strip() != 'end':
- try:
- data = binascii.a2b_uu(s)
- except binascii.Error, v:
- # Workaround for broken uuencoders by /Fredrik Lundh
- nbytes = (((ord(s[0])-32) & 63) * 4 + 5) / 3
- data = binascii.a2b_uu(s[:nbytes])
- if not quiet:
- sys.stderr.write("Warning: %s\n" % str(v))
- out_file.write(data)
- s = in_file.readline()
-# if not s:
- # raise Error, 'Truncated input file'
- return (hdrfields[2].rstrip(), start_pos, in_file.tell())
diff --git a/contrib/jb2bz.py b/contrib/jb2bz.py
index e2f502927..e2f502927 100644..100755
--- a/contrib/jb2bz.py
+++ b/contrib/jb2bz.py
diff --git a/contrib/merge-users.pl b/contrib/merge-users.pl
index 80c516e04..80c516e04 100644..100755
--- a/contrib/merge-users.pl
+++ b/contrib/merge-users.pl
diff --git a/contrib/sendbugmail.pl b/contrib/sendbugmail.pl
index 4fd1c8374..4fd1c8374 100644..100755
--- a/contrib/sendbugmail.pl
+++ b/contrib/sendbugmail.pl
diff --git a/contrib/sendunsentbugmail.pl b/contrib/sendunsentbugmail.pl
index ec92a97a0..ec92a97a0 100644..100755
--- a/contrib/sendunsentbugmail.pl
+++ b/contrib/sendunsentbugmail.pl
diff --git a/contrib/yp_nomail.sh b/contrib/yp_nomail.sh
index 36bbc82f7..36bbc82f7 100644..100755
--- a/contrib/yp_nomail.sh
+++ b/contrib/yp_nomail.sh