X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/ab71bbe6094f2ef024ae212325c2a5172afc8707..fbb64cf55d4ec47a6b340862d7902f06b7a1ddc8:/utils/perlbug.PL diff --git a/utils/perlbug.PL b/utils/perlbug.PL index cac62a0..d1eb1e0 100644 --- a/utils/perlbug.PL +++ b/utils/perlbug.PL @@ -20,41 +20,16 @@ chdir dirname($0); $file = basename($0, '.PL'); $file .= '.com' if $^O eq 'VMS'; -open OUT, ">$file" or die "Can't create $file: $!"; +open OUT, ">", $file or die "Can't create $file: $!"; -# extract patchlevel.h information +# get patchlevel.h timestamp -open PATCH_LEVEL, "<" . catfile(updir, "patchlevel.h") - or die "Can't open patchlevel.h: $!"; +-e catfile(updir, "patchlevel.h") + or die "Can't find patchlevel.h: $!"; -my $patchlevel_date = (stat PATCH_LEVEL)[9]; +my $patchlevel_date = (stat _)[9]; -while () { - last if $_ =~ /^\s*static\s+(?:const\s+)?char.*?local_patches\[\]\s*=\s*{\s*$/; -} - -if (! defined($_)) { - warn "Warning: local_patches section not found in patchlevel.h\n"; -} - -my @patches; -while () { - last if /^\s*}/; - next if /^\s*#/; # preprocessor stuff - next if /PERL_GIT_UNPUSHED_COMMITS/; # XXX expand instead - next if /"uncommitted-changes"/; # XXX determine if active instead - chomp; - s/^\s+,?\s*"?//; - s/"?\s*,?$//; - s/(['\\])/\\$1/g; - push @patches, $_ unless $_ eq 'NULL'; -} -my $patch_desc = "'" . join("',\n '", @patches) . "'"; -my $patch_tags = join "", map /(\S+)/ ? "+$1 " : (), @patches; - -close(PATCH_LEVEL) or die "Error closing patchlevel.h: $!"; - -# TO DO (prehaps): store/embed $Config::config_sh into perlbug. When perlbug is +# TO DO (perhaps): store/embed $Config::config_sh into perlbug. When perlbug is # used, compare $Config::config_sh with the stored version. If they differ then # append a list of individual differences to the bug report. @@ -74,16 +49,15 @@ $Config{startperl} my \$config_tag1 = '$extract_version - $Config{cf_time}'; my \$patchlevel_date = $patchlevel_date; -my \$patch_tags = '$patch_tags'; -my \@patches = ( - $patch_desc -); !GROK!THIS! # In the following, perl variables are not expanded during extraction. print OUT <<'!NO!SUBS!'; +my @patches = Config::local_patches(); +my $patch_tags = join "", map /(\S+)/ ? "+$1 " : (), @patches; +BEGIN { pop @INC if $INC[-1] eq '.' } use warnings; use strict; use Config; @@ -91,6 +65,8 @@ use File::Spec; # keep perlbug Perl 5.005 compatible use Getopt::Std; use File::Basename 'basename'; +$Getopt::Std::STANDARD_HELP_VERSION = 1; + sub paraprint; BEGIN { @@ -103,9 +79,11 @@ BEGIN { $::HaveTemp = ($@ eq ""); eval { require Module::CoreList; }; $::HaveCoreList = ($@ eq ""); + eval { require Text::Wrap; }; + $::HaveWrap = ($@ eq ""); }; -my $Version = "1.39"; +our $VERSION = "1.41"; #TODO: # make sure failure (transmission-wise) of Mail::Send is accounted for. @@ -117,9 +95,11 @@ my( $file, $usefile, $cc, $address, $bugaddress, $testaddress, $thanksaddress, $fh, $me, $body, $andcc, %REP, $ok, $thanks, $progname, $Is_MSWin32, $Is_Linux, $Is_VMS, $Is_OpenBSD, $report_about_module, $category, $severity, - %opt, + %opt, $have_attachment, $attachments, $has_patch, $mime_boundary ); +my $running_noninteractively = !-t STDIN; + my $perl_version = $^V ? sprintf("%vd", $^V) : $]; my $config_tag2 = "$perl_version - $Config{cf_time}"; @@ -128,7 +108,7 @@ Init(); if ($opt{h}) { Help(); exit; } if ($opt{d}) { Dump(*STDOUT); exit; } -if (!-t STDIN && !($ok and not $opt{n})) { +if ($running_noninteractively && !$opt{t} && !($ok and not $opt{n})) { paraprint <<"EOF"; Please use $progname interactively. If you want to include a file, you can use the -f switch. @@ -145,9 +125,22 @@ if ($outfile) { Send(); if ($thanks) { print "\nThank you for taking the time to send a thank-you message!\n\n"; + + paraprint <$filename") or die "Unable to create report file '$filename': $!\n"; + open(REP, '>:raw', $filename) or die "Unable to create report file '$filename': $!\n"; + binmode(REP, ':raw :crlf') if $Is_MSWin32; + my $reptype = !$ok ? ($thanks ? 'thank-you' : 'bug') : $opt{n} ? "build failure" : "success"; print REP <) { print REP $_ } @@ -662,6 +681,13 @@ Flags: severity=$severity EFF + if ($has_patch) { + print OUT <ile/ve if ( SaveMessage() ) { exit } } elsif ($action =~ /^(d|l|sh)/i ) { # isplay, ist, ow # Display the message - open(REP, "<$filename") or die "Couldn't open file '$filename': $!\n"; - while () { print $_ } - close(REP) or die "Error closing report file '$filename': $!"; + print _read_report($filename); + if ($have_attachment) { + print "\n\n---\nAttachment(s):\n"; + for my $att (split /\s*,\s*/, $attachments) { print " $att\n"; } + } } elsif ($action =~ /^su/i) { # bject my $reply = _prompt( "Subject: $subject", "If the above subject is fine, press Enter. Otherwise, type a replacement now\nSubject"); if ($reply ne '') { @@ -861,7 +890,7 @@ sub TrivialSubject { if ($subject =~ /^(y(es)?|no?|help|perl( (bug|problem))?|bug|problem)$/i || length($subject) < 4 || - $subject !~ /\s/) { + ($subject !~ /\s/ && ! $opt{t})) { # non-whitespace is accepted in test mode print "\nThe subject you entered wasn't very descriptive. Please try again.\n\n"; return 1; } else { @@ -923,6 +952,7 @@ Advanced usage: $0 [-v] [-a address] [-s subject] [-b body | -f inpufile ] [ -F outputfile ] [-r returnaddress] [-e editor] [-c adminaddress | -C] [-S] [-t] [-h] + [-p patchfile ] $0 [-v] [-r returnaddress] [-A] [-ok | -okay | -nok | -nokay] @@ -931,6 +961,8 @@ Options: -v Include Verbose configuration data in the report -f File containing the body of the report. Use this to quickly send a prepared message. + -p File containing a patch or other text attachment. Separate + multiple files with commas. -F File to output the resulting mail message to, instead of mailing. -S Send without asking for confirmation. -a Address to send the report to. Defaults to '$address'. @@ -993,6 +1025,7 @@ sub _prompt { } print $prompt. ($default ? " [$default]" :''). ": "; my $result = scalar(<>); + return $default if !defined $result; # got eof chomp($result); $result =~ s/^\s*(.*?)\s*$/$1/s; if ($default && $result eq '') { @@ -1018,21 +1051,84 @@ sub _message_headers { $headers{'Message-Id'} = $messageid if ($messageid); $headers{'Reply-To'} = $from if ($from); $headers{'From'} = $from if ($from); + if ($have_attachment) { + $headers{'MIME-Version'} = '1.0'; + $headers{'Content-Type'} = qq{multipart/mixed; boundary=\"$mime_boundary\"}; + } return \%headers; } +sub _add_body_start { + my $body_start = <<"BODY_START"; +This is a multi-part message in MIME format. +--$mime_boundary +Content-Type: text/plain; format=fixed +Content-Transfer-Encoding: 8bit + +BODY_START + return $body_start; +} + +sub _add_attachments { + my $attach = ''; + for my $attachment (split /\s*,\s*/, $attachments) { + my $attach_file = basename($attachment); + $attach .= <<"ATTACHMENT"; + +--$mime_boundary +Content-Type: text/x-patch; name="$attach_file" +Content-Transfer-Encoding: 8bit +Content-Disposition: attachment; filename="$attach_file" + +ATTACHMENT + + open my $attach_fh, '<:raw', $attachment + or die "Couldn't open attachment '$attachment': $!\n"; + while (<$attach_fh>) { $attach .= $_; } + close($attach_fh) or die "Error closing attachment '$attachment': $!"; + } + + $attach .= "\n--$mime_boundary--\n"; + return $attach; +} + +sub _read_report { + my $fname = shift; + my $content; + open( REP, "<:raw", $fname ) or die "Couldn't open file '$fname': $!\n"; + binmode(REP, ':raw :crlf') if $Is_MSWin32; + # wrap long lines to make sure the report gets delivered + local $Text::Wrap::columns = 900; + local $Text::Wrap::huge = 'overflow'; + while () { + if ($::HaveWrap && /\S/) { # wrap() would remove empty lines + $content .= Text::Wrap::wrap(undef, undef, $_); + } else { + $content .= $_; + } + } + close(REP) or die "Error closing report file '$fname': $!"; + return $content; +} + sub build_complete_message { my $content = _build_header(%{_message_headers()}) . "\n\n"; - open( REP, "<$filename" ) or die "Couldn't open file '$filename': $!\n"; - while () { $content .= $_; } - close(REP) or die "Error closing report file '$filename': $!"; + $content .= _add_body_start() if $have_attachment; + $content .= _read_report($filename); + $content .= _add_attachments() if $have_attachment; return $content; } sub save_message_to_disk { my $file = shift; - open OUTFILE, ">$file" or do { warn "Couldn't open '$file': $!\n"; return undef}; + if (-e $file) { + my $response = _prompt( '', "Overwrite existing '$file'", 'n' ); + return undef unless $response =~ / yes | y /xi; + } + open OUTFILE, '>:raw', $file or do { warn "Couldn't open '$file': $!\n"; return undef}; + binmode(OUTFILE, ':raw :crlf') if $Is_MSWin32; + print OUTFILE build_complete_message(); close(OUTFILE) or do { warn "Error closing $file: $!"; return undef }; print "\nMessage saved.\n"; @@ -1040,22 +1136,27 @@ sub save_message_to_disk { } sub _send_message_vms { - if ( ( $address =~ /@/ and $address !~ /^\w+%"/ ) - or ( $cc =~ /@/ and $cc !~ /^\w+%"/ ) ) { - my $prefix; - foreach ( qw[ IN MX SMTP UCX PONY WINS ], '' ) { - $prefix = "$_%", last if $ENV{"MAIL\$PROTOCOL_$_"}; + + my $mail_from = $from; + my $rcpt_to_to = $address; + my $rcpt_to_cc = $cc; + + map { $_ =~ s/^[^<]*[^>]*//; } ($mail_from, $rcpt_to_to, $rcpt_to_cc); + + if ( open my $sff_fh, '|-:raw', 'MCR TCPIP$SYSTEM:TCPIP$SMTP_SFF.EXE SYS$INPUT:' ) { + print $sff_fh "MAIL FROM:<$mail_from>\n"; + print $sff_fh "RCPT TO:<$rcpt_to_to>\n"; + print $sff_fh "RCPT TO:<$rcpt_to_cc>\n" if $rcpt_to_cc; + print $sff_fh "DATA\n"; + print $sff_fh build_complete_message(); + my $success = close $sff_fh; + if ($success ) { + print "\nMessage sent\n"; + return; } - $address = qq[${prefix}"$address"] unless $address =~ /^\w+%"/; - $cc = qq[${prefix}"$cc"] unless !$cc || $cc =~ /^\w+%"/; - } - $subject =~ s/"/""/g; - $address =~ s/"/""/g; - $cc =~ s/"/""/g; - my $sts = system(qq[mail/Subject="$subject" $filename. "$address","$cc"]); - if ($sts) { - die "Can't spawn off mail (leaving bug report in $filename): $sts"; } + die "Mail transport failed (leaving bug report in $filename): $^E\n"; } sub _send_message_mailsend { @@ -1066,9 +1167,10 @@ sub _send_message_mailsend { } $fh = $msg->open; - open(REP, "<$filename") or die "Couldn't open '$filename': $!\n"; - while () { print $fh $_ } - close(REP) or die "Error closing $filename: $!"; + binmode($fh, ':raw'); + print $fh _add_body_start() if $have_attachment; + print $fh _read_report($filename); + print $fh _add_attachments() if $have_attachment; $fh->close or die "Error sending mail: $!"; print "\nMessage sent.\n"; @@ -1111,7 +1213,7 @@ send to '$address' with your normal mail client. EOF } - open( SENDMAIL, "|-", $sendmail, "-t", "-oi", "-f", $from ) + open( SENDMAIL, "|-:raw", $sendmail, "-t", "-oi", "-f", $from ) || die "'|$sendmail -t -oi -f $from' failed: $!"; print SENDMAIL build_complete_message(); if ( close(SENDMAIL) ) { @@ -1133,7 +1235,8 @@ sub _fingerprint_lines_in_report { # we can track whether the user does any editing. # yes, *all* whitespace is ignored. - open(REP, "<$filename") or die "Unable to open report file '$filename': $!\n"; + open(REP, '<:raw', $filename) or die "Unable to open report file '$filename': $!\n"; + binmode(REP, ':raw :crlf') if $Is_MSWin32; while (my $line = ) { $line =~ s/\s+//g; $new_lines++ if (!$REP{$line}); @@ -1288,11 +1391,11 @@ will help a great deal. In other words, try to analyze the problem =item Can you fix the bug yourself? -A bug report which I will almost -definitely be fixed. When sending a patch, please use the C -program with the C<-u> option to generate "unified" diff files. -Bug reports with patches are likely to receive significantly more -attention and interest than those without patches. +If so, that's great news; bug reports with patches are likely to +receive significantly more attention and interest than those without +patches. Please attach your patch to the report using the C<-p> option. +When sending a patch, create it using C if possible, +though a unified diff created with C will do nearly as well. Your patch may be returned with requests for changes, or requests for more detailed explanations about your fix. @@ -1301,10 +1404,10 @@ Here are a few hints for creating high-quality patches: Make sure the patch is not reversed (the first argument to diff is typically the original file, the second argument your changed file). -Make sure you test your patch by applying it with the C -program before you send it on its way. Try to follow the same style -as the code you are trying to patch. Make sure your patch really -does work (C, if the thing you're patching is covered +Make sure you test your patch by applying it with C or the +C program before you send it on its way. Try to follow the +same style as the code you are trying to patch. Make sure your patch +really does work (C, if the thing you're patching is covered by Perl's test suite). =item Can you use C to submit the report? @@ -1338,11 +1441,12 @@ a duplicate of an existing report, you may not receive a personal reply. If it is important to you that your bug be fixed, do monitor the -perl5-porters@perl.org mailing list and the commit logs to development +perl5-porters@perl.org mailing list (mailing lists are moderated, your +message may take a while to show up) and the commit logs to development versions of Perl, and encourage the maintainers with kind words or offers of frosty beverages. (Please do be kind to the maintainers. -Harassing or flaming them is likely to have the opposite effect of -the one you want.) +Harassing or flaming them is likely to have the opposite effect of the +one you want.) Feel free to update the ticket about your bug on http://rt.perl.org if a new version of Perl is released and your bug is still present. @@ -1429,6 +1533,11 @@ days old. As B<-nok> except it will report on older systems. +=item B<-p> + +The names of one or more patch files or other text attachments to be +included with the report. Multiple files must be separated with commas. + =item B<-r> Your return address. The program will ask you to confirm its default @@ -1446,6 +1555,8 @@ supply one on the command line. =item B<-t> Test mode. The target address defaults to B. +Also makes it possible to command perlbug from a pipe or file, for +testing purposes. =item B<-T> @@ -1463,12 +1574,12 @@ Kenneth Albanowski (Ekjahds@kjahds.comE), subsequently Itored by Gurusamy Sarathy (Egsar@activestate.comE), Tom Christiansen (Etchrist@perl.comE), Nathan Torkington (Egnat@frii.comE), Charles F. Randall (Ecfr@pobox.comE), -Mike Guy (Emjtg@cam.a.ukE), Dominic Dunlop -(Edomo@computer.orgE), Hugo van der Sanden (Ehv@crypt.org), +Mike Guy (Emjtg@cam.ac.ukE), Dominic Dunlop +(Edomo@computer.orgE), Hugo van der Sanden (Ehv@crypt.orgE), Jarkko Hietaniemi (Ejhi@iki.fiE), Chris Nandor (Epudge@pobox.comE), Jon Orwant (Eorwant@media.mit.eduE, -Richard Foley (Erichard.foley@rfi.netE), and Jesse Vincent -(Ejesse@bestpractical.com). +Richard Foley (Erichard.foley@rfi.netE), Jesse Vincent +(Ejesse@bestpractical.comE), and Craig A. Berry (Ecraigberry@mac.comE). =head1 SEE ALSO