2008-11-04 Anders Carlsson <andersca@apple.com>
[webkit/qt.git] / BugsSite / importxml.pl
blob0d9dcb8683782e1eadee2fa8745ef743f0b5a999
1 #!/usr/bin/perl -w
2 # -*- Mode: perl; indent-tabs-mode: nil -*-
4 # The contents of this file are subject to the Mozilla Public
5 # License Version 1.1 (the "License"); you may not use this file
6 # except in compliance with the License. You may obtain a copy of
7 # the License at http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS
10 # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 # implied. See the License for the specific language governing
12 # rights and limitations under the License.
14 # The Original Code is the Bugzilla Bug Tracking System.
16 # The Initial Developer of the Original Code is Netscape Communications
17 # Corporation. Portions created by Netscape are
18 # Copyright (C) 1998 Netscape Communications Corporation. All
19 # Rights Reserved.
21 # Contributor(s): Dawn Endico <endico@mozilla.org>
24 # This script reads in xml bug data from standard input and inserts
25 # a new bug into bugzilla. Everything before the beginning <?xml line
26 # is removed so you can pipe in email messages.
28 use strict;
30 #####################################################################
32 # This script is used import bugs from another installation of bugzilla.
33 # Moving a bug on another system will send mail to an alias provided by
34 # the administrator of the target installation (you). Set up an alias
35 # similar to the one given below so this mail will be automatically
36 # run by this script and imported into your database. Run 'newaliases'
37 # after adding this alias to your aliases file. Make sure your sendmail
38 # installation is configured to allow mail aliases to execute code.
40 # bugzilla-import: "|/usr/bin/perl /opt/bugzilla/importxml.pl"
42 #####################################################################
45 # figure out which path this script lives in. Set the current path to
46 # this and add it to @INC so this will work when run as part of mail
47 # alias by the mailer daemon
48 # since "use lib" is run at compile time, we need to enclose the
49 # $::path declaration in a BEGIN block so that it is executed before
50 # the rest of the file is compiled.
51 BEGIN {
52 $::path = $0;
53 $::path =~ m#(.*)/[^/]+#;
54 $::path = $1;
55 $::path ||= '.'; # $0 is empty at compile time. This line will
56 # have no effect on this script at runtime.
59 chdir $::path;
60 use lib ($::path);
62 use Bugzilla;
63 use Bugzilla::Config qw(:DEFAULT $datadir);
64 use Bugzilla::BugMail;
66 use XML::Parser;
67 use Data::Dumper;
68 $Data::Dumper::Useqq = 1;
69 use Bugzilla::BugMail;
70 use Bugzilla::User;
72 require "CGI.pl";
73 require "globals.pl";
75 GetVersionTable();
78 sub sillyness {
79 my $zz;
80 $zz = $Data::Dumper::Useqq;
81 $zz = %::versions;
82 $zz = %::keywordsbyname;
83 $zz = @::legal_bug_status;
84 $zz = @::legal_opsys;
85 $zz = @::legal_platform;
86 $zz = @::legal_priority;
87 $zz = @::legal_severity;
88 $zz = @::legal_resolution;
89 $zz = %::target_milestone;
92 # XML::Parser automatically unquotes characters when it
93 # parses the XML, so this routine shouldn't be needed
94 # for anything (see bug 109530).
95 sub UnQuoteXMLChars {
96 $_[0] =~ s/&amp;/&/g;
97 $_[0] =~ s/&lt;/</g;
98 $_[0] =~ s/&gt;/>/g;
99 $_[0] =~ s/&apos;/'/g; # ' # Darned emacs colors
100 $_[0] =~ s/&quot;/"/g; # " # Darned emacs colors
101 # $_[0] =~ s/([\x80-\xFF])/&XmlUtf8Encode(ord($1))/ge;
102 return($_[0]);
105 sub MailMessage {
106 my $subject = shift @_;
107 my $message = shift @_;
108 my @recipients = @_;
110 my $to = join (", ", @recipients);
111 my $header = "To: $to\n";
112 my $from = Param("moved-from-address");
113 $from =~ s/@/\@/g;
114 $header.= "From: Bugzilla <$from>\n";
115 $header.= "Subject: $subject\n\n";
117 my $sendmessage = $header . $message . "\n";
118 Bugzilla::BugMail::MessageToMTA($sendmessage);
122 my $xml;
123 while (<>) {
124 $xml .= $_;
126 # remove everything in file before xml header (i.e. remove the mail header)
127 $xml =~ s/^.+(<\?xml version.+)$/$1/s;
129 my $parser = new XML::Parser(Style => 'Tree');
130 my $tree = $parser->parse($xml);
131 my $dbh = Bugzilla->dbh;
133 my $maintainer;
134 if (defined $tree->[1][0]->{'maintainer'}) {
135 $maintainer= $tree->[1][0]->{'maintainer'};
136 } else {
137 my $subject = "Bug import error: no maintainer";
138 my $message = "Cannot import these bugs because no maintainer for ";
139 $message .= "the exporting db is given.\n";
140 $message .= "\n\nPlease re-open the original bug.\n";
141 $message .= "\n\n$xml";
142 my @to = (Param("maintainer"));
143 MailMessage ($subject, $message, @to);
144 exit;
147 my $exporter;
148 if (defined $tree->[1][0]->{'exporter'}) {
149 $exporter = $tree->[1][0]->{'exporter'};
150 } else {
151 my $subject = "Bug import error: no exporter";
152 my $message = "Cannot import these bugs because no exporter is given.\n";
153 $message .= "\n\nPlease re-open the original bug.\n";
154 $message .= "\n\n$xml";
155 my @to = (Param("maintainer"), $maintainer);
156 MailMessage ($subject, $message, @to);
157 exit;
161 unless ( Param("move-enabled") ) {
162 my $subject = "Error: bug importing is disabled here";
163 my $message = "Cannot import these bugs because importing is disabled\n";
164 $message .= "at this site. For more info, contact ";
165 $message .= Param("maintainer") . ".\n";
166 my @to = (Param("maintainer"), $maintainer, $exporter);
167 MailMessage ($subject, $message, @to);
168 exit;
171 my $exporterid = login_to_id($exporter);
172 if ( ! $exporterid ) {
173 my $subject = "Bug import error: invalid exporter";
174 my $message = "The user <$tree->[1][0]->{'exporter'}> who tried to move\n";
175 $message .= "bugs here does not have an account in this database.\n";
176 $message .= "\n\nPlease re-open the original bug.\n";
177 $message .= "\n\n$xml";
178 my @to = (Param("maintainer"), $maintainer, $exporter);
179 MailMessage ($subject, $message, @to);
180 exit;
183 my $urlbase;
184 if (defined $tree->[1][0]->{'urlbase'}) {
185 $urlbase= $tree->[1][0]->{'urlbase'};
186 } else {
187 my $subject = "Bug import error: invalid exporting database";
188 my $message = "Cannot import these bugs because the name of the exporting db was not given.\n";
189 $message .= "\n\nPlease re-open the original bug.\n";
190 $message .= "\n\n$xml";
191 my @to = (Param("maintainer"), $maintainer, $exporter);
192 MailMessage ($subject, $message, @to);
193 exit;
197 my $bugqty = ($#{$tree->[1]} +1 -3) / 4;
198 my $log = "Imported $bugqty bug(s) from $urlbase,\n sent by $exporter.\n\n";
199 for (my $k=1 ; $k <= $bugqty ; $k++) {
200 my $cur = $k*4;
202 if (defined $tree->[1][$cur][0]->{'error'}) {
203 $log .= "\nError in bug $tree->[1][$cur][4][2]\@$urlbase:";
204 $log .= " $tree->[1][$cur][0]->{'error'}\n";
205 if ($tree->[1][$cur][0]->{'error'} =~ /NotFound/) {
206 $log .= "$exporter tried to move bug $tree->[1][$cur][4][2] here";
207 $log .= " but $urlbase reports that this bug does not exist.\n";
208 } elsif ( $tree->[1][$cur][0]->{'error'} =~ /NotPermitted/) {
209 $log .= "$exporter tried to move bug $tree->[1][$cur][4][2] here";
210 $log .= " but $urlbase reports that $exporter does not have access";
211 $log .= " to that bug.\n";
213 next;
216 my %multiple_fields;
217 foreach my $field (qw (dependson cc long_desc blocks)) {
218 $multiple_fields{$field} = "x";
220 my %all_fields;
221 foreach my $field (qw (dependson product bug_status priority cc version
222 bug_id rep_platform short_desc assigned_to bug_file_loc resolution
223 delta_ts component reporter urlbase target_milestone bug_severity
224 creation_ts qa_contact keywords status_whiteboard op_sys blocks)) {
225 $all_fields{$field} = "x";
229 my %bug_fields;
230 my $err = "";
231 for (my $i=3 ; $i < $#{$tree->[1][$cur]} ; $i=$i+4) {
232 if (defined $multiple_fields{$tree->[1][$cur][$i]}) {
233 if (defined $bug_fields{$tree->[1][$cur][$i]}) {
234 $bug_fields{$tree->[1][$cur][$i]} .= " " . $tree->[1][$cur][$i+1][2];
235 } else {
236 $bug_fields{$tree->[1][$cur][$i]} = $tree->[1][$cur][$i+1][2];
238 } elsif (defined $all_fields{$tree->[1][$cur][$i]}) {
239 $bug_fields{$tree->[1][$cur][$i]} = $tree->[1][$cur][$i+1][2];
240 } else {
241 $err .= "---\n";
242 $err .= "Unknown bug field \"$tree->[1][$cur][$i]\"";
243 $err .= " encountered while moving bug\n";
244 $err .= "<$tree->[1][$cur][$i]>";
245 if (defined $tree->[1][$cur][$i+1][3]) {
246 $err .= "\n";
247 for (my $j=3 ; $j < $#{$tree->[1][$cur][$i+1]} ; $j=$j+4) {
248 $err .= " <". $tree->[1][$cur][$i+1][$j] . ">";
249 $err .= " $tree->[1][$cur][$i+1][$j+1][2] ";
250 $err .= "</". $tree->[1][$cur][$i+1][$j] . ">\n";
252 } else {
253 $err .= " $tree->[1][$cur][$i+1][2] ";
255 $err .= "</$tree->[1][$cur][$i]>\n";
259 my @long_descs;
260 for (my $i=3 ; $i < $#{$tree->[1][$cur]} ; $i=$i+4) {
261 if ($tree->[1][$cur][$i] =~ /long_desc/) {
262 my %long_desc;
263 $long_desc{'who'} = $tree->[1][$cur][$i+1][4][2];
264 $long_desc{'bug_when'} = $tree->[1][$cur][$i+1][8][2];
265 $long_desc{'thetext'} = $tree->[1][$cur][$i+1][12][2];
266 push @long_descs, \%long_desc;
270 # instead of giving each comment its own item in the longdescs
271 # table like it should have, lets cat them all into one big
272 # comment otherwise we would have to lie often about who
273 # authored the comment since commenters in one bugzilla probably
274 # don't have accounts in the other one.
275 sub by_date {my @a; my @b; $a->{'bug_when'} cmp $b->{'bug_when'}; }
276 my @sorted_descs = sort by_date @long_descs;
277 my $long_description = "";
278 for (my $z=0 ; $z <= $#sorted_descs ; $z++) {
279 unless ( $z==0 ) {
280 $long_description .= "\n\n\n------- Additional Comments From ";
281 $long_description .= "$sorted_descs[$z]->{'who'} ";
282 $long_description .= "$sorted_descs[$z]->{'bug_when'}";
283 $long_description .= " ----\n\n";
285 $long_description .= $sorted_descs[$z]->{'thetext'};
286 $long_description .= "\n";
289 my $comments;
291 $comments .= "\n\n------- Bug moved to this database by $exporter ";
292 $comments .= time2str("%Y-%m-%d %H:%M", time);
293 $comments .= " -------\n\n";
294 $comments .= "This bug previously known as bug $bug_fields{'bug_id'} at ";
295 $comments .= $urlbase . "\n";
296 $comments .= $urlbase . "show_bug.cgi?";
297 $comments .= "id=" . $bug_fields{'bug_id'} . "\n";
298 $comments .= "Originally filed under the $bug_fields{'product'} ";
299 $comments .= "product and $bug_fields{'component'} component.\n";
300 if (defined $bug_fields{'dependson'}) {
301 $comments .= "Bug depends on bug(s) $bug_fields{'dependson'}.\n";
303 if (defined $bug_fields{'blocks'}) {
304 $comments .= "Bug blocks bug(s) $bug_fields{'blocks'}.\n";
307 my @query = ();
308 my @values = ();
309 foreach my $field ( qw(creation_ts status_whiteboard) ) {
310 if ( (defined $bug_fields{$field}) && ($bug_fields{$field}) ){
311 push (@query, "$field");
312 push (@values, SqlQuote($bug_fields{$field}));
316 push (@query, "delta_ts");
317 if ( (defined $bug_fields{'delta_ts'}) && ($bug_fields{'delta_ts'}) ){
318 push (@values, SqlQuote($bug_fields{'delta_ts'}));
320 else {
321 push (@values, "NOW()");
324 if ( (defined $bug_fields{'bug_file_loc'}) && ($bug_fields{'bug_file_loc'}) ){
325 push (@query, "bug_file_loc");
326 push (@values, SqlQuote($bug_fields{'bug_file_loc'}));
329 if ( (defined $bug_fields{'short_desc'}) && ($bug_fields{'short_desc'}) ){
330 push (@query, "short_desc");
331 push (@values, SqlQuote($bug_fields{'short_desc'}) );
335 my $prod;
336 my $comp;
337 my $default_prod = Param("moved-default-product");
338 my $default_comp = Param("moved-default-component");
339 if ( (defined ($bug_fields{'product'})) &&
340 (defined ($bug_fields{'component'})) ) {
341 $prod = $bug_fields{'product'};
342 $comp = $bug_fields{'component'};
343 } else {
344 $prod = $default_prod;
345 $comp = $default_comp;
348 # XXX - why are these arrays??
349 my @product;
350 my @component;
351 my $prod_id;
352 my $comp_id;
354 # First, try the given product/component
355 $prod_id = get_product_id($prod);
356 $comp_id = get_component_id($prod_id, $comp) if $prod_id;
358 if ($prod_id && $comp_id) {
359 $product[0] = $prod;
360 $component[0] = $comp;
361 } else {
362 # Second, try the defaults
363 $prod_id = get_product_id($default_prod);
364 $comp_id = get_component_id($prod_id, $default_comp) if $prod_id;
365 if ($prod_id && $comp_id) {
366 $product[0] = $default_prod;
367 $component[0] = $default_comp;
371 if ($prod_id && $comp_id) {
372 push (@query, "product_id");
373 push (@values, $prod_id );
374 push (@query, "component_id");
375 push (@values, $comp_id );
376 } else {
377 my $subject = "Bug import error: invalid default product or component";
378 my $message = "Cannot import these bugs because an invalid default ";
379 $message .= "product and/or component was defined for the target db.\n";
380 $message .= Param("maintainer") . " needs to fix the definitions of ";
381 $message .= "moved-default-product and moved-default-component.\n";
382 $message .= "\n\nPlease re-open the original bug.\n";
383 $message .= "\n\n$xml";
384 my @to = (Param("maintainer"), $maintainer, $exporter);
385 MailMessage ($subject, $message, @to);
386 exit;
389 if (defined ($::versions{$product[0]} ) &&
390 (my @version = grep(lc($_) eq lc($bug_fields{'version'}),
391 @{$::versions{$product[0]}})) ){
392 push (@values, SqlQuote($version[0]) );
393 push (@query, "version");
394 } else {
395 push (@query, "version");
396 push (@values, SqlQuote($::versions{$product[0]}->[0]));
397 $err .= "Unknown version $bug_fields{'version'} in product $product[0]. ";
398 $err .= "Setting version to \"$::versions{$product[0]}->[0]\".\n";
401 if (defined ($bug_fields{'priority'}) &&
402 (my @priority = grep(lc($_) eq lc($bug_fields{'priority'}), @::legal_priority)) ){
403 push (@values, SqlQuote($priority[0]) );
404 push (@query, "priority");
405 } else {
406 push (@values, SqlQuote("P3"));
407 push (@query, "priority");
408 $err .= "Unknown priority ";
409 $err .= (defined $bug_fields{'priority'})?$bug_fields{'priority'}:"unknown";
410 $err .= ". Setting to default priority \"P3\".\n";
413 if (defined ($bug_fields{'rep_platform'}) &&
414 (my @platform = grep(lc($_) eq lc($bug_fields{'rep_platform'}), @::legal_platform)) ){
415 push (@values, SqlQuote($platform[0]) );
416 push (@query, "rep_platform");
417 } else {
418 push (@values, SqlQuote("Other") );
419 push (@query, "rep_platform");
420 $err .= "Unknown platform ";
421 $err .= (defined $bug_fields{'rep_platform'})?
422 $bug_fields{'rep_platform'}:"unknown";
423 $err .= ". Setting to default platform \"Other\".\n";
426 if (defined ($bug_fields{'op_sys'}) &&
427 (my @opsys = grep(lc($_) eq lc($bug_fields{'op_sys'}), @::legal_opsys)) ){
428 push (@values, SqlQuote($opsys[0]) );
429 push (@query, "op_sys");
430 } else {
431 push (@values, SqlQuote("other"));
432 push (@query, "op_sys");
433 $err .= "Unknown operating system ";
434 $err .= (defined $bug_fields{'op_sys'})?$bug_fields{'op_sys'}:"unknown";
435 $err .= ". Setting to default OS \"other\".\n";
438 if (Param("usetargetmilestone")) {
439 if (defined ($::target_milestone{$product[0]} ) &&
440 (my @tm = grep(lc($_) eq lc($bug_fields{'target_milestone'}),
441 @{$::target_milestone{$product[0]}})) ){
442 push (@values, SqlQuote($tm[0]) );
443 push (@query, "target_milestone");
444 } else {
445 SendSQL("SELECT defaultmilestone FROM products " .
446 "WHERE name = " . SqlQuote($product[0]));
447 my $tm = FetchOneColumn();
448 push (@values, SqlQuote($tm));
449 push (@query, "target_milestone");
450 $err .= "Unknown milestone \"";
451 $err .= (defined $bug_fields{'target_milestone'})?
452 $bug_fields{'target_milestone'}:"unknown";
453 $err .= "\" in product \"$product[0]\".\n";
454 $err .= " Setting to default milestone for this product, ";
455 $err .= "\'" . $tm . "\'\n";
459 if (defined ($bug_fields{'bug_severity'}) &&
460 (my @severity= grep(lc($_) eq lc($bug_fields{'bug_severity'}),
461 @::legal_severity)) ){
462 push (@values, SqlQuote($severity[0]) );
463 push (@query, "bug_severity");
464 } else {
465 push (@values, SqlQuote("normal"));
466 push (@query, "bug_severity");
467 $err .= "Unknown severity ";
468 $err .= (defined $bug_fields{'bug_severity'})?
469 $bug_fields{'bug_severity'}:"unknown";
470 $err .= ". Setting to default severity \"normal\".\n";
473 my $reporterid = login_to_id($bug_fields{'reporter'});
474 if ( ($bug_fields{'reporter'}) && ( $reporterid ) ) {
475 push (@values, SqlQuote($reporterid));
476 push (@query, "reporter");
477 } else {
478 push (@values, SqlQuote($exporterid));
479 push (@query, "reporter");
480 $err .= "The original reporter of this bug does not have\n";
481 $err .= " an account here. Reassigning to the person who moved\n";
482 $err .= " it here, $exporter.\n";
483 if ( $bug_fields{'reporter'} ) {
484 $err .= " Previous reporter was $bug_fields{'reporter'}.\n";
485 } else {
486 $err .= " Previous reporter is unknown.\n";
490 my $changed_owner = 0;
491 if ( ($bug_fields{'assigned_to'}) &&
492 ( login_to_id($bug_fields{'assigned_to'})) ) {
493 push (@values, SqlQuote(login_to_id($bug_fields{'assigned_to'})));
494 push (@query, "assigned_to");
495 } else {
496 push (@values, SqlQuote($exporterid) );
497 push (@query, "assigned_to");
498 $changed_owner = 1;
499 $err .= "The original assignee of this bug does not have\n";
500 $err .= " an account here. Reassigning to the person who moved\n";
501 $err .= " it here, $exporter.\n";
502 if ( $bug_fields{'assigned_to'} ) {
503 $err .= " Previous assignee was $bug_fields{'assigned_to'}.\n";
504 } else {
505 $err .= " Previous assignee is unknown.\n";
509 my @resolution;
510 if (defined ($bug_fields{'resolution'}) &&
511 (@resolution= grep(lc($_) eq lc($bug_fields{'resolution'}), @::legal_resolution)) ){
512 push (@values, SqlQuote($resolution[0]) );
513 push (@query, "resolution");
514 } elsif ( (defined $bug_fields{'resolution'}) && (!$resolution[0]) ){
515 $err .= "Unknown resolution \"$bug_fields{'resolution'}\".\n";
518 # if the bug's assignee changed, mark the bug NEW, unless a valid
519 # resolution is set, which indicates that the bug should be closed.
521 if ( ($changed_owner) && (!$resolution[0]) ) {
522 push (@values, SqlQuote("NEW"));
523 push (@query, "bug_status");
524 $err .= "Bug reassigned, setting status to \"NEW\".\n";
525 $err .= " Previous status was \"";
526 $err .= (defined $bug_fields{'bug_status'})?
527 $bug_fields{'bug_status'}:"unknown";
528 $err .= "\".\n";
529 } elsif ( (defined ($bug_fields{'resolution'})) && (!$resolution[0]) ){
530 #if the resolution was illegal then set status to NEW
531 push (@values, SqlQuote("NEW"));
532 push (@query, "bug_status");
533 $err .= "Resolution was invalid. Setting status to \"NEW\".\n";
534 $err .= " Previous status was \"";
535 $err .= (defined $bug_fields{'bug_status'})?
536 $bug_fields{'bug_status'}:"unknown";
537 $err .= "\".\n";
538 } elsif (defined ($bug_fields{'bug_status'}) &&
539 (my @status = grep(lc($_) eq lc($bug_fields{'bug_status'}), @::legal_bug_status)) ){
540 #if a bug status was set then use it, if its legal
541 push (@values, SqlQuote($status[0]));
542 push (@query, "bug_status");
543 } else {
544 # if all else fails, make the bug new
545 push (@values, SqlQuote("NEW"));
546 push (@query, "bug_status");
547 $err .= "Unknown status ";
548 $err .= (defined $bug_fields{'bug_status'})?
549 $bug_fields{'bug_status'}:"unknown";
550 $err .= ". Setting to default status \"NEW\".\n";
553 if (Param("useqacontact")) {
554 my $qa_contact;
555 if ( (defined $bug_fields{'qa_contact'}) &&
556 ($qa_contact = login_to_id($bug_fields{'qa_contact'})) ){
557 push (@values, $qa_contact);
558 push (@query, "qa_contact");
559 } else {
560 SendSQL("SELECT initialqacontact FROM components, products " .
561 "WHERE components.product_id = products.id" .
562 " AND products.name = " . SqlQuote($product[0]) .
563 " AND components.name = " . SqlQuote($component[0]) );
564 $qa_contact = FetchOneColumn();
565 push (@values, $qa_contact);
566 push (@query, "qa_contact");
567 $err .= "Setting qa contact to the default for this product.\n";
568 $err .= " This bug either had no qa contact or an invalid one.\n";
573 my $query = "INSERT INTO bugs (\n"
574 . join (",\n", @query)
575 . "\n) VALUES (\n"
576 . join (",\n", @values)
577 . "\n)\n";
578 SendSQL($query);
579 my $id = $dbh->bz_last_key('bugs', 'bug_id');
581 if (defined $bug_fields{'cc'}) {
582 foreach my $person (split(/[ ,]/, $bug_fields{'cc'})) {
583 my $uid;
584 if ( ($person ne "") && ($uid = login_to_id($person)) ) {
585 SendSQL("insert into cc (bug_id, who) values ($id, " . SqlQuote($uid) .")");
590 if (defined ($bug_fields{'keywords'})) {
591 my %keywordseen;
592 foreach my $keyword (split(/[\s,]+/, $bug_fields{'keywords'})) {
593 if ($keyword eq '') {
594 next;
596 my $i = $::keywordsbyname{$keyword};
597 if (!$i) {
598 $err .= "Skipping unknown keyword: $keyword.\n";
599 next;
601 if (!$keywordseen{$i}) {
602 SendSQL("INSERT INTO keywords (bug_id, keywordid) VALUES ($id, $i)");
603 $keywordseen{$i} = 1;
608 $long_description .= "\n" . $comments;
609 if ($err) {
610 $long_description .= "\n$err\n";
613 SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES " .
614 "($id, $exporterid, now(), " . SqlQuote($long_description) . ")");
616 $log .= "Bug $urlbase/show_bug.cgi?id=$bug_fields{'bug_id'} ";
617 $log .= "imported as bug $id.\n";
618 $log .= Param("urlbase") . "/show_bug.cgi?id=$id\n\n";
619 if ($err) {
620 $log .= "The following problems were encountered creating bug $id.\n";
621 $log .= "You may have to set certain fields in the new bug by hand.\n\n";
622 $log .= $err;
623 $log .= "\n\n\n";
626 Bugzilla::BugMail::Send($id, { 'changer' => $exporter });
629 my $subject = "$bugqty bug(s) successfully moved from $urlbase to "
630 . Param("urlbase") ;
631 my @to = ($exporter);
632 MailMessage ($subject, $log, @to);