[Reportbug-commits] r596 - in trunk (reportbug reportbug_4merge)
morph-guest at users.alioth.debian.org
morph-guest at users.alioth.debian.org
Wed Aug 6 21:49:15 UTC 2008
Date: Wednesday, August 6, 2008 @ 21:49:13
Author: morph-guest
Revision: 596
renaming reportbug exec to easy branches/modules merge
Added:
trunk/reportbug_4merge
(from rev 594, trunk/reportbug)
Deleted:
trunk/reportbug
Deleted: trunk/reportbug
===================================================================
--- trunk/reportbug 2008-08-06 07:26:56 UTC (rev 595)
+++ trunk/reportbug 2008-08-06 21:49:13 UTC (rev 596)
@@ -1,1831 +0,0 @@
-#! /usr/bin/python
-# -*- python -*-
-# reportbug - Report a bug in the Debian distribution.
-# Written by Chris Lawrence <lawrencc at debian.org>
-# Copyright (C) 1999-2007 Chris Lawrence
-#
-# This program is freely distributable per the following license:
-#
-LICENSE="""\
-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 appears in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation.
-
-I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I
-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."""
-#
-# Version ##VERSION##; see changelog for revision history
-# $Id: reportbug,v 1.98.2.33 2008-04-18 05:38:27 lawrencc Exp $
-
-DEBUGGER = 'lawrencc at debian.org'
-DEFAULT_BTS = 'debian'
-
-import sys, os
-sys.path = ['/usr/share/reportbug'] + sys.path
-
-import optparse
-import re
-import locale
-import commands
-import rfc822
-import gettext
-import textwrap
-
-from reportbuglib import reportbug
-from reportbuglib.reportbug import (
- VERSION, COPYRIGHT,
- MODE_EXPERT, MODE_ADVANCED, MODE_NOVICE, MODE_STANDARD,
- )
-from reportbuglib.rbtempfile import (
- TempFile,
- tempfile_prefix,
- cleanup_temp_file,
- )
-from reportbuglib.reportbug_exceptions import (
- UINotImportable, UINotImplemented,
- NoNetwork, NoPackage, NoBugs, NoReport,
- )
-from reportbuglib import reportbug_submit
-from reportbuglib import checkversions
-from reportbuglib import debianbts
-from reportbuglib import checkbuildd
-from reportbuglib import reportbug_ui_text as ui
-
-try:
- gettext.install('reportbug')
-except IOError:
- pass
-
-# Magic constant time
-MIN_USER_ID = 250
-
-quietly = False
-
-# Cheat for now.
-# ewrite() may put stuff on the status bar or in message boxes depending on UI
-def ewrite(*args):
- return quietly or ui.log_message(*args)
-
-def efail(*args):
- ui.display_failure(*args)
- sys.exit(1)
-
-# Lame message when we store a report as a temp file.
-def stopmsg(filename):
- ui.final_message(
- 'reportbug stopped; your incomplete report is stored as "%s".\n'
- 'This file may be located in a temporary directory; if so, it might '
- 'disappear without any further notice. To recover this file to use '
- 'it as bug report body, please take a look at the "-i FILE, '
- '--include=FILE" option.\n', filename)
-
-# Obscene hack :)
-def system(cmdline):
- try:
- x = os.getcwd()
- except OSError:
- os.chdir('/')
- os.system(cmdline)
-
-def include_file_in_report(message, message_filename,
- attachment_filenames, package_name,
- include_filename, charset, inline=False):
- """ Include a file in the report.
-
- :parameters:
- `message`
- The current text of the message.
- `message_filename`
- The current message filename.
- `attachment_filenames`
- List of current attachment filenames.
- `package_name`
- Name of the package for this report.
- `include_filename`
- Full pathname of the file to be included.
- `inline`
- If True, include the message inline with the message
- text. Otherwise, add the file path to the attachments.
-
- :return value:
- Tuple (`message`, `message_filename`, `attachments`) of
- values as modified during the process of including the new
- file.
-
- """
- if inline:
- try:
- fp = file(include_filename)
- message += '\n*** %s\n%s' % (
- include_filename.decode(charset, 'replace'),
- fp.read().decode(charset, 'replace'))
- fp.close()
- fp, temp_filename = TempFile(
- prefix=tempfile_prefix(package_name))
- fp.write(message.encode(charset, 'replace'))
- fp.close()
- os.unlink(message_filename)
- message_filename = temp_filename
- except (IOError, OSError), exc:
- ewrite('Unable to attach file %s\n%s\n',
- include_filename, str(exc))
- else:
- attachment_filenames.append(include_filename)
-
- return (message, message_filename, attachment_filenames)
-
-def handle_editing(filename, dmessage, options, sendto, attachments, package,
- editor=None, charset='utf-8'):
- if not editor:
- editor = options.editor
- editor = reportbug.which_editor(editor)
- message = None
- skip_editing = False
- while True:
- if not skip_editing:
- (message, changed) = ui.spawn_editor(message or dmessage, filename,
- editor, charset)
- skip_editing = False
- if not message:
- x = ''
- while x != 'y':
- x = ui.select_options('Done editing', 'Ynq',
- {'y': 'Continue (editing done).',
- 'n': "Don't continue yet.",
- 'q': 'Exit without sending report.'})
- if x == 'q':
- stopmsg(filename)
- sys.exit(1)
-
- message = file(filename).read().decode(charset, 'replace')
- changed = True
-
- prompt = 'Submit this report on %s (e to edit)' % package
-
- if options.kudos:
- prompt = 'Send this message (e to edit)'
- ewrite("Message will be sent to %s\n", sendto)
- elif options.outfile:
- ewrite("Report will be saved as %s\n", options.outfile)
- else:
- ewrite("Report will be sent to %s\n", sendto)
-
- if attachments:
- ewrite('Attachments:\n')
- for name in attachments:
- ewrite(' %s\n', name)
-
- subject = re.search('^Subject: ', message, re.M | re.I)
- if not subject:
- ewrite('No subject found in message. Please edit again.\n')
-
- menuopts = "Ynaceilmpq"
-
- if not changed or not subject:
- menuopts = "ynacEilmpq"
-
- # cfr Debian BTS #293361
- if package == 'wnpp':
- for itp_line in debianbts.itp_template.rsplit('\n'):
- # if the line is not empty and it's in the message the user wrote
- if itp_line in message and itp_line != '':
- ewrite("Wrong line: %s\n", itp_line)
- menuopts = "Eq"
- prompt = 'ERROR: you have composed an ITP with fields unchanged from the template; this will NOT be submitted. You should edit all fields so they contain correct values for your ITP (e to edit)'
-
- x = ui.select_options(prompt, menuopts,
- {'y': 'Submit the bug report via email.',
- 'n': "Don't submit the bug report; instead, "
- "save it in a temporary file (exits reportbug).",
- 'q': "Save it in a temporary file and quit.",
- 'a': "Attach a file.",
- 'i': "Include a text file.",
- 'c': "Change editor and re-edit.",
- 'e': 'Re-edit the bug report.',
- 'l': 'Pipe the message through the pager.',
- 'p': 'Print message to stdout.',
- 'm': "Choose a mailer to edit the report."})
- if x in ('a', 'i'):
- invalid = True
- while invalid:
- if x == 'i':
- attachfile = ui.get_filename('Choose a text file to include: ')
- else:
- attachfile = ui.get_filename('Choose a file to attach: ')
- if attachfile:
- attachfile = os.path.expanduser(attachfile)
- if os.access(attachfile, os.R_OK) and os.path.isfile(attachfile):
- invalid = False
- inline = (x == 'i')
- (message, filename, attachments) = include_file_in_report(
- message, filename, attachments, package,
- attachfile, charset, inline=inline)
- if not inline:
- skip_editing = True
- else:
- ewrite("Can't find %s to include!\n", attachfile)
- else:
- break
- elif x == 'c':
- ed = ui.get_filename('Choose editor: ', default=options.editor)
- if ed:
- editor = ed
- elif x == 'm':
- mailers = [(x, '') for x in reportbug.MUA.keys()]
- mailers.sort()
- mailer = ui.menu('Choose a mailer for your report', mailers,
- 'Select mailer: ', default='', empty_ok=True)
- if mailer:
- mailer = reportbug.MUA.get(mailer)
- if mailer:
- options.mua = mailer
- break
- skip_editing = True
- elif x in ('n', 'q'):
- stopmsg(filename)
- sys.exit(1)
- elif x in ('l', 'p'):
- skip_editing = True
- if x == 'l':
- pager = os.environ.get('PAGER', 'sensible-pager')
- os.popen(pager, 'w').write(message.encode(charset, 'replace'))
- else:
- sys.stdout.write(message.encode(charset, 'replace'))
- elif x == 'y':
- if message == dmessage:
- x = ui.select_options(
- 'Report is unchanged. Edit this report or quit', 'Eqs',
- {'q': "Don't submit the bug report; instead, save it "
- "in a temporary file and quit.",
- 'e': 'Re-edit the bug report.',
- 's': 'Send report anyway.'})
- if x == 'q':
- stopmsg(filename)
- sys.exit(1)
- break
- elif x == 's':
- ewrite('Sending empty report anyway...\n')
- break
- else:
- break
-
- return file(filename).read()
-
-def find_package_for(filename, notatty=False, pathonly=False):
- ewrite("Finding package for '%s'...\n", filename)
- (newfilename, packages) = reportbug.find_package_for(filename, pathonly)
- if newfilename != filename:
- filename = newfilename
- ewrite("Resolved as '%s'.\n", filename)
- if not packages:
- ewrite("No packages match.\n")
- return (filename, None)
- elif len(packages) > 1:
- packlist = packages.items()
- packlist.sort()
-
- if notatty:
- print "Please re-run reportbug selecting one of these packages:"
- for pkg, files in packlist:
- print " "+pkg
- sys.exit(1)
-
- packs = []
- for pkg, files in packlist:
- if len(files) > 3:
- files[3:] = ['...']
- packs.append( (pkg, ', '.join(files) ) )
-
- package = ui.menu("Multiple packages match: ", packs, 'Select one '
- 'of these packages: ', any_ok=True)
- return (filename, package)
- else:
- package = packages.keys()[0]
- ewrite("Using package '%s'.\n", package)
- return (filename, package)
-
-def validate_package_name(package):
- if not re.match(r'^[a-z0-9][a-z0-9\-\+\.]+$', package):
- ui.long_message("%s is not a valid package name.", package)
- package = None
- return package
-
-def get_other_package_name(others):
- """Displays the list of pseudo-packages and returns the one selected."""
-
- result = ui.menu("Please enter the name of the package in which you "
- "have found a problem, or choose one of these bug "
- "categories:", others, "Enter a package: ", any_ok=True,
- default='')
- if isinstance(result, basestring):
- # If the package selected is kernel, we replace it with linux-image
- # since it contains additional information useful to maintainer
- if result == 'kernel':
- result = 'linux-image'
- return result
- else:
- return None
-
-def get_package_name(bts='debian', mode=MODE_EXPERT):
- others = debianbts.SYSTEMS[bts].get('otherpkgs')
- prompt = "Please enter the name of the package in which you have found "\
- "a problem"
- if others:
- prompt += ", or type 'other' to report a more general problem."
- else:
- prompt += '.'
-
- options = []
- pkglist = commands.getoutput('apt-cache pkgnames')
- if pkglist:
- options += pkglist.split()
- if others:
- options += others.keys()
-
- package = None
- while package is None:
- package = ui.get_string(prompt, options, force_prompt=True)
- if not package:
- return
- if others and package and package == 'other':
- package = get_other_package_name(others)
- if not package:
- return
- package = validate_package_name(package)
-
- if mode < MODE_STANDARD:
- if package == 'reportbug':
- if not ui.yes_no('Is "reportbug" actually the package you are '
- 'having problems with',
- 'Yes, I am actually experiencing a problem with '
- 'reportbug.',
- 'No, I really meant to file a bug report on '
- 'another package.'):
- return get_package_name(bts, mode)
-
- if mode < MODE_EXPERT:
- if package in ('bugs.debian.org', 'debbugs'):
- if ui.yes_no('Are you reporting a problem with this program '
- '(reportbug)', 'Yes, this is actually a bug in '
- 'reportbug.', 'No, this is really a problem in the '
- 'bug tracking system itself.'):
- package = 'reportbug'
-
- if package in ('general', 'project', 'debian-general', 'base'):
- if not ui.yes_no(
- "Are you sure this bug doesn't apply to a specific package?",
- 'Yes, this bug is truly general.',
- 'No, this is not really a general bug.', False):
- return get_package_name(bts, mode)
-
- if package == 'wnpp':
- if not ui.yes_no(
- 'Are you sure you want to file a WNPP report?',
- 'Yes, I am a developer or know what I\'m doing.',
- 'No, I am not a developer and I don\'t know what wnpp means.',
- False):
- return get_package_name(bts, mode)
-
- if package == 'ftp.debian.org':
- if not ui.yes_no(
- 'Are you sure you want to file a bug on ftp.debian.org?',
- 'Yes, I am a developer or know what I\'m doing.',
- 'No, I am not a developer and I don\'t know what ftp.debian.org is.',
- False):
- return get_package_name(bts, mode)
-
- return package
-
-def special_prompts(package, bts, ui, fromaddr):
- prompts = debianbts.SYSTEMS[bts].get('specials')
- if prompts:
- pkgprompts = prompts.get(package)
- if pkgprompts:
- return pkgprompts(package, bts, ui, fromaddr)
- return
-
-def offer_configuration(options):
- charset = locale.nl_langinfo(locale.CODESET)
- # It would be nice if there were some canonical character set conversion
- if charset.lower() == 'ansi_x3.4-1968':
- charset = 'us-ascii'
- ui.charset = charset
-
- if not options.configure:
- ui.long_message('Welcome to reportbug! Since it looks like this is '
- 'the first time you have used reportbug, we are '
- 'configuring its behavior. These settings will be '
- 'saved to the file "%s", which you will be free to '
- 'edit further.\n\n', reportbug.USERFILE)
- mode = ui.menu('Please choose the default operating mode for reportbug.',
- reportbug.MODES, 'Select mode: ', options.mode,
- order=reportbug.MODELIST)
-
- uis = dict()
- for i in reportbug.AVAILABLE_UIS:
- if (i in reportbug.UIS) and i != 'newt':
- uis[i] = reportbug.UIS[i]
- if len(uis) > 1:
- interface = ui.menu(
- 'Please choose the default interface for reportbug.', uis,
- 'Select interface: ', options.interface)
- else:
- interface = 'text'
-
- online = ui.yes_no('Will reportbug often have direct '
- 'Internet access? (You should answer yes to this '
- 'question unless you know what you are doing and '
- 'plan to check whether duplicate reports have been '
- 'filed via some other channel.)',
- 'Yes, reportbug should assume it has access to the '
- 'network always.',
- 'No, I am only online occasionally to send and '
- 'receive mail.',
- default=(not options.offline))
-
- def_realname, def_email = reportbug.get_email()
-
- try:
- if options.realname:
- realname = options.realname.encode(charset, 'replace')
- else:
- realname = def_realname.encode(charset, 'replace')
- except UnicodeDecodeError:
- realname = ''
-
- realname = ui.get_string('What real name should be used for sending bug '
- 'reports? [%s]' % realname, force_prompt=True)
- if isinstance(realname, str):
- realname = realname.decode(charset, 'replace')
-
- from_addr = ui.get_string(
- 'Which of your email addresses should be used when sending bug '
- 'reports? (Note that this address will be visible in the bug tracking '
- 'system, so you may want to use a webmail address or another address '
- 'with good spam filtering capabilities.) [%s]' %
- (options.email or def_email), force_prompt=True)
-
- stupidmode = not ui.yes_no(
- 'Do you have a "mail transport agent" (MTA) like Exim, Postfix or '
- 'SSMTP configured on this computer to send mail to the Internet?',
- 'Yes, I can run /usr/sbin/sendmail without horrible things happening. '
- 'If you can send email from this machine without setting an SMTP Host '
- 'in your mailer, you should choose this answer.',
- 'No, I need to use an SMTP Host or I don\'t know if I have an MTA.',
- (not options.smtphost))
-
- if stupidmode:
- opts = []
- if options.smtphost:
- opts += [options.smtphost]
- smtphost = ui.get_string(
- 'Please enter the name of your SMTP host. Usually it\'s called '
- 'something like "mail.example.org" or "smtp.example.org". '
- 'Just press ENTER if you don\'t have one or don\'t know.',
- options=opts, force_prompt=True)
- if smtphost:
- stupidmode = False
- else:
- smtphost = ''
-
- if smtphost:
- smtpuser = ui.get_string(
- ('If you need to use a user name to send email via "%s" on your '
- 'computer, please enter that user name. Just press ENTER if you '
- 'don\'t need a user name.' % smtphost), force_prompt=True)
- else:
- smtpuser = ''
-
- if os.path.exists(reportbug.USERFILE):
- try:
- os.rename(reportbug.USERFILE, reportbug.USERFILE+'~')
- except OSError:
- ewrite('Unable to rename %s as %s~\n', reportbug.USERFILE,
- reportbug.USERFILE)
-
- try:
- fd = os.open(reportbug.USERFILE, os.O_WRONLY|os.O_TRUNC|os.O_CREAT,
- 0600)
- except OSError, x:
- ui.long_message('Unable to save %s; most likely, you do not have a '
- 'home directory. Please fix this before using '
- 'reportbug again.\n', reportbug.USERFILE)
- sys.exit(1)
-
- fp = os.fdopen(fd, 'w')
- print >> fp, '# reportbug preferences file'
- print >> fp, '# character encoding: %s' % charset
- print >> fp, '# Version of reportbug this preferences file was written by'
- print >> fp, 'reportbug_version "##VERSION##"'
- print >> fp, '# default operating mode: one of:',
- print >> fp, ', '.join(reportbug.MODELIST)
- print >> fp, 'mode %s' % mode
- print >> fp, '# default user interface'
- print >> fp, 'ui %s' % interface
- print >> fp, '# offline setting - comment out to be online'
- if not online:
- print >> fp, 'offline'
- else:
- print >> fp, '#offline'
- print >> fp, '# name and email setting (if non-default)'
- rn = 'realname "%s"'
- em = 'email "%s"'
- email_addy = (from_addr or options.email or def_email)
- email_name = (realname or options.realname or def_realname)
-
- if email_name != def_realname:
- print >> fp, rn % email_name.encode(charset, 'replace')
- else:
- print >> fp, '# '+(rn % email_name.encode(charset, 'replace'))
-
- if email_addy != def_email:
- print >> fp, em % email_addy
- else:
- print >> fp, '# '+(em % email_addy)
-
- uid = os.getuid()
- if uid < MIN_USER_ID:
- print >> fp, '# Suppress user ID check for this user'
- print >> fp, 'no-check-uid'
-
- if smtphost:
- print >> fp, '# Send all outgoing mail via the following host'
- print >> fp, 'smtphost "%s"' % smtphost
- if smtpuser:
- print >> fp, 'smtpuser "%s"' % smtpuser
- print >> fp, '#smtppasswd "my password here"'
- else:
- print >> fp, '# If you need to enter a user name and password:'
- print >> fp, '#smtpuser "my username here"'
- print >> fp, '#smtppasswd "my password here"'
-
- if stupidmode:
- print >> fp, '# Disable fallback mode by commenting out the following:'
- print >> fp, 'no-cc'
- print >> fp, 'header "X-Debbugs-CC: %s"' % email_addy
- print >> fp, 'smtphost bugs.debian.org'
- else:
- print >> fp, '# If nothing else works, remove the # at the beginning'
- print >> fp, '# of the following three lines:'
- print >> fp, '#no-cc'
- print >> fp, '#header "X-Debbugs-CC: %s"' % email_addy
- print >> fp, '#smtphost bugs.debian.org'
-
- print >> fp, '# You can add other settings after this line. See'
- print >> fp, '# /etc/reportbug.conf for a full listing of options.'
- fp.close()
- ui.final_message('Default preferences file written. To reconfigure, '
- 're-run reportbug with the "--configure" option.\n')
-
-def verify_option(option, opt, value, parser, *args):
- heading, valid = args
- if value == 'help':
- ewrite('%s:\n %s\n' % (heading, '\n '.join(valid)))
- sys.exit(1)
- elif value in valid:
- setattr(parser.values, option.dest, value)
- else:
- ewrite('Ignored bogus setting for %s: %s\n' % (opt, value))
-
-def verify_append_option(option, opt, value, parser, *args):
- heading, valid = args
- if value == 'help':
- ewrite('%s:\n %s\n' % (heading, '\n '.join(valid)))
- sys.exit(1)
- elif value in valid:
- try:
- getattr(parser.values, option.dest).append(value)
- except AttributeError:
- setattr(parser.values, option.dest, [value])
- else:
- ewrite('Ignored bogus setting for %s: %s\n' % (opt, value))
-
-def main():
- global quietly, ui
-
- try:
- locale.setlocale(locale.LC_ALL, '')
- except locale.Error, x:
- print >> sys.stderr, '*** Warning:', x
-
- charset = locale.nl_langinfo(locale.CODESET)
- # It would be nice if there were some canonical character set conversion
- if charset.lower() == 'ansi_x3.4-1968':
- charset = 'us-ascii'
-
- defaults = dict(sendto="submit", mode="novice", mta="/usr/sbin/sendmail",
- check_available=True, query_src=True, debconf=True,
- editor='', offline=False, verify=True, check_uid=True,
- testmode=False, attachments=[], keyid='', body=None,
- bodyfile=None, smtptls=False, smtpuser='', smtppasswd='',
- paranoid=False)
-
- if not sys.stdin.isatty():
- defaults.update({ 'dontquery' : True, 'notatty' : True,
- 'printonly' : True })
-
- # Convention: consider `option.foo' names read-only; they always contain
- # the original value as determined by the cascade of command-line options
- # and configuration files. When we need to adjust a value, we first say
- # "foo = options.foo" and then refer to just `foo'.
- args = reportbug.parse_config_files()
- for option, arg in args.items():
- if option in reportbug.CONFIG_ARGS:
- if isinstance(arg, unicode):
- arg = arg.encode(charset, 'replace')
- defaults[option] = arg
- else:
- sys.stderr.write('Warning: untranslated token "%s"\n' % option)
-
- parser = optparse.OptionParser(
- usage='%prog [options] <package | filename>', version=VERSION)
- parser.set_defaults(**defaults)
- parser.add_option('-c', '--no-config-files', action="store_true",
- dest='noconf', help='do not include conffiles in report')
- parser.add_option('-C', '--class', action='callback', type='string',
- callback=verify_option, dest="klass", metavar='CLASS',
- callback_args=('Permitted report classes:',
- debianbts.CLASSLIST),
- help='specify report class for GNATS BTSes')
- parser.add_option('-d', '--debug', action='store_true', default=False,
- dest='debugmode', help='send report only to yourself')
- parser.add_option('--test', action="store_true", default=False,
- dest="testmode",
- help="operate in test mode (maintainer use only)")
- parser.add_option('-e', '--editor', dest='editor',
- help='specify an editor for your report')
- parser.add_option('-f', '--filename', dest='searchfor',
- help='file to search for')
- parser.add_option('--path', dest='pathonly', action="store_true",
- default=False, help='only search the path with -f')
- parser.add_option('-g', '--gnupg', '--gpg', action='store_const',
- dest='sign', const='gpg',
- help='sign report with GNU Privacy Guard')
- parser.add_option('-G', '--gnus', action='store_const', dest='mua',
- const=reportbug.MUA['gnus'],
- help='send the report using GNUS')
- parser.add_option('--pgp', action='store_const', dest='sign',
- const='pgp', help='sign report with PGP')
- parser.add_option('-K', '--keyid', type="string", dest="keyid",
- help="key ID to use for PGP/GnuPG signatures")
- parser.add_option('-H', '--header', action='append', dest='headers',
- help='add a custom RFC822 header to your report')
- parser.add_option('-P', '--pseudo-header', action='append', dest='pseudos',
- help='add a custom pseudo-header to your report')
- parser.add_option('--license', action='store_true', default=False,
- help='show copyright and license information')
- parser.add_option('-m', '--maintonly', action='store_const',
- dest='sendto', const='maintonly',
- help='send the report to the maintainer only')
- parser.add_option('-M', '--mutt', action='store_const', dest='mua',
- const=reportbug.MUA['mutt'],
- help='send the report using mutt')
- parser.add_option('--mirror', action='append', help='add a BTS mirror',
- dest='mirrors')
- parser.add_option('-a', '--af', action='store_const', dest='mua',
- const=reportbug.MUA['af'],
- help='send the report using af')
- parser.add_option('-n', '--mh', '--nmh', action='store_const', dest='mua',
- help='send the report using mh/nmh',
- const=reportbug.MUA['mh'])
- parser.add_option('--mua', dest='mua',
- help='send the report using the specified mailer')
- parser.add_option('--mta', dest='mta', help='send the report using the '
- 'specified mail transport agent')
- parser.add_option('--list-cc', action='append', dest='listcc',
- help='send a copy to the specified address')
- parser.add_option('-p', '--print', action='store_true', dest='printonly',
- help='output the report to standard output only')
- parser.add_option('--report-quiet', action='store_const', dest='sendto',
- const='quiet', help='file report without any mail to '
- 'the maintainer or tracking lists')
- parser.add_option('-q', '--quiet', action='store_true', dest='quietly',
- help='reduce the verbosity of the output', default=False)
- parser.add_option('-s', '--subject', help='the subject for your report')
- parser.add_option('-x', '--no-cc', dest='nocc', action='store_true',
- help='do not send a copy of the report to yourself')
- parser.add_option('-z', '--no-compress', dest='nocompress',
- action='store_true', help='do not strip blank lines '
- 'and comments from config files')
- parser.add_option('-o', '--output', dest='outfile', help='output the '
- 'report to the specified file')
- parser.add_option('-O', '--offline', help='disable all external queries',
- action='store_true')
- parser.add_option('-i', '--include', action='append',
- help='include the specified file in the report')
- parser.add_option('-A', '--attach', action='append', dest='attachments',
- help='attach the specified file to the report')
- parser.add_option('-b', '--no-query-bts', action='store_true',
- dest='dontquery',help='do not query the BTS for reports')
- parser.add_option('--query-bts', action='store_false', dest='dontquery',
- help='query the BTS for reports')
- parser.add_option('-T', '--tag', action='callback', dest='tags',
- callback=verify_append_option, type='string',
- callback_args=('Permitted tags:',
- debianbts.TAGLIST+['none']),
- help='add the specified tag to the report')
- parser.add_option('--http_proxy', '--proxy', help='use this proxy for '
- 'HTTP accesses')
- parser.add_option('--email', help='specify originating email address')
- parser.add_option('--realname', help='specify real name for your report')
- parser.add_option('--smtphost', help='specify SMTP server for mailing')
- parser.add_option('--tls', help='use TLS to talk to SMTP servers',
- dest="smtptls", action='store_true')
- parser.add_option('--smtpuser', help='username to use for SMTP')
- parser.add_option('--smtppasswd', help='password to use for SMTP')
- parser.add_option('--replyto', '--reply-to', help='specify Reply-To '
- 'address for your report')
- parser.add_option('--query-source', action='store_true', dest='query_src',
- help='query on source packages, not binary packages')
- parser.add_option('--no-query-source', action='store_false',
- dest='query_src', help='query on binary packages only')
- parser.add_option('--debconf', action='store_true',
- help='include debconf settings in your report')
- parser.add_option('--no-debconf', action='store_false', dest='debconf',
- help='exclude debconf settings from your report')
- parser.add_option('-j', '--justification', help='include justification '
- 'for the severity of your report')
- parser.add_option('-V', '--package-version', dest='pkgversion',
- help='specify the version number for the package')
- parser.add_option('-u', '--interface', '--ui', action='callback',
- callback=verify_option, type='string', dest='interface',
- callback_args=('Valid user interfaces',
- reportbug.AVAILABLE_UIS),
- help='choose which user interface to use')
- parser.add_option('-Q', '--query-only', action='store_true',
- dest='queryonly', help='only query the BTS')
- parser.add_option('-t', '--type', action='callback', dest='type',
- callback=verify_option, type='string',
- callback_args=('Valid types of report:',
- ('gnats', 'debbugs')),
- help='choose the type of report to file')
- parser.add_option('-B', '--bts', action='callback', dest='bts',
- callback=verify_option, type='string',
- callback_args=('Valid bug tracking systems',
- debianbts.SYSTEMS.keys()),
- help='choose BTS to file the report with')
- parser.add_option('-S', '--severity', action='callback',
- callback=verify_option, type='string', dest='severity',
- callback_args=('Valid severities', debianbts.SEVLIST),
- help='identify the severity of the report')
- parser.add_option('--template', action='store_true',
- help='output a template report only')
- parser.add_option('--configure', action='store_true',
- help='reconfigure reportbug for this user')
- parser.add_option('--check-available', action='store_true',
- help='check for new releases at packages.debian.org')
- parser.add_option('--no-check-available', action='store_false',
- dest='check_available', help='do not check for new '
- 'releases')
- parser.add_option('--mode', action='callback', help='choose the operating '
- 'mode for reportbug', callback=verify_option,
- type='string', dest='mode',
- callback_args=('Permitted operating modes',
- reportbug.MODES.keys()))
- parser.add_option('-v', '--verify', action='store_true', help='verify '
- 'integrity of installed package using debsums')
- parser.add_option('--no-verify', action='store_false', dest='verify',
- help='do not verify package installation')
- parser.add_option('-k', '--kudos', action='store_true', default=False,
- help='send appreciative email to the maintainer, rather '
- 'than filing a bug report')
- parser.add_option('--check-installed', action='store_true',
- dest='querydpkg', help='check whether the specified '
- 'package is installed when filing a report (default)')
- parser.add_option('--body', dest="body", type="string",
- help="specify the body for the report as a string")
- parser.add_option('--body-file', '--bodyfile', dest="bodyfile",
- type="string",
- help="use the specified file as the body of the report")
- parser.add_option('-I', '--no-check-installed', action='store_false',
- default=True, dest='querydpkg',
- help='don\'t check whether the package is installed')
- parser.add_option('--exit-prompt', action='store_true', dest='exitprompt',
- help='prompt before exiting')
- parser.add_option('--paranoid', action='store_true', dest='paranoid',
- help='show contents of message before sending')
- parser.add_option('--no-paranoid', action='store_false', dest='paranoid',
- help='don\'t show contents of message before sending '
- '(default)')
-
- (options, args) = parser.parse_args()
-
- # Load the interface, *before* the configuration step.
- sys.argv = sys.argv[:1] + list(args)
- if options.interface:
- interface = options.interface
- if interface in ('gnome', 'newt'):
- ui.long_message("The %s interface is not supported. Unless you "
- "are debugging reportbug, please do not use it. "
- "If you are debugging reportbug, please DO NOT "
- "file bugs more serious than 'normal' that "
- "indicate problems with this interface.\n",
- interface)
-
- iface = 'reportbug_ui_%(interface)s' % vars()
- try:
- lib_package = __import__('reportbuglib', fromlist=[iface])
- ui = getattr(lib_package, iface)
- except UINotImportable, msg:
- ui.long_message('*** Unable to import %s interface: %s '
- 'Falling back to text interface.\n',
- interface, msg)
- ewrite('\n')
-
- reportbug_submit.ui = ui
- # Add INTERFACE as an environment variable to access it from the
- # script gathering the special information for reportbug, when
- # a new bug should be filed against it.
- os.environ['INTERFACE'] = interface
-
- iface = UI(options, args)
- if not hasattr(ui, 'run_interface'):
- return iface.user_interface()
- return ui.run_interface(iface.user_interface)
-
-class UI(object):
- def __init__(self, options, args):
- self.options = options
- self.args = args
-
- def user_interface(self):
- body = ''
- filename = None
- notatty = not ui.ISATTY
-
- charset = locale.nl_langinfo(locale.CODESET)
- # It would be nice if there were some canonical character set conversion
- if charset.lower() == 'ansi_x3.4-1968':
- charset = 'us-ascii'
-
- # Allow the UI to know what charset we're using
- ui.charset = charset
-
- if self.options.configure:
- offer_configuration(self.options)
- sys.exit(0)
- elif self.options.license:
- print COPYRIGHT
- print
- print LICENSE
- sys.exit(0)
-
- # These option values may get adjusted below, so give them a variable name.
- sendto = self.options.sendto
- check_available = self.options.check_available
- dontquery = self.options.dontquery
- headers = self.options.headers or []
- pseudos = self.options.pseudos or []
- mua = self.options.mua
- pkgversion = self.options.pkgversion
- quietly = self.options.quietly
- severity = self.options.severity
- smtphost = self.options.smtphost
- subject = self.options.subject
- bts = self.options.bts or 'debian'
- sysinfo = debianbts.SYSTEMS[bts]
- rtype = self.options.type or sysinfo.get('type')
- attachments = self.options.attachments
- pgp_addr = self.options.keyid
-
- if self.options.body:
- body = textwrap.fill(self.options.body)
- elif self.options.bodyfile:
- try:
- body = file(self.options.bodyfile).read()
- except:
- ewrite('Unable to read body from file %s.\n', self.options.bodyfile)
- sys.exit(1)
-
- if body and not body.endswith('\n'):
- body += '\n'
-
- if self.options.queryonly:
- check_available = False
-
- if self.options.offline:
- check_available = False
- dontquery = True
-
- if self.options.tags:
- taglist = self.options.tags
- if 'none' in taglist:
- taglist = []
- else:
- taglist = []
-
- if self.options.testmode:
- self.options.debugmode = True
- self.options.tags = ['none']
- check_available = False
- dontquery = True
- severity = 'normal'
- subject = 'testing'
- taglist = []
-
- interactive = True
- if self.options.template:
- check_available = interactive = False
- dontquery = quietly = notatty = True
- mua = smtphost = None
- severity = severity or 'wishlist'
- subject = subject or 'none'
- taglist = taglist or []
-
- if self.options.outfile or self.options.printonly:
- mua = smtphost = None
-
- if smtphost and smtphost.lower() == 'master.debian.org':
- ui.long_message('*** Warning: master.debian.org is no longer an appropriate smtphost setting for reportbug; please update your .reportbugrc file.\n')
- smtphost = 'bugs.debian.org'
-
- if attachments and mua:
- ewrite('Attachments are incompatible with using an MUA. They will be ignored.\n')
- attachments = []
-
- if reportbug.first_run():
- if not self.args:
- offer_configuration(self.options)
- main()
- sys.exit(0)
- else:
- ewrite('Warning: no reportbug configuration found. Proceeding in %s mode.\n' % self.options.mode)
-
- mode = reportbug.MODELIST.index(self.options.mode)
-
- # Disable signatures when in printonly or mua mode
- # (since they'll be bogus anyway)
- sign = self.options.sign
- if (self.options.mua or self.options.printonly) and sign:
- sign = ''
- if self.options.mua:
- ewrite('The signature option is ignored when using an MUA.\n')
- elif self.options.printonly:
- ewrite('The signature option is ignored when producing a template.\n')
-
- uid = os.getuid()
- if uid < MIN_USER_ID:
- if notatty and not uid:
- ewrite("reportbug will not run as root non-interactively.\n")
- sys.exit(1)
-
- if not uid or self.options.check_uid:
- if not uid:
- message = "Running 'reportbug' as root is probably insecure!"
- else:
- message = "Running 'reportbug' as an administrative user "\
- "is probably not a good idea!"
- message += ' Continue'
-
- if not ui.yes_no(message, 'Continue with reportbug.', 'Exit.',
- False):
- ewrite("reportbug stopped.\n")
- sys.exit(1)
-
- if (reportbug.first_run() and not self.args):
- offer_configuration(self.options)
- ewrite('To report a bug, please rerun reportbug.\n')
- sys.exit(0)
-
- foundfile = None
- package = None
- if not len(self.args) and not self.options.searchfor and not notatty:
- package = get_package_name(bts, mode)
- elif len(self.args) > 1:
- ewrite("Please report one bug at a time.\n")
- ewrite("[Did you forget to put all switches before the "
- "package name?]\n")
- sys.exit(1)
- elif self.options.searchfor:
- (foundfile, package) = find_package_for(self.options.searchfor, notatty,
- self.options.pathonly)
- elif len(self.args):
- package = self.args[0]
- if package and package.startswith('/'):
- (foundfile, package) = find_package_for(package, notatty)
-
- others = debianbts.SYSTEMS[bts].get('otherpkgs')
- if package == 'other' and others:
- package = get_other_package_name(others)
-
- if not package:
- efail("No package specified; stopping.\n")
-
- tfprefix = tempfile_prefix(package)
- if self.options.interface == 'text':
- ewrite('*** Welcome to reportbug. Use ? for help at prompts. ***\n')
-
- try:
- blah = u'hello'.encode(charset)
- except LookupError:
- ui.long_message(
- 'Unable to use specified character set "%s"; you probably need '
- 'either cjkcodecs (for users of Asian locales) or iconvcodec '
- 'installed.\nFalling back to ASCII encoding.\n', charset)
- charset = 'us-ascii'
- else:
- ewrite("Detected character set: %s\n"
- "Please change your locale if this is incorrect.\n\n", charset)
-
- fromaddr = reportbug.get_user_id(self.options.email, self.options.realname, charset)
- ewrite("Using '%s' as your from address.\n", fromaddr.encode(charset, 'replace'))
- fromaddr = fromaddr.encode('utf-8')
- if self.options.debugmode:
- sendto = fromaddr
-
- edname = reportbug.which_editor(self.options.editor)
- baseedname = os.path.basename(edname)
- if baseedname == 'sensible-editor':
- edname = reportbug.realpath('/usr/bin/editor')
-
- if not notatty and 'vi' in baseedname and mode < MODE_STANDARD and \
- 'EDITOR' not in os.environ:
- if not ui.yes_no('You appear to be using the "vi" editor, which is '
- 'not suited for new users. You probably want to '
- 'change this setting by using "update-alternatives '
- '--config editor" as root. (You can bypass this '
- 'message in the future by using reportbug in '
- '"standard" mode or higher.) '
- 'Do you want to continue?',
- 'Continue filing this report.',
- 'Stop reportbug to change editors.', False):
- ewrite('Exiting per user request.\n')
- sys.exit(1)
-
- incfiles = u""
- if self.options.include:
- for f in self.options.include:
- if os.path.exists(f):
- fp = file(f)
- incfiles = u'%s\n*** %s\n%s' % (
- incfiles, f.decode('utf-8', 'replace'),
- fp.read().decode('utf-8', 'replace'))
- fp.close()
- else:
- ewrite("Can't find %s to include!\n", f)
- sys.exit(1)
- incfiles += '\n'
-
- pkgavail = maintainer = origin = src_name = state = ''
- depends = []
- recommends = []
- suggests = []
- conffiles = []
- reportinfo = None
- isvirtual = (package in sysinfo.get('otherpkgs', {}).keys() and
- package not in sysinfo.get('nonvirtual', []))
- issource = installed = usedavail = False
- status = None
-
- if not pkgversion and self.options.querydpkg and \
- sysinfo.get('query-dpkg', True):
- ewrite("Getting status for %s...\n", package)
- status = reportbug.get_package_status(package)
-
- pkgavail, installed = status[1], status[6]
- # Packages that only exist to do weird dependency things
- deppkgs = sysinfo.get('deppkgs')
- if pkgavail and deppkgs:
- if installed and package in deppkgs:
- depends = status[2]
- if depends:
- newdepends = []
- for x in depends:
- newdepends.extend(x)
- depends = newdepends
- if len(depends) == 1:
- if mode < MODE_ADVANCED:
- ewrite('Dependency package "%s" corresponds to '
- 'actual package "%s".\n', package, depends[0])
- package = depends[0]
- else:
- opts = [(x,
- (reportbug.get_package_status(x)[11] or
- 'not installed')) for x in depends]
- if mode >= MODE_ADVANCED:
- opts += [(package,
- status[11]+' (dependency package)')]
-
- package = ui.menu('%s is a dependency package. '
- 'Which of the following '
- 'packages is the bug in?' % package,
- opts,
- 'Select one of these packages: ')
- ewrite("Getting status for %s...\n", package)
- status = reportbug.get_package_status(package)
- pkgavail, installed = status[1], status[6]
-
- if not pkgavail and not isvirtual:
- # Look for a matching source package
- packages = reportbug.get_source_package(package)
- if len(packages) > 0:
- src = package
- if len(packages) and not notatty:
- packages.sort()
- if src not in [x[0] for x in packages]:
- packages.append( (src, 'Source package') )
-
- if len(packages) > 1:
- package = ui.menu(
- 'Which of the following packages is the bug in?',
- packages, empty_ok=True,
- prompt='Select one of these packages: ')
- else:
- package = packages[0][0]
-
- if not package:
- efail("No package specified; stopping.\n")
-
- if package != src:
- ewrite("Getting status for %s...\n", package)
- status = reportbug.get_package_status(package)
- pkgavail, installed = status[1], status[6]
- elif len(packages) > 1:
- issource = True
- else:
- ewrite('No matching source or binary packages.\n')
-
- if (not installed and not isvirtual and not issource) and not notatty:
- packages = reportbug.packages_providing(package)
- tmp = pack = None
- if not packages:
- if ui.yes_no(
- 'A package named "%s" does not appear to be installed; do '
- 'you want to search for a similar-looking filename in '
- 'an installed package' % package,
- 'Look for a file with a similar filename.',
- 'Continue filing with this package name.', True):
- pkgavail = False
- else:
- pack = package
- packages = [(package, '')]
- ewrite("Getting available info for %s...\n", package)
- status = reportbug.get_package_status(package, avail=True)
- check_available = False
- usedavail = True
-
- if not packages and not pkgavail and not pack:
- (tmp, pack) = find_package_for(package, notatty)
- if pack:
- status = None
- if not ui.yes_no(
- "A package named '%s' does not appear to be installed "
- "on your system; however, '%s' contains a file named "
- "'%s'. Do you want to file your report on the "
- "package reportbug found" % (package, pack, tmp),
- 'Yes, use the package specified.',
- 'No, give up the search.'):
- efail("Package not installed; stopping.\n")
-
- if not status and pack:
- foundfile, package = tmp, pack
- ewrite("Getting status for %s...\n", package)
- status = reportbug.get_package_status(package)
- elif not packages:
- if not ui.yes_no(
- 'This package does not appear to be installed; continue '
- 'with this report', 'Ignore this problem and continue.',
- 'Exit without filing a report.', False):
- efail("Package not installed; stopping.\n")
- elif (len(packages) > 1) or (packages[0][0] != package):
- this_package = [(package, 'Uninstalled/non-existent package')]
- packages.sort()
- package = ui.menu('Which of the following installed packages '
- 'is the bug in?', packages + this_package,
- 'Select one of these packages: ',
- empty_ok=True)
- if not package:
- efail("No package specified; stopping.\n")
- else:
- ewrite("Getting status for %s...\n", package)
- status = reportbug.get_package_status(package)
- elif not pkgavail and not notatty and not isvirtual and not issource:
- if not ui.yes_no(
- 'This package does not appear to exist; continue',
- 'Ignore this problem and continue.',
- 'Exit without filing a report.', False):
- efail("Package does not exist; stopping.\n")
- sys.exit(1)
-
- (pkgversion, pkgavail, depends, recommends, conffiles, maintainer,
- installed, origin, vendor, reportinfo, priority, desc, src_name,
- fulldesc, state, suggests) = status
-
- buginfo = '/usr/share/bug/' + package
- bugexec = submitas = submitto = presubj = None
- reportwith = []
- supplemental = []
- if os.path.isfile(buginfo) and os.access(buginfo, os.X_OK):
- bugexec = buginfo
- elif os.path.isdir(buginfo):
- if os.path.isfile(buginfo+'/script') and os.access(buginfo+'/script', os.X_OK):
- bugexec = buginfo+'/script'
-
- if os.path.isfile(buginfo+'/presubj'):
- presubj = buginfo+'/presubj'
-
- if os.path.isfile(buginfo+'/control'):
- submitas, submitto, reportwith, supplemental = \
- reportbug.parse_bug_control_file(buginfo+'/control')
- elif os.path.isfile('/usr/share/bug/default/'+package) \
- and os.access('/usr/share/bug/default/'+package, os.X_OK):
- bugexec = '/usr/share/bug/default/'+package
- elif os.path.isdir('/usr/share/bug/default/'+package):
- buginfo = '/usr/share/bug/default/'+package
- if os.path.isfile(buginfo+'/script') and os.access(buginfo+'/script',
- os.X_OK):
- bugexec = buginfo+'/script'
-
- if os.path.isfile(buginfo+'/presubj'):
- presubj = buginfo+'/presubj'
-
- if os.path.isfile(buginfo+'/control'):
- submitas, submitto, reportwith, supplemental = \
- reportbug.parse_bug_control_file(buginfo+'/control')
-
- if submitas and (submitas not in reportwith):
- reportwith += [submitas]
-
- if reportwith:
- # Remove current package from report-with list
- reportwith = [x for x in reportwith if x != package]
-
- if (pkgavail and self.options.verify and os.path.exists('/usr/bin/debsums')
- and not (notatty or self.options.kudos) and state == 'installed'):
- ewrite('Verifying package integrity...\n')
- rc, output = commands.getstatusoutput('/usr/bin/debsums -s'+
- commands.mkarg(package))
- if rc:
- if not ui.yes_no(
- 'There may be a problem with your installation of '+package+
- ';\nthe following files appear to be missing or changed:\n'+
- output+'\nDo you still want to file a report',
- 'Ignore this problem and continue. This may be '
- 'appropriate if you have fixed the package manually already. '
- 'This problem may also result from the use of localepurge.',
- 'Exit without filing a report.', False, nowrap=True):
- efail("Package integrity check failed; stopping.\n")
-
- if not pkgversion or usedavail or (not pkgavail and
- not self.options.pkgversion):
- if not (isvirtual or notatty):
- pkgversion = ui.get_string('Please enter the version of the '
- 'package this report applies to '
- '(blank OK)', force_prompt=True)
- elif (check_available and not (self.options.kudos or notatty or self.options.offline)
- and state == 'installed' and bts == 'debian'):
- arch = reportbug.get_arch()
- check_more = (mode > MODE_STANDARD)
- if check_more:
- ewrite('Checking for newer versions at packages.debian.org,'+
- ' incoming.debian.org and http://ftp-master.debian.org/new.html\n')
- else:
- ewrite('Checking for newer versions at packages.debian.org...\n')
- (avail, toonew) = checkversions.check_available(
- package, pkgversion, check_incoming=check_more,
- check_newqueue=check_more,
- http_proxy=self.options.http_proxy, arch=arch)
- if toonew:
- if not ui.yes_no(
- '\nYour version of %s (%s) is newer than that in Debian!\n'
- 'Do you still want to file a report' % (package, pkgversion),
- 'Ignore this problem and continue. This may be '
- 'appropriate if you know this bug is present in older '
- 'releases of the package, or you\'re running a mixed '
- 'stable/testing installation.',
- 'Exit without filing a report.', False):
- efail("Newer released version; stopping.\n")
-
- if avail:
- availtext = ''
- availlist = avail.keys()
- availlist.sort()
- for rel in availlist:
- availtext += ' %s: %s\n' % (rel, avail[rel])
-
- if not ui.yes_no(
- ('\nYour version (%s) of %s appears to be out of date.\nThe '
- 'following newer release(s) are available in the Debian '
- 'archive:\n' % (pkgversion, package))+availtext+
- 'Do you still want to file a report',
- 'Ignore this problem and continue. This may be '
- 'appropriate if you know this bug is still present in more '
- 'recent releases of the package.',
- 'Exit without filing a report.', False, nowrap=True):
- efail("Newer released version; stopping.\n")
-
- bts = DEFAULT_BTS
- if self.options.bts:
- bts = self.options.bts
- ewrite("Will send report to %s (per request).\n",
- debianbts.SYSTEMS[bts].get('name', bts))
- elif origin:
- if origin.lower() == bts:
- ewrite("Package originates from %s.\n", vendor or origin)
- reportinfo = None
- elif origin.lower() in debianbts.SYSTEMS.keys():
- ewrite("Package originates from %s; overriding your system "
- "selection.\n", vendor or origin)
- bts = origin.lower()
- sysinfo = debianbts.SYSTEMS[bts]
- elif reportinfo:
- ewrite("Unknown origin %s; will send to %s.\n", origin,
- reportinfo[1])
- rtype, submitto = reportinfo
- elif submitto:
- ewrite("Unknown origin %s; will send to %s.\n", origin, submitto)
- else:
- ewrite("Unknown origin %s; will send to %s.\n", origin, bts)
- elif reportinfo:
- rtype, submitto = reportinfo
- ewrite("Will use %s protocol talking to %s.\n", rtype, submitto)
- dontquery = True
- else:
- lsbr = commands.getoutput('lsb_release -si 2>/dev/null')
- if lsbr:
- distro = lsbr.strip().lower()
- if distro in debianbts.SYSTEMS:
- bts = distro
- ewrite("Will send report to %s (per lsb_release).\n",
- debianbts.SYSTEMS[bts].get('name', bts))
-
- if rtype == 'mailto':
- rtype = 'debbugs'
- dontquery = True
-
- special = False
- if not body and not subject and not notatty:
- res = special_prompts(package, bts, ui, fromaddr)
- if res:
- (subject, severity, h, ph, body, query) = res
- headers += h
- pseudos += ph
- if not query:
- dontquery = True
- special = True
-
- exinfo = None
- if not (dontquery or notatty or self.options.kudos):
- pkg, src = package, issource
- if self.options.query_src:
- src = True
- if src_name:
- pkg = src_name
- try:
- exinfo = ui.handle_bts_query(pkg, bts, self.options.mirrors,
- self.options.http_proxy,
- source=src,
- queryonly=self.options.queryonly,
- version=pkgversion)
- except UINotImplemented:
- exinfo = None
- except NoNetwork:
- sys.exit(1)
- except NoPackage:
- if not self.options.queryonly and maintainer and ui.yes_no(
- 'There is no record of this package in the bug tracking '
- 'system.\nSend report directly to maintainer',
- 'Send the report to the maintainer (%s).' % maintainer,
- 'Send the report to the BTS anyway.'):
- rtype = 'debbugs'
- sendto = maintainer
- except NoBugs:
- ewrite('No bug reports found.\n')
- except NoReport:
- if self.options.queryonly:
- ewrite('Exiting at user request.\n')
- else:
- ewrite('Nothing new to report; exiting.\n')
- return
-
- if self.options.queryonly and not exinfo:
- return
-
- ccaddr = os.environ.get('MAILCC')
- if self.options.nocc:
- bccaddr = os.environ.get('MAILBCC')
- else:
- bccaddr = os.environ.get('MAILBCC', fromaddr)
-
- if maintainer:
- mstr = u"Maintainer for %s is '%s'.\n" % (package, maintainer)
- ewrite(mstr.encode(charset, 'replace'))
- if 'qa.debian.org' in maintainer:
- ui.long_message('''\
-This package is currently "orphaned"; if you are a current or prospective
-Debian developer, you might consider adopting it. Please be aware that your
-report may not be resolved for a while, and that packages that have been
-orphaned for a long period of time are often removed from the archive.\n''')
- ui.ewrite('\nFor more details, please see: http://www.debian.org/devel/wnpp/\n')
-
- if self.options.kudos:
- sendto = '%s at packages.debian.org' % package
-
- depinfo = ""
- # Grab dependency list, removing version conditions.
- if (depends or recommends or suggests) and not self.options.kudos:
- ewrite("Looking up dependencies of %s...\n", package)
- depinfo = (reportbug.get_dependency_info(package, depends) +
- reportbug.get_dependency_info(package, recommends, "recommends") +
- reportbug.get_dependency_info(package, suggests, "suggests"))
-
- if reportwith and not self.options.kudos:
- for extrapackage in reportwith:
- ewrite("Getting status for related package %s...\n", extrapackage)
- extrastatus = reportbug.get_package_status(extrapackage)
- if extrastatus[2]:
- extradepends = [x for x in extrastatus[2] if package not in x]
- ewrite("Looking up dependencies of related package %s...\n", extrapackage)
- depinfo += reportbug.get_dependency_info(extrapackage, extradepends)
-
- if supplemental and not self.options.kudos:
- ewrite("Looking up status of additional packages...\n")
- depinfo += reportbug.get_dependency_info(
- package, [[x] for x in supplemental], rel='is related to')
-
- confinfo = []
- if conffiles and not self.options.kudos:
- ewrite("Getting changed configuration files...\n")
- confinfo, changed = reportbug.get_changed_config_files(
- conffiles, nocompress)
-
- if self.options.noconf and changed:
- for f in changed:
- confinfo[f] = 'changed [not included]'
- elif changed and not notatty:
- while 1:
- x = ui.select_self.options(
- "*** WARNING: The following configuration files have been "
- "modified:\n"+ "\n".join(changed)+
- "\nSend modified configuration files", 'Ynd',
- {'y':'Send your modified configuration files.',
- 'n':"Don't send modified configuration files.",
- 'd':'Display modified configuration files.'})
- if x == 'n':
- for f in changed:
- confinfo[f] = 'changed [not included]'
- break
- elif x == 'd':
- PAGER = os.environ.get('PAGER', '/usr/bin/sensible-pager')
- system(PAGER+' '+' '.join(changed))
- else:
- break
-
- conftext = u''
- if confinfo:
- conftext = u'\n-- Configuration Files:\n'
- files = confinfo.keys()
- files.sort()
- for f in files:
- conftext = conftext + u'%s %s\n' % (f, confinfo[f])
-
- if (self.options.debconf and os.path.exists('/usr/bin/debconf-show') and
- not self.options.kudos and installed):
- showpkgs = package
- if reportwith:
- showpkgs += ' ' + ' '.join(reportwith)
- (status, output) = commands.getstatusoutput(
- 'DEBCONF_SYSTEMRC=1 DEBCONF_NOWARNINGS=yes '
- '/usr/bin/debconf-show %s' % showpkgs )
- if status:
- conftext += '\n-- debconf-show failed\n'
- elif output:
- output = output.decode('utf-8', 'replace')
- outstr = output.encode(charset, 'replace')
- if (notatty or ui.yes_no(
- "*** The following debconf settings were detected:\n"
- +outstr+"\nInclude these settings in your report",
- 'Send your debconf settings.',
- "Don't send your debconf settings.", nowrap=True)):
- conftext += u'\n-- debconf information:\n%s\n' % output
- else:
- conftext += u'\n-- debconf information excluded\n'
- else:
- conftext += u'\n-- no debconf information\n'
-
- ewrite('\n')
- prompted = False
- if interactive and not (self.options.kudos or exinfo) and presubj:
- ui.display_report(file(presubj).read()+'\n')
-
- if self.options.kudos:
- subject = subject or ('Thanks for packaging %s!' % package)
- elif exinfo:
- if special:
- body = ''
- prompted = True
- subject = ui.get_string(
- 'Please provide a subject for your response; no subject will '
- 'stop reportbug.', force_prompt=True)
- # Check to make sure the bug still exists to avoid auto-reopens
- if subject and pkgversion:
- if not ui.yes_no('Does this bug still exist in version %s '
- 'of this package?' % pkgversion,
- 'Yes, it does.',
- 'No, it doesn\'t (or I don\'t know).',
- default=False):
- pkgversion = None
- elif not subject and not notatty:
- prompted = True
- subject = ui.get_string(
- 'Please briefly describe your problem (you can elaborate in '
- 'a moment; an empty response will stop reportbug). This will '
- 'be the bug email subject, so write a concise summary of what '
- 'is wrong with the package, for example, "fails to send email" '
- 'or "does not start with -q option specified."', force_prompt=True)
-
- if not subject:
- efail("No subject specified; stopping.\n")
-
- if len(subject) > 100 and prompted and mode < MODE_EXPERT:
- subject = ui.get_string(
- 'Your description is a bit long; please enter a shorter subject. '
- '(An empty response will retain the existing subject.)',
- force_prompt=True) or subject
- if package != 'wnpp' and prompted and mode < MODE_EXPERT:
- if foundfile:
- subject = foundfile + ": " + subject
- ewrite("Rewriting subject to '%s'\n", subject)
- elif (not re.match(r"\S+:\s", subject) and package not in subject):
- subject = package + ": " + subject
- ewrite("Rewriting subject to '%s'\n", subject)
-
- listcc = self.options.listcc
- if not listcc:
- listcc = []
-
- if not listcc and mode > MODE_STANDARD and rtype == 'debbugs' and not self.options.testmode and not self.options.template:
- listcc += ui.get_multiline('Enter any additional addresses this report should be sent to; press ENTER after each address.')
-
- if severity and rtype:
- severity = debianbts.convert_severity(severity, rtype)
-
- klass = self.options.klass
- if not notatty and not (exinfo or self.options.kudos):
- if not severity:
- if rtype == 'gnats':
- severities = debianbts.SEVERITIES_gnats
- default = 'non-critical'
- else:
- severities = debianbts.SEVERITIES
- default = 'normal'
-
- severity = ui.menu("How would you rate the severity of this "
- "problem or report?", severities,
- 'Please select a severity level: ',
- default=default, order=debianbts.SEVLIST)
-
- if rtype == 'gnats':
- # Class of report
- klass = ui.menu("What sort of problem are you reporting?",
- debianbts.CLASSES, 'Please select a class: ',
- default='sw-bug', order=debianbts.CLASSLIST)
-
- severity = severity or 'normal'
-
- justification = self.options.justification
- if rtype == 'debbugs' and package != 'wnpp' and mode < MODE_EXPERT:
- if severity in ('critical', 'grave'):
- justification = ui.menu(
- 'You are reporting a ' +severity+' bug; which of the '
- 'following criteria does it meet?',
- debianbts.JUSTIFICATIONS[severity],
- 'Please select the impact of the bug: ', default='unknown')
- elif severity == 'serious':
- justification = ui.get_string(
- 'You are reporting a serious bug; which section of the '
- 'Debian Policy Manual contains the "must" or "required" '
- 'directive that it violates (E.g., "1.2.3")? '
- 'Just type "unknown" if you are not sure (that would '
- 'downgrade severity to normal).', force_prompt=True)
- if re.match('[0-9]+\.[0-9.]+', justification):
- justification = 'Policy ' + justification
- elif not justification:
- justification = 'unknown'
-
- if justification == 'unknown':
- justification = ''
- severity = 'normal'
- ewrite('Severity downgraded to "normal".\n')
-
- if severity == 'does-not-build':
- if pkgversion and not src_name:
- src_name = package
- if src_name and check_available and not notatty:
- ewrite('Checking buildd.debian.org for past builds of %s...\n',
- src_name)
- built = checkbuildd.check_built(src_name,
- http_proxy=self.options.http_proxy)
-
- if built:
- ewrite('Successful past builds... treating as serious.\n')
- severity = 'serious'
- justification = 'no longer builds from source'
- else:
- ewrite('No successful builds... treating as important.\n')
- severity = 'important'
- justification = 'fails to build from source'
- else:
- if notatty:
- severity = 'important'
- justification = 'fails to build from source'
- else:
- if ui.yes_no(
- 'Has this package successfully been built for this '
- 'architecture in the past (you can look this up at '
- 'buildd.debian.org)',
- 'Yes, this is a recently-introduced problem.',
- 'No, it has always been this way.'):
- severity = 'serious'
- justification = 'no longer builds from source'
- else:
- severity = 'important'
- justification = 'fails to build from source'
-
- HOMEDIR = os.environ.get('HOME', '/')
-
- if (rtype == 'debbugs' and not self.options.tags and
- not (notatty or self.options.kudos or exinfo) and package not in ('wnpp','ftp.debian.org') and
- mode > MODE_NOVICE):
- # Multiple-choice checkbox
- if severity in ('grave', 'critical', 'serious'):
- tags = debianbts.TAGS.copy()
- tags.update(debianbts.CRITICAL_TAGS)
- tagorder = debianbts.TAGLIST + debianbts.CRITICAL_TAGLIST
- else:
- tags = debianbts.TAGS
- tagorder = debianbts.TAGLIST
-
- taglist = ui.select_multiple(
- 'Do any of the following apply to this report?', tags,
- 'Please select tags: ', order=tagorder,
- extras=debianbts.EXTRA_TAGS)
-
- patch = ('patch' in taglist)
-
- if justification and 'security' not in taglist and 'security' in \
- justification:
- ewrite('Adding security tag to this report.\n')
- taglist += ['security']
-
- if taglist:
- tags = ' '.join(taglist)
- else:
- tags = ''
-
- # Execute bug script
- if (interactive or self.options.template) and bugexec and not self.options.kudos:
- if os.path.exists('handle_bugscript'):
- handler = './handle_bugscript'
- else:
- handler = '/usr/share/reportbug/handle_bugscript'
-
- fh, filename = TempFile(prefix=tfprefix)
- fh.close()
- system('%s %s %s' % (handler, commands.mkarg(bugexec),
- commands.mkarg(filename)))
-
- addinfo = None
- if not self.options.noconf:
- fp = open(filename)
- addinfo = u"\n-- Package-specific info:\n"+fp.read().decode('utf-8', 'replace')
- fp.close()
-
- cleanup_temp_file(filename)
- if addinfo and incfiles:
- incfiles = addinfo + u"\n" + incfiles
- elif addinfo:
- incfiles = addinfo
-
- if bts == 'debian' and 'security' in taglist:
- ewrite('Will send a CC of this report to the Debian Security and Testing Security Team.\n')
- listcc += ['Debian Security Team <team at security.debian.org>']
- listcc += ['Debian Testing Security Team <secure-testing-team at lists.alioth.debian.org>']
-
- if listcc:
- headers.append('X-Debbugs-CC: '+', '.join(listcc))
-
- # Prepare bug report
- if self.options.kudos:
- message = u'\n\n'
- if not mua:
- SIGFILE = os.path.join(HOMEDIR, '.signature')
- try:
- message = u"\n\n-- \n"+file(SIGFILE).read().decode('utf-8', 'replace')
- except IOError:
- pass
- else:
- message = reportbug.generate_blank_report(
- submitas or package, pkgversion, severity, justification,
- depinfo, conftext, foundfile, incfiles, bts, exinfo, rtype,
- klass, subject, tags, body, mode, pseudos)
-
- # Substitute server email address
- if submitto and '@' not in sendto:
- if '@' in submitto:
- sendto = submitto
- else:
- if exinfo:
- if sendto != 'submit':
- sendto = '%d-%s' % (exinfo, sendto)
- else:
- sendto = str(exinfo)
-
- sendto = sendto+'@'+submitto
- elif '@' not in sendto:
- if exinfo:
- if sendto != 'submit':
- sendto = '%d-%s' % (exinfo, sendto)
- else:
- sendto = str(exinfo)
-
- try:
- sendto = sysinfo['email'] % sendto
- except TypeError:
- sendto = sysinfo['email']
-
- sendto = rfc822.dump_address_pair((sysinfo['name']+
- ' Bug Tracking System', sendto))
-
- mailing = not (mua or self.options.printonly or self.options.template)
- message = u"Subject: %s\n%s" % (subject, message)
-
- if mailing:
- fh, filename = TempFile(prefix=tfprefix)
- fh.write(message.encode(charset, 'replace'))
- fh.close()
- oldmua = mua or self.options.mua
- if not self.options.body and not self.options.bodyfile:
- message = handle_editing(filename, message, self.options,
- sendto, attachments, package,
- charset=charset)
- if not oldmua and self.options.mua:
- mua = self.options.mua
- if mua:
- mailing = False
- elif not sendto:
- print message,
- cleanup_temp_file(filename)
- return
-
- cleanup_temp_file(filename)
-
- if not mua and patch and not attachments and not notatty:
- while True:
- patchfile = ui.get_filename(
- 'What is the filename of the patch (if none, or you have '
- 'already included it, just press ENTER)?',
- force_prompt=True)
- if patchfile:
- attachfile = os.path.expanduser(patchfile)
- if os.path.exists(attachfile):
- attachments.append(attachfile)
- break
- else:
- ewrite('%s not found!', attachfile)
- else:
- break
-
- body, headers, pseudoheaders = reportbug.cleanup_msg(message,headers,rtype)
-
- if sign:
- ewrite('Passing message to %s for signature...\n', sign)
- oldbody = body
- body = reportbug_submit.sign_message(body, fromaddr, package, pgp_addr,
- sign)
- if not body:
- ewrite('Signature failed; sending message unsigned.\n')
- body = oldbody
-
- if pseudoheaders:
- body = '\n'.join(pseudoheaders)+'\n\n'+body
-
- # Strip the body of useless whitespace at the end, then put a final
- # newline in the message. See #234963.
- body = body.rstrip('\n')+'\n'
-
- reportbug_submit.send_report(
- body, attachments, mua, fromaddr, sendto, ccaddr, bccaddr,
- headers, package, charset, mailing, sysinfo, rtype, exinfo,
- self.options.replyto, self.options.printonly, self.options.template,
- self.options.outfile, self.options.mta, self.options.kudos, self.options.smtptls,
- smtphost, self.options.smtpuser, self.options.smtppasswd, self.options.paranoid)
-
- if self.options.exitprompt:
- ui.get_string('Please press ENTER to exit reportbug: ')
- return
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- ewrite("\nreportbug: exiting due to user interrupt.\n")
- except debianbts.Error, x:
- ewrite('error accessing BTS: %s\n' % x)
Copied: trunk/reportbug_4merge (from rev 594, trunk/reportbug)
===================================================================
--- trunk/reportbug_4merge (rev 0)
+++ trunk/reportbug_4merge 2008-08-06 21:49:13 UTC (rev 596)
@@ -0,0 +1,1831 @@
+#! /usr/bin/python
+# -*- python -*-
+# reportbug - Report a bug in the Debian distribution.
+# Written by Chris Lawrence <lawrencc at debian.org>
+# Copyright (C) 1999-2007 Chris Lawrence
+#
+# This program is freely distributable per the following license:
+#
+LICENSE="""\
+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 appears in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation.
+
+I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I
+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."""
+#
+# Version ##VERSION##; see changelog for revision history
+# $Id: reportbug,v 1.98.2.33 2008-04-18 05:38:27 lawrencc Exp $
+
+DEBUGGER = 'lawrencc at debian.org'
+DEFAULT_BTS = 'debian'
+
+import sys, os
+sys.path = ['/usr/share/reportbug'] + sys.path
+
+import optparse
+import re
+import locale
+import commands
+import rfc822
+import gettext
+import textwrap
+
+from reportbuglib import reportbug
+from reportbuglib.reportbug import (
+ VERSION, COPYRIGHT,
+ MODE_EXPERT, MODE_ADVANCED, MODE_NOVICE, MODE_STANDARD,
+ )
+from reportbuglib.rbtempfile import (
+ TempFile,
+ tempfile_prefix,
+ cleanup_temp_file,
+ )
+from reportbuglib.reportbug_exceptions import (
+ UINotImportable, UINotImplemented,
+ NoNetwork, NoPackage, NoBugs, NoReport,
+ )
+from reportbuglib import reportbug_submit
+from reportbuglib import checkversions
+from reportbuglib import debianbts
+from reportbuglib import checkbuildd
+from reportbuglib import reportbug_ui_text as ui
+
+try:
+ gettext.install('reportbug')
+except IOError:
+ pass
+
+# Magic constant time
+MIN_USER_ID = 250
+
+quietly = False
+
+# Cheat for now.
+# ewrite() may put stuff on the status bar or in message boxes depending on UI
+def ewrite(*args):
+ return quietly or ui.log_message(*args)
+
+def efail(*args):
+ ui.display_failure(*args)
+ sys.exit(1)
+
+# Lame message when we store a report as a temp file.
+def stopmsg(filename):
+ ui.final_message(
+ 'reportbug stopped; your incomplete report is stored as "%s".\n'
+ 'This file may be located in a temporary directory; if so, it might '
+ 'disappear without any further notice. To recover this file to use '
+ 'it as bug report body, please take a look at the "-i FILE, '
+ '--include=FILE" option.\n', filename)
+
+# Obscene hack :)
+def system(cmdline):
+ try:
+ x = os.getcwd()
+ except OSError:
+ os.chdir('/')
+ os.system(cmdline)
+
+def include_file_in_report(message, message_filename,
+ attachment_filenames, package_name,
+ include_filename, charset, inline=False):
+ """ Include a file in the report.
+
+ :parameters:
+ `message`
+ The current text of the message.
+ `message_filename`
+ The current message filename.
+ `attachment_filenames`
+ List of current attachment filenames.
+ `package_name`
+ Name of the package for this report.
+ `include_filename`
+ Full pathname of the file to be included.
+ `inline`
+ If True, include the message inline with the message
+ text. Otherwise, add the file path to the attachments.
+
+ :return value:
+ Tuple (`message`, `message_filename`, `attachments`) of
+ values as modified during the process of including the new
+ file.
+
+ """
+ if inline:
+ try:
+ fp = file(include_filename)
+ message += '\n*** %s\n%s' % (
+ include_filename.decode(charset, 'replace'),
+ fp.read().decode(charset, 'replace'))
+ fp.close()
+ fp, temp_filename = TempFile(
+ prefix=tempfile_prefix(package_name))
+ fp.write(message.encode(charset, 'replace'))
+ fp.close()
+ os.unlink(message_filename)
+ message_filename = temp_filename
+ except (IOError, OSError), exc:
+ ewrite('Unable to attach file %s\n%s\n',
+ include_filename, str(exc))
+ else:
+ attachment_filenames.append(include_filename)
+
+ return (message, message_filename, attachment_filenames)
+
+def handle_editing(filename, dmessage, options, sendto, attachments, package,
+ editor=None, charset='utf-8'):
+ if not editor:
+ editor = options.editor
+ editor = reportbug.which_editor(editor)
+ message = None
+ skip_editing = False
+ while True:
+ if not skip_editing:
+ (message, changed) = ui.spawn_editor(message or dmessage, filename,
+ editor, charset)
+ skip_editing = False
+ if not message:
+ x = ''
+ while x != 'y':
+ x = ui.select_options('Done editing', 'Ynq',
+ {'y': 'Continue (editing done).',
+ 'n': "Don't continue yet.",
+ 'q': 'Exit without sending report.'})
+ if x == 'q':
+ stopmsg(filename)
+ sys.exit(1)
+
+ message = file(filename).read().decode(charset, 'replace')
+ changed = True
+
+ prompt = 'Submit this report on %s (e to edit)' % package
+
+ if options.kudos:
+ prompt = 'Send this message (e to edit)'
+ ewrite("Message will be sent to %s\n", sendto)
+ elif options.outfile:
+ ewrite("Report will be saved as %s\n", options.outfile)
+ else:
+ ewrite("Report will be sent to %s\n", sendto)
+
+ if attachments:
+ ewrite('Attachments:\n')
+ for name in attachments:
+ ewrite(' %s\n', name)
+
+ subject = re.search('^Subject: ', message, re.M | re.I)
+ if not subject:
+ ewrite('No subject found in message. Please edit again.\n')
+
+ menuopts = "Ynaceilmpq"
+
+ if not changed or not subject:
+ menuopts = "ynacEilmpq"
+
+ # cfr Debian BTS #293361
+ if package == 'wnpp':
+ for itp_line in debianbts.itp_template.rsplit('\n'):
+ # if the line is not empty and it's in the message the user wrote
+ if itp_line in message and itp_line != '':
+ ewrite("Wrong line: %s\n", itp_line)
+ menuopts = "Eq"
+ prompt = 'ERROR: you have composed an ITP with fields unchanged from the template; this will NOT be submitted. You should edit all fields so they contain correct values for your ITP (e to edit)'
+
+ x = ui.select_options(prompt, menuopts,
+ {'y': 'Submit the bug report via email.',
+ 'n': "Don't submit the bug report; instead, "
+ "save it in a temporary file (exits reportbug).",
+ 'q': "Save it in a temporary file and quit.",
+ 'a': "Attach a file.",
+ 'i': "Include a text file.",
+ 'c': "Change editor and re-edit.",
+ 'e': 'Re-edit the bug report.',
+ 'l': 'Pipe the message through the pager.',
+ 'p': 'Print message to stdout.',
+ 'm': "Choose a mailer to edit the report."})
+ if x in ('a', 'i'):
+ invalid = True
+ while invalid:
+ if x == 'i':
+ attachfile = ui.get_filename('Choose a text file to include: ')
+ else:
+ attachfile = ui.get_filename('Choose a file to attach: ')
+ if attachfile:
+ attachfile = os.path.expanduser(attachfile)
+ if os.access(attachfile, os.R_OK) and os.path.isfile(attachfile):
+ invalid = False
+ inline = (x == 'i')
+ (message, filename, attachments) = include_file_in_report(
+ message, filename, attachments, package,
+ attachfile, charset, inline=inline)
+ if not inline:
+ skip_editing = True
+ else:
+ ewrite("Can't find %s to include!\n", attachfile)
+ else:
+ break
+ elif x == 'c':
+ ed = ui.get_filename('Choose editor: ', default=options.editor)
+ if ed:
+ editor = ed
+ elif x == 'm':
+ mailers = [(x, '') for x in reportbug.MUA.keys()]
+ mailers.sort()
+ mailer = ui.menu('Choose a mailer for your report', mailers,
+ 'Select mailer: ', default='', empty_ok=True)
+ if mailer:
+ mailer = reportbug.MUA.get(mailer)
+ if mailer:
+ options.mua = mailer
+ break
+ skip_editing = True
+ elif x in ('n', 'q'):
+ stopmsg(filename)
+ sys.exit(1)
+ elif x in ('l', 'p'):
+ skip_editing = True
+ if x == 'l':
+ pager = os.environ.get('PAGER', 'sensible-pager')
+ os.popen(pager, 'w').write(message.encode(charset, 'replace'))
+ else:
+ sys.stdout.write(message.encode(charset, 'replace'))
+ elif x == 'y':
+ if message == dmessage:
+ x = ui.select_options(
+ 'Report is unchanged. Edit this report or quit', 'Eqs',
+ {'q': "Don't submit the bug report; instead, save it "
+ "in a temporary file and quit.",
+ 'e': 'Re-edit the bug report.',
+ 's': 'Send report anyway.'})
+ if x == 'q':
+ stopmsg(filename)
+ sys.exit(1)
+ break
+ elif x == 's':
+ ewrite('Sending empty report anyway...\n')
+ break
+ else:
+ break
+
+ return file(filename).read()
+
+def find_package_for(filename, notatty=False, pathonly=False):
+ ewrite("Finding package for '%s'...\n", filename)
+ (newfilename, packages) = reportbug.find_package_for(filename, pathonly)
+ if newfilename != filename:
+ filename = newfilename
+ ewrite("Resolved as '%s'.\n", filename)
+ if not packages:
+ ewrite("No packages match.\n")
+ return (filename, None)
+ elif len(packages) > 1:
+ packlist = packages.items()
+ packlist.sort()
+
+ if notatty:
+ print "Please re-run reportbug selecting one of these packages:"
+ for pkg, files in packlist:
+ print " "+pkg
+ sys.exit(1)
+
+ packs = []
+ for pkg, files in packlist:
+ if len(files) > 3:
+ files[3:] = ['...']
+ packs.append( (pkg, ', '.join(files) ) )
+
+ package = ui.menu("Multiple packages match: ", packs, 'Select one '
+ 'of these packages: ', any_ok=True)
+ return (filename, package)
+ else:
+ package = packages.keys()[0]
+ ewrite("Using package '%s'.\n", package)
+ return (filename, package)
+
+def validate_package_name(package):
+ if not re.match(r'^[a-z0-9][a-z0-9\-\+\.]+$', package):
+ ui.long_message("%s is not a valid package name.", package)
+ package = None
+ return package
+
+def get_other_package_name(others):
+ """Displays the list of pseudo-packages and returns the one selected."""
+
+ result = ui.menu("Please enter the name of the package in which you "
+ "have found a problem, or choose one of these bug "
+ "categories:", others, "Enter a package: ", any_ok=True,
+ default='')
+ if isinstance(result, basestring):
+ # If the package selected is kernel, we replace it with linux-image
+ # since it contains additional information useful to maintainer
+ if result == 'kernel':
+ result = 'linux-image'
+ return result
+ else:
+ return None
+
+def get_package_name(bts='debian', mode=MODE_EXPERT):
+ others = debianbts.SYSTEMS[bts].get('otherpkgs')
+ prompt = "Please enter the name of the package in which you have found "\
+ "a problem"
+ if others:
+ prompt += ", or type 'other' to report a more general problem."
+ else:
+ prompt += '.'
+
+ options = []
+ pkglist = commands.getoutput('apt-cache pkgnames')
+ if pkglist:
+ options += pkglist.split()
+ if others:
+ options += others.keys()
+
+ package = None
+ while package is None:
+ package = ui.get_string(prompt, options, force_prompt=True)
+ if not package:
+ return
+ if others and package and package == 'other':
+ package = get_other_package_name(others)
+ if not package:
+ return
+ package = validate_package_name(package)
+
+ if mode < MODE_STANDARD:
+ if package == 'reportbug':
+ if not ui.yes_no('Is "reportbug" actually the package you are '
+ 'having problems with',
+ 'Yes, I am actually experiencing a problem with '
+ 'reportbug.',
+ 'No, I really meant to file a bug report on '
+ 'another package.'):
+ return get_package_name(bts, mode)
+
+ if mode < MODE_EXPERT:
+ if package in ('bugs.debian.org', 'debbugs'):
+ if ui.yes_no('Are you reporting a problem with this program '
+ '(reportbug)', 'Yes, this is actually a bug in '
+ 'reportbug.', 'No, this is really a problem in the '
+ 'bug tracking system itself.'):
+ package = 'reportbug'
+
+ if package in ('general', 'project', 'debian-general', 'base'):
+ if not ui.yes_no(
+ "Are you sure this bug doesn't apply to a specific package?",
+ 'Yes, this bug is truly general.',
+ 'No, this is not really a general bug.', False):
+ return get_package_name(bts, mode)
+
+ if package == 'wnpp':
+ if not ui.yes_no(
+ 'Are you sure you want to file a WNPP report?',
+ 'Yes, I am a developer or know what I\'m doing.',
+ 'No, I am not a developer and I don\'t know what wnpp means.',
+ False):
+ return get_package_name(bts, mode)
+
+ if package == 'ftp.debian.org':
+ if not ui.yes_no(
+ 'Are you sure you want to file a bug on ftp.debian.org?',
+ 'Yes, I am a developer or know what I\'m doing.',
+ 'No, I am not a developer and I don\'t know what ftp.debian.org is.',
+ False):
+ return get_package_name(bts, mode)
+
+ return package
+
+def special_prompts(package, bts, ui, fromaddr):
+ prompts = debianbts.SYSTEMS[bts].get('specials')
+ if prompts:
+ pkgprompts = prompts.get(package)
+ if pkgprompts:
+ return pkgprompts(package, bts, ui, fromaddr)
+ return
+
+def offer_configuration(options):
+ charset = locale.nl_langinfo(locale.CODESET)
+ # It would be nice if there were some canonical character set conversion
+ if charset.lower() == 'ansi_x3.4-1968':
+ charset = 'us-ascii'
+ ui.charset = charset
+
+ if not options.configure:
+ ui.long_message('Welcome to reportbug! Since it looks like this is '
+ 'the first time you have used reportbug, we are '
+ 'configuring its behavior. These settings will be '
+ 'saved to the file "%s", which you will be free to '
+ 'edit further.\n\n', reportbug.USERFILE)
+ mode = ui.menu('Please choose the default operating mode for reportbug.',
+ reportbug.MODES, 'Select mode: ', options.mode,
+ order=reportbug.MODELIST)
+
+ uis = dict()
+ for i in reportbug.AVAILABLE_UIS:
+ if (i in reportbug.UIS) and i != 'newt':
+ uis[i] = reportbug.UIS[i]
+ if len(uis) > 1:
+ interface = ui.menu(
+ 'Please choose the default interface for reportbug.', uis,
+ 'Select interface: ', options.interface)
+ else:
+ interface = 'text'
+
+ online = ui.yes_no('Will reportbug often have direct '
+ 'Internet access? (You should answer yes to this '
+ 'question unless you know what you are doing and '
+ 'plan to check whether duplicate reports have been '
+ 'filed via some other channel.)',
+ 'Yes, reportbug should assume it has access to the '
+ 'network always.',
+ 'No, I am only online occasionally to send and '
+ 'receive mail.',
+ default=(not options.offline))
+
+ def_realname, def_email = reportbug.get_email()
+
+ try:
+ if options.realname:
+ realname = options.realname.encode(charset, 'replace')
+ else:
+ realname = def_realname.encode(charset, 'replace')
+ except UnicodeDecodeError:
+ realname = ''
+
+ realname = ui.get_string('What real name should be used for sending bug '
+ 'reports? [%s]' % realname, force_prompt=True)
+ if isinstance(realname, str):
+ realname = realname.decode(charset, 'replace')
+
+ from_addr = ui.get_string(
+ 'Which of your email addresses should be used when sending bug '
+ 'reports? (Note that this address will be visible in the bug tracking '
+ 'system, so you may want to use a webmail address or another address '
+ 'with good spam filtering capabilities.) [%s]' %
+ (options.email or def_email), force_prompt=True)
+
+ stupidmode = not ui.yes_no(
+ 'Do you have a "mail transport agent" (MTA) like Exim, Postfix or '
+ 'SSMTP configured on this computer to send mail to the Internet?',
+ 'Yes, I can run /usr/sbin/sendmail without horrible things happening. '
+ 'If you can send email from this machine without setting an SMTP Host '
+ 'in your mailer, you should choose this answer.',
+ 'No, I need to use an SMTP Host or I don\'t know if I have an MTA.',
+ (not options.smtphost))
+
+ if stupidmode:
+ opts = []
+ if options.smtphost:
+ opts += [options.smtphost]
+ smtphost = ui.get_string(
+ 'Please enter the name of your SMTP host. Usually it\'s called '
+ 'something like "mail.example.org" or "smtp.example.org". '
+ 'Just press ENTER if you don\'t have one or don\'t know.',
+ options=opts, force_prompt=True)
+ if smtphost:
+ stupidmode = False
+ else:
+ smtphost = ''
+
+ if smtphost:
+ smtpuser = ui.get_string(
+ ('If you need to use a user name to send email via "%s" on your '
+ 'computer, please enter that user name. Just press ENTER if you '
+ 'don\'t need a user name.' % smtphost), force_prompt=True)
+ else:
+ smtpuser = ''
+
+ if os.path.exists(reportbug.USERFILE):
+ try:
+ os.rename(reportbug.USERFILE, reportbug.USERFILE+'~')
+ except OSError:
+ ewrite('Unable to rename %s as %s~\n', reportbug.USERFILE,
+ reportbug.USERFILE)
+
+ try:
+ fd = os.open(reportbug.USERFILE, os.O_WRONLY|os.O_TRUNC|os.O_CREAT,
+ 0600)
+ except OSError, x:
+ ui.long_message('Unable to save %s; most likely, you do not have a '
+ 'home directory. Please fix this before using '
+ 'reportbug again.\n', reportbug.USERFILE)
+ sys.exit(1)
+
+ fp = os.fdopen(fd, 'w')
+ print >> fp, '# reportbug preferences file'
+ print >> fp, '# character encoding: %s' % charset
+ print >> fp, '# Version of reportbug this preferences file was written by'
+ print >> fp, 'reportbug_version "##VERSION##"'
+ print >> fp, '# default operating mode: one of:',
+ print >> fp, ', '.join(reportbug.MODELIST)
+ print >> fp, 'mode %s' % mode
+ print >> fp, '# default user interface'
+ print >> fp, 'ui %s' % interface
+ print >> fp, '# offline setting - comment out to be online'
+ if not online:
+ print >> fp, 'offline'
+ else:
+ print >> fp, '#offline'
+ print >> fp, '# name and email setting (if non-default)'
+ rn = 'realname "%s"'
+ em = 'email "%s"'
+ email_addy = (from_addr or options.email or def_email)
+ email_name = (realname or options.realname or def_realname)
+
+ if email_name != def_realname:
+ print >> fp, rn % email_name.encode(charset, 'replace')
+ else:
+ print >> fp, '# '+(rn % email_name.encode(charset, 'replace'))
+
+ if email_addy != def_email:
+ print >> fp, em % email_addy
+ else:
+ print >> fp, '# '+(em % email_addy)
+
+ uid = os.getuid()
+ if uid < MIN_USER_ID:
+ print >> fp, '# Suppress user ID check for this user'
+ print >> fp, 'no-check-uid'
+
+ if smtphost:
+ print >> fp, '# Send all outgoing mail via the following host'
+ print >> fp, 'smtphost "%s"' % smtphost
+ if smtpuser:
+ print >> fp, 'smtpuser "%s"' % smtpuser
+ print >> fp, '#smtppasswd "my password here"'
+ else:
+ print >> fp, '# If you need to enter a user name and password:'
+ print >> fp, '#smtpuser "my username here"'
+ print >> fp, '#smtppasswd "my password here"'
+
+ if stupidmode:
+ print >> fp, '# Disable fallback mode by commenting out the following:'
+ print >> fp, 'no-cc'
+ print >> fp, 'header "X-Debbugs-CC: %s"' % email_addy
+ print >> fp, 'smtphost bugs.debian.org'
+ else:
+ print >> fp, '# If nothing else works, remove the # at the beginning'
+ print >> fp, '# of the following three lines:'
+ print >> fp, '#no-cc'
+ print >> fp, '#header "X-Debbugs-CC: %s"' % email_addy
+ print >> fp, '#smtphost bugs.debian.org'
+
+ print >> fp, '# You can add other settings after this line. See'
+ print >> fp, '# /etc/reportbug.conf for a full listing of options.'
+ fp.close()
+ ui.final_message('Default preferences file written. To reconfigure, '
+ 're-run reportbug with the "--configure" option.\n')
+
+def verify_option(option, opt, value, parser, *args):
+ heading, valid = args
+ if value == 'help':
+ ewrite('%s:\n %s\n' % (heading, '\n '.join(valid)))
+ sys.exit(1)
+ elif value in valid:
+ setattr(parser.values, option.dest, value)
+ else:
+ ewrite('Ignored bogus setting for %s: %s\n' % (opt, value))
+
+def verify_append_option(option, opt, value, parser, *args):
+ heading, valid = args
+ if value == 'help':
+ ewrite('%s:\n %s\n' % (heading, '\n '.join(valid)))
+ sys.exit(1)
+ elif value in valid:
+ try:
+ getattr(parser.values, option.dest).append(value)
+ except AttributeError:
+ setattr(parser.values, option.dest, [value])
+ else:
+ ewrite('Ignored bogus setting for %s: %s\n' % (opt, value))
+
+def main():
+ global quietly, ui
+
+ try:
+ locale.setlocale(locale.LC_ALL, '')
+ except locale.Error, x:
+ print >> sys.stderr, '*** Warning:', x
+
+ charset = locale.nl_langinfo(locale.CODESET)
+ # It would be nice if there were some canonical character set conversion
+ if charset.lower() == 'ansi_x3.4-1968':
+ charset = 'us-ascii'
+
+ defaults = dict(sendto="submit", mode="novice", mta="/usr/sbin/sendmail",
+ check_available=True, query_src=True, debconf=True,
+ editor='', offline=False, verify=True, check_uid=True,
+ testmode=False, attachments=[], keyid='', body=None,
+ bodyfile=None, smtptls=False, smtpuser='', smtppasswd='',
+ paranoid=False)
+
+ if not sys.stdin.isatty():
+ defaults.update({ 'dontquery' : True, 'notatty' : True,
+ 'printonly' : True })
+
+ # Convention: consider `option.foo' names read-only; they always contain
+ # the original value as determined by the cascade of command-line options
+ # and configuration files. When we need to adjust a value, we first say
+ # "foo = options.foo" and then refer to just `foo'.
+ args = reportbug.parse_config_files()
+ for option, arg in args.items():
+ if option in reportbug.CONFIG_ARGS:
+ if isinstance(arg, unicode):
+ arg = arg.encode(charset, 'replace')
+ defaults[option] = arg
+ else:
+ sys.stderr.write('Warning: untranslated token "%s"\n' % option)
+
+ parser = optparse.OptionParser(
+ usage='%prog [options] <package | filename>', version=VERSION)
+ parser.set_defaults(**defaults)
+ parser.add_option('-c', '--no-config-files', action="store_true",
+ dest='noconf', help='do not include conffiles in report')
+ parser.add_option('-C', '--class', action='callback', type='string',
+ callback=verify_option, dest="klass", metavar='CLASS',
+ callback_args=('Permitted report classes:',
+ debianbts.CLASSLIST),
+ help='specify report class for GNATS BTSes')
+ parser.add_option('-d', '--debug', action='store_true', default=False,
+ dest='debugmode', help='send report only to yourself')
+ parser.add_option('--test', action="store_true", default=False,
+ dest="testmode",
+ help="operate in test mode (maintainer use only)")
+ parser.add_option('-e', '--editor', dest='editor',
+ help='specify an editor for your report')
+ parser.add_option('-f', '--filename', dest='searchfor',
+ help='file to search for')
+ parser.add_option('--path', dest='pathonly', action="store_true",
+ default=False, help='only search the path with -f')
+ parser.add_option('-g', '--gnupg', '--gpg', action='store_const',
+ dest='sign', const='gpg',
+ help='sign report with GNU Privacy Guard')
+ parser.add_option('-G', '--gnus', action='store_const', dest='mua',
+ const=reportbug.MUA['gnus'],
+ help='send the report using GNUS')
+ parser.add_option('--pgp', action='store_const', dest='sign',
+ const='pgp', help='sign report with PGP')
+ parser.add_option('-K', '--keyid', type="string", dest="keyid",
+ help="key ID to use for PGP/GnuPG signatures")
+ parser.add_option('-H', '--header', action='append', dest='headers',
+ help='add a custom RFC822 header to your report')
+ parser.add_option('-P', '--pseudo-header', action='append', dest='pseudos',
+ help='add a custom pseudo-header to your report')
+ parser.add_option('--license', action='store_true', default=False,
+ help='show copyright and license information')
+ parser.add_option('-m', '--maintonly', action='store_const',
+ dest='sendto', const='maintonly',
+ help='send the report to the maintainer only')
+ parser.add_option('-M', '--mutt', action='store_const', dest='mua',
+ const=reportbug.MUA['mutt'],
+ help='send the report using mutt')
+ parser.add_option('--mirror', action='append', help='add a BTS mirror',
+ dest='mirrors')
+ parser.add_option('-a', '--af', action='store_const', dest='mua',
+ const=reportbug.MUA['af'],
+ help='send the report using af')
+ parser.add_option('-n', '--mh', '--nmh', action='store_const', dest='mua',
+ help='send the report using mh/nmh',
+ const=reportbug.MUA['mh'])
+ parser.add_option('--mua', dest='mua',
+ help='send the report using the specified mailer')
+ parser.add_option('--mta', dest='mta', help='send the report using the '
+ 'specified mail transport agent')
+ parser.add_option('--list-cc', action='append', dest='listcc',
+ help='send a copy to the specified address')
+ parser.add_option('-p', '--print', action='store_true', dest='printonly',
+ help='output the report to standard output only')
+ parser.add_option('--report-quiet', action='store_const', dest='sendto',
+ const='quiet', help='file report without any mail to '
+ 'the maintainer or tracking lists')
+ parser.add_option('-q', '--quiet', action='store_true', dest='quietly',
+ help='reduce the verbosity of the output', default=False)
+ parser.add_option('-s', '--subject', help='the subject for your report')
+ parser.add_option('-x', '--no-cc', dest='nocc', action='store_true',
+ help='do not send a copy of the report to yourself')
+ parser.add_option('-z', '--no-compress', dest='nocompress',
+ action='store_true', help='do not strip blank lines '
+ 'and comments from config files')
+ parser.add_option('-o', '--output', dest='outfile', help='output the '
+ 'report to the specified file')
+ parser.add_option('-O', '--offline', help='disable all external queries',
+ action='store_true')
+ parser.add_option('-i', '--include', action='append',
+ help='include the specified file in the report')
+ parser.add_option('-A', '--attach', action='append', dest='attachments',
+ help='attach the specified file to the report')
+ parser.add_option('-b', '--no-query-bts', action='store_true',
+ dest='dontquery',help='do not query the BTS for reports')
+ parser.add_option('--query-bts', action='store_false', dest='dontquery',
+ help='query the BTS for reports')
+ parser.add_option('-T', '--tag', action='callback', dest='tags',
+ callback=verify_append_option, type='string',
+ callback_args=('Permitted tags:',
+ debianbts.TAGLIST+['none']),
+ help='add the specified tag to the report')
+ parser.add_option('--http_proxy', '--proxy', help='use this proxy for '
+ 'HTTP accesses')
+ parser.add_option('--email', help='specify originating email address')
+ parser.add_option('--realname', help='specify real name for your report')
+ parser.add_option('--smtphost', help='specify SMTP server for mailing')
+ parser.add_option('--tls', help='use TLS to talk to SMTP servers',
+ dest="smtptls", action='store_true')
+ parser.add_option('--smtpuser', help='username to use for SMTP')
+ parser.add_option('--smtppasswd', help='password to use for SMTP')
+ parser.add_option('--replyto', '--reply-to', help='specify Reply-To '
+ 'address for your report')
+ parser.add_option('--query-source', action='store_true', dest='query_src',
+ help='query on source packages, not binary packages')
+ parser.add_option('--no-query-source', action='store_false',
+ dest='query_src', help='query on binary packages only')
+ parser.add_option('--debconf', action='store_true',
+ help='include debconf settings in your report')
+ parser.add_option('--no-debconf', action='store_false', dest='debconf',
+ help='exclude debconf settings from your report')
+ parser.add_option('-j', '--justification', help='include justification '
+ 'for the severity of your report')
+ parser.add_option('-V', '--package-version', dest='pkgversion',
+ help='specify the version number for the package')
+ parser.add_option('-u', '--interface', '--ui', action='callback',
+ callback=verify_option, type='string', dest='interface',
+ callback_args=('Valid user interfaces',
+ reportbug.AVAILABLE_UIS),
+ help='choose which user interface to use')
+ parser.add_option('-Q', '--query-only', action='store_true',
+ dest='queryonly', help='only query the BTS')
+ parser.add_option('-t', '--type', action='callback', dest='type',
+ callback=verify_option, type='string',
+ callback_args=('Valid types of report:',
+ ('gnats', 'debbugs')),
+ help='choose the type of report to file')
+ parser.add_option('-B', '--bts', action='callback', dest='bts',
+ callback=verify_option, type='string',
+ callback_args=('Valid bug tracking systems',
+ debianbts.SYSTEMS.keys()),
+ help='choose BTS to file the report with')
+ parser.add_option('-S', '--severity', action='callback',
+ callback=verify_option, type='string', dest='severity',
+ callback_args=('Valid severities', debianbts.SEVLIST),
+ help='identify the severity of the report')
+ parser.add_option('--template', action='store_true',
+ help='output a template report only')
+ parser.add_option('--configure', action='store_true',
+ help='reconfigure reportbug for this user')
+ parser.add_option('--check-available', action='store_true',
+ help='check for new releases at packages.debian.org')
+ parser.add_option('--no-check-available', action='store_false',
+ dest='check_available', help='do not check for new '
+ 'releases')
+ parser.add_option('--mode', action='callback', help='choose the operating '
+ 'mode for reportbug', callback=verify_option,
+ type='string', dest='mode',
+ callback_args=('Permitted operating modes',
+ reportbug.MODES.keys()))
+ parser.add_option('-v', '--verify', action='store_true', help='verify '
+ 'integrity of installed package using debsums')
+ parser.add_option('--no-verify', action='store_false', dest='verify',
+ help='do not verify package installation')
+ parser.add_option('-k', '--kudos', action='store_true', default=False,
+ help='send appreciative email to the maintainer, rather '
+ 'than filing a bug report')
+ parser.add_option('--check-installed', action='store_true',
+ dest='querydpkg', help='check whether the specified '
+ 'package is installed when filing a report (default)')
+ parser.add_option('--body', dest="body", type="string",
+ help="specify the body for the report as a string")
+ parser.add_option('--body-file', '--bodyfile', dest="bodyfile",
+ type="string",
+ help="use the specified file as the body of the report")
+ parser.add_option('-I', '--no-check-installed', action='store_false',
+ default=True, dest='querydpkg',
+ help='don\'t check whether the package is installed')
+ parser.add_option('--exit-prompt', action='store_true', dest='exitprompt',
+ help='prompt before exiting')
+ parser.add_option('--paranoid', action='store_true', dest='paranoid',
+ help='show contents of message before sending')
+ parser.add_option('--no-paranoid', action='store_false', dest='paranoid',
+ help='don\'t show contents of message before sending '
+ '(default)')
+
+ (options, args) = parser.parse_args()
+
+ # Load the interface, *before* the configuration step.
+ sys.argv = sys.argv[:1] + list(args)
+ if options.interface:
+ interface = options.interface
+ if interface in ('gnome', 'newt'):
+ ui.long_message("The %s interface is not supported. Unless you "
+ "are debugging reportbug, please do not use it. "
+ "If you are debugging reportbug, please DO NOT "
+ "file bugs more serious than 'normal' that "
+ "indicate problems with this interface.\n",
+ interface)
+
+ iface = 'reportbug_ui_%(interface)s' % vars()
+ try:
+ lib_package = __import__('reportbuglib', fromlist=[iface])
+ ui = getattr(lib_package, iface)
+ except UINotImportable, msg:
+ ui.long_message('*** Unable to import %s interface: %s '
+ 'Falling back to text interface.\n',
+ interface, msg)
+ ewrite('\n')
+
+ reportbug_submit.ui = ui
+ # Add INTERFACE as an environment variable to access it from the
+ # script gathering the special information for reportbug, when
+ # a new bug should be filed against it.
+ os.environ['INTERFACE'] = interface
+
+ iface = UI(options, args)
+ if not hasattr(ui, 'run_interface'):
+ return iface.user_interface()
+ return ui.run_interface(iface.user_interface)
+
+class UI(object):
+ def __init__(self, options, args):
+ self.options = options
+ self.args = args
+
+ def user_interface(self):
+ body = ''
+ filename = None
+ notatty = not ui.ISATTY
+
+ charset = locale.nl_langinfo(locale.CODESET)
+ # It would be nice if there were some canonical character set conversion
+ if charset.lower() == 'ansi_x3.4-1968':
+ charset = 'us-ascii'
+
+ # Allow the UI to know what charset we're using
+ ui.charset = charset
+
+ if self.options.configure:
+ offer_configuration(self.options)
+ sys.exit(0)
+ elif self.options.license:
+ print COPYRIGHT
+ print
+ print LICENSE
+ sys.exit(0)
+
+ # These option values may get adjusted below, so give them a variable name.
+ sendto = self.options.sendto
+ check_available = self.options.check_available
+ dontquery = self.options.dontquery
+ headers = self.options.headers or []
+ pseudos = self.options.pseudos or []
+ mua = self.options.mua
+ pkgversion = self.options.pkgversion
+ quietly = self.options.quietly
+ severity = self.options.severity
+ smtphost = self.options.smtphost
+ subject = self.options.subject
+ bts = self.options.bts or 'debian'
+ sysinfo = debianbts.SYSTEMS[bts]
+ rtype = self.options.type or sysinfo.get('type')
+ attachments = self.options.attachments
+ pgp_addr = self.options.keyid
+
+ if self.options.body:
+ body = textwrap.fill(self.options.body)
+ elif self.options.bodyfile:
+ try:
+ body = file(self.options.bodyfile).read()
+ except:
+ ewrite('Unable to read body from file %s.\n', self.options.bodyfile)
+ sys.exit(1)
+
+ if body and not body.endswith('\n'):
+ body += '\n'
+
+ if self.options.queryonly:
+ check_available = False
+
+ if self.options.offline:
+ check_available = False
+ dontquery = True
+
+ if self.options.tags:
+ taglist = self.options.tags
+ if 'none' in taglist:
+ taglist = []
+ else:
+ taglist = []
+
+ if self.options.testmode:
+ self.options.debugmode = True
+ self.options.tags = ['none']
+ check_available = False
+ dontquery = True
+ severity = 'normal'
+ subject = 'testing'
+ taglist = []
+
+ interactive = True
+ if self.options.template:
+ check_available = interactive = False
+ dontquery = quietly = notatty = True
+ mua = smtphost = None
+ severity = severity or 'wishlist'
+ subject = subject or 'none'
+ taglist = taglist or []
+
+ if self.options.outfile or self.options.printonly:
+ mua = smtphost = None
+
+ if smtphost and smtphost.lower() == 'master.debian.org':
+ ui.long_message('*** Warning: master.debian.org is no longer an appropriate smtphost setting for reportbug; please update your .reportbugrc file.\n')
+ smtphost = 'bugs.debian.org'
+
+ if attachments and mua:
+ ewrite('Attachments are incompatible with using an MUA. They will be ignored.\n')
+ attachments = []
+
+ if reportbug.first_run():
+ if not self.args:
+ offer_configuration(self.options)
+ main()
+ sys.exit(0)
+ else:
+ ewrite('Warning: no reportbug configuration found. Proceeding in %s mode.\n' % self.options.mode)
+
+ mode = reportbug.MODELIST.index(self.options.mode)
+
+ # Disable signatures when in printonly or mua mode
+ # (since they'll be bogus anyway)
+ sign = self.options.sign
+ if (self.options.mua or self.options.printonly) and sign:
+ sign = ''
+ if self.options.mua:
+ ewrite('The signature option is ignored when using an MUA.\n')
+ elif self.options.printonly:
+ ewrite('The signature option is ignored when producing a template.\n')
+
+ uid = os.getuid()
+ if uid < MIN_USER_ID:
+ if notatty and not uid:
+ ewrite("reportbug will not run as root non-interactively.\n")
+ sys.exit(1)
+
+ if not uid or self.options.check_uid:
+ if not uid:
+ message = "Running 'reportbug' as root is probably insecure!"
+ else:
+ message = "Running 'reportbug' as an administrative user "\
+ "is probably not a good idea!"
+ message += ' Continue'
+
+ if not ui.yes_no(message, 'Continue with reportbug.', 'Exit.',
+ False):
+ ewrite("reportbug stopped.\n")
+ sys.exit(1)
+
+ if (reportbug.first_run() and not self.args):
+ offer_configuration(self.options)
+ ewrite('To report a bug, please rerun reportbug.\n')
+ sys.exit(0)
+
+ foundfile = None
+ package = None
+ if not len(self.args) and not self.options.searchfor and not notatty:
+ package = get_package_name(bts, mode)
+ elif len(self.args) > 1:
+ ewrite("Please report one bug at a time.\n")
+ ewrite("[Did you forget to put all switches before the "
+ "package name?]\n")
+ sys.exit(1)
+ elif self.options.searchfor:
+ (foundfile, package) = find_package_for(self.options.searchfor, notatty,
+ self.options.pathonly)
+ elif len(self.args):
+ package = self.args[0]
+ if package and package.startswith('/'):
+ (foundfile, package) = find_package_for(package, notatty)
+
+ others = debianbts.SYSTEMS[bts].get('otherpkgs')
+ if package == 'other' and others:
+ package = get_other_package_name(others)
+
+ if not package:
+ efail("No package specified; stopping.\n")
+
+ tfprefix = tempfile_prefix(package)
+ if self.options.interface == 'text':
+ ewrite('*** Welcome to reportbug. Use ? for help at prompts. ***\n')
+
+ try:
+ blah = u'hello'.encode(charset)
+ except LookupError:
+ ui.long_message(
+ 'Unable to use specified character set "%s"; you probably need '
+ 'either cjkcodecs (for users of Asian locales) or iconvcodec '
+ 'installed.\nFalling back to ASCII encoding.\n', charset)
+ charset = 'us-ascii'
+ else:
+ ewrite("Detected character set: %s\n"
+ "Please change your locale if this is incorrect.\n\n", charset)
+
+ fromaddr = reportbug.get_user_id(self.options.email, self.options.realname, charset)
+ ewrite("Using '%s' as your from address.\n", fromaddr.encode(charset, 'replace'))
+ fromaddr = fromaddr.encode('utf-8')
+ if self.options.debugmode:
+ sendto = fromaddr
+
+ edname = reportbug.which_editor(self.options.editor)
+ baseedname = os.path.basename(edname)
+ if baseedname == 'sensible-editor':
+ edname = reportbug.realpath('/usr/bin/editor')
+
+ if not notatty and 'vi' in baseedname and mode < MODE_STANDARD and \
+ 'EDITOR' not in os.environ:
+ if not ui.yes_no('You appear to be using the "vi" editor, which is '
+ 'not suited for new users. You probably want to '
+ 'change this setting by using "update-alternatives '
+ '--config editor" as root. (You can bypass this '
+ 'message in the future by using reportbug in '
+ '"standard" mode or higher.) '
+ 'Do you want to continue?',
+ 'Continue filing this report.',
+ 'Stop reportbug to change editors.', False):
+ ewrite('Exiting per user request.\n')
+ sys.exit(1)
+
+ incfiles = u""
+ if self.options.include:
+ for f in self.options.include:
+ if os.path.exists(f):
+ fp = file(f)
+ incfiles = u'%s\n*** %s\n%s' % (
+ incfiles, f.decode('utf-8', 'replace'),
+ fp.read().decode('utf-8', 'replace'))
+ fp.close()
+ else:
+ ewrite("Can't find %s to include!\n", f)
+ sys.exit(1)
+ incfiles += '\n'
+
+ pkgavail = maintainer = origin = src_name = state = ''
+ depends = []
+ recommends = []
+ suggests = []
+ conffiles = []
+ reportinfo = None
+ isvirtual = (package in sysinfo.get('otherpkgs', {}).keys() and
+ package not in sysinfo.get('nonvirtual', []))
+ issource = installed = usedavail = False
+ status = None
+
+ if not pkgversion and self.options.querydpkg and \
+ sysinfo.get('query-dpkg', True):
+ ewrite("Getting status for %s...\n", package)
+ status = reportbug.get_package_status(package)
+
+ pkgavail, installed = status[1], status[6]
+ # Packages that only exist to do weird dependency things
+ deppkgs = sysinfo.get('deppkgs')
+ if pkgavail and deppkgs:
+ if installed and package in deppkgs:
+ depends = status[2]
+ if depends:
+ newdepends = []
+ for x in depends:
+ newdepends.extend(x)
+ depends = newdepends
+ if len(depends) == 1:
+ if mode < MODE_ADVANCED:
+ ewrite('Dependency package "%s" corresponds to '
+ 'actual package "%s".\n', package, depends[0])
+ package = depends[0]
+ else:
+ opts = [(x,
+ (reportbug.get_package_status(x)[11] or
+ 'not installed')) for x in depends]
+ if mode >= MODE_ADVANCED:
+ opts += [(package,
+ status[11]+' (dependency package)')]
+
+ package = ui.menu('%s is a dependency package. '
+ 'Which of the following '
+ 'packages is the bug in?' % package,
+ opts,
+ 'Select one of these packages: ')
+ ewrite("Getting status for %s...\n", package)
+ status = reportbug.get_package_status(package)
+ pkgavail, installed = status[1], status[6]
+
+ if not pkgavail and not isvirtual:
+ # Look for a matching source package
+ packages = reportbug.get_source_package(package)
+ if len(packages) > 0:
+ src = package
+ if len(packages) and not notatty:
+ packages.sort()
+ if src not in [x[0] for x in packages]:
+ packages.append( (src, 'Source package') )
+
+ if len(packages) > 1:
+ package = ui.menu(
+ 'Which of the following packages is the bug in?',
+ packages, empty_ok=True,
+ prompt='Select one of these packages: ')
+ else:
+ package = packages[0][0]
+
+ if not package:
+ efail("No package specified; stopping.\n")
+
+ if package != src:
+ ewrite("Getting status for %s...\n", package)
+ status = reportbug.get_package_status(package)
+ pkgavail, installed = status[1], status[6]
+ elif len(packages) > 1:
+ issource = True
+ else:
+ ewrite('No matching source or binary packages.\n')
+
+ if (not installed and not isvirtual and not issource) and not notatty:
+ packages = reportbug.packages_providing(package)
+ tmp = pack = None
+ if not packages:
+ if ui.yes_no(
+ 'A package named "%s" does not appear to be installed; do '
+ 'you want to search for a similar-looking filename in '
+ 'an installed package' % package,
+ 'Look for a file with a similar filename.',
+ 'Continue filing with this package name.', True):
+ pkgavail = False
+ else:
+ pack = package
+ packages = [(package, '')]
+ ewrite("Getting available info for %s...\n", package)
+ status = reportbug.get_package_status(package, avail=True)
+ check_available = False
+ usedavail = True
+
+ if not packages and not pkgavail and not pack:
+ (tmp, pack) = find_package_for(package, notatty)
+ if pack:
+ status = None
+ if not ui.yes_no(
+ "A package named '%s' does not appear to be installed "
+ "on your system; however, '%s' contains a file named "
+ "'%s'. Do you want to file your report on the "
+ "package reportbug found" % (package, pack, tmp),
+ 'Yes, use the package specified.',
+ 'No, give up the search.'):
+ efail("Package not installed; stopping.\n")
+
+ if not status and pack:
+ foundfile, package = tmp, pack
+ ewrite("Getting status for %s...\n", package)
+ status = reportbug.get_package_status(package)
+ elif not packages:
+ if not ui.yes_no(
+ 'This package does not appear to be installed; continue '
+ 'with this report', 'Ignore this problem and continue.',
+ 'Exit without filing a report.', False):
+ efail("Package not installed; stopping.\n")
+ elif (len(packages) > 1) or (packages[0][0] != package):
+ this_package = [(package, 'Uninstalled/non-existent package')]
+ packages.sort()
+ package = ui.menu('Which of the following installed packages '
+ 'is the bug in?', packages + this_package,
+ 'Select one of these packages: ',
+ empty_ok=True)
+ if not package:
+ efail("No package specified; stopping.\n")
+ else:
+ ewrite("Getting status for %s...\n", package)
+ status = reportbug.get_package_status(package)
+ elif not pkgavail and not notatty and not isvirtual and not issource:
+ if not ui.yes_no(
+ 'This package does not appear to exist; continue',
+ 'Ignore this problem and continue.',
+ 'Exit without filing a report.', False):
+ efail("Package does not exist; stopping.\n")
+ sys.exit(1)
+
+ (pkgversion, pkgavail, depends, recommends, conffiles, maintainer,
+ installed, origin, vendor, reportinfo, priority, desc, src_name,
+ fulldesc, state, suggests) = status
+
+ buginfo = '/usr/share/bug/' + package
+ bugexec = submitas = submitto = presubj = None
+ reportwith = []
+ supplemental = []
+ if os.path.isfile(buginfo) and os.access(buginfo, os.X_OK):
+ bugexec = buginfo
+ elif os.path.isdir(buginfo):
+ if os.path.isfile(buginfo+'/script') and os.access(buginfo+'/script', os.X_OK):
+ bugexec = buginfo+'/script'
+
+ if os.path.isfile(buginfo+'/presubj'):
+ presubj = buginfo+'/presubj'
+
+ if os.path.isfile(buginfo+'/control'):
+ submitas, submitto, reportwith, supplemental = \
+ reportbug.parse_bug_control_file(buginfo+'/control')
+ elif os.path.isfile('/usr/share/bug/default/'+package) \
+ and os.access('/usr/share/bug/default/'+package, os.X_OK):
+ bugexec = '/usr/share/bug/default/'+package
+ elif os.path.isdir('/usr/share/bug/default/'+package):
+ buginfo = '/usr/share/bug/default/'+package
+ if os.path.isfile(buginfo+'/script') and os.access(buginfo+'/script',
+ os.X_OK):
+ bugexec = buginfo+'/script'
+
+ if os.path.isfile(buginfo+'/presubj'):
+ presubj = buginfo+'/presubj'
+
+ if os.path.isfile(buginfo+'/control'):
+ submitas, submitto, reportwith, supplemental = \
+ reportbug.parse_bug_control_file(buginfo+'/control')
+
+ if submitas and (submitas not in reportwith):
+ reportwith += [submitas]
+
+ if reportwith:
+ # Remove current package from report-with list
+ reportwith = [x for x in reportwith if x != package]
+
+ if (pkgavail and self.options.verify and os.path.exists('/usr/bin/debsums')
+ and not (notatty or self.options.kudos) and state == 'installed'):
+ ewrite('Verifying package integrity...\n')
+ rc, output = commands.getstatusoutput('/usr/bin/debsums -s'+
+ commands.mkarg(package))
+ if rc:
+ if not ui.yes_no(
+ 'There may be a problem with your installation of '+package+
+ ';\nthe following files appear to be missing or changed:\n'+
+ output+'\nDo you still want to file a report',
+ 'Ignore this problem and continue. This may be '
+ 'appropriate if you have fixed the package manually already. '
+ 'This problem may also result from the use of localepurge.',
+ 'Exit without filing a report.', False, nowrap=True):
+ efail("Package integrity check failed; stopping.\n")
+
+ if not pkgversion or usedavail or (not pkgavail and
+ not self.options.pkgversion):
+ if not (isvirtual or notatty):
+ pkgversion = ui.get_string('Please enter the version of the '
+ 'package this report applies to '
+ '(blank OK)', force_prompt=True)
+ elif (check_available and not (self.options.kudos or notatty or self.options.offline)
+ and state == 'installed' and bts == 'debian'):
+ arch = reportbug.get_arch()
+ check_more = (mode > MODE_STANDARD)
+ if check_more:
+ ewrite('Checking for newer versions at packages.debian.org,'+
+ ' incoming.debian.org and http://ftp-master.debian.org/new.html\n')
+ else:
+ ewrite('Checking for newer versions at packages.debian.org...\n')
+ (avail, toonew) = checkversions.check_available(
+ package, pkgversion, check_incoming=check_more,
+ check_newqueue=check_more,
+ http_proxy=self.options.http_proxy, arch=arch)
+ if toonew:
+ if not ui.yes_no(
+ '\nYour version of %s (%s) is newer than that in Debian!\n'
+ 'Do you still want to file a report' % (package, pkgversion),
+ 'Ignore this problem and continue. This may be '
+ 'appropriate if you know this bug is present in older '
+ 'releases of the package, or you\'re running a mixed '
+ 'stable/testing installation.',
+ 'Exit without filing a report.', False):
+ efail("Newer released version; stopping.\n")
+
+ if avail:
+ availtext = ''
+ availlist = avail.keys()
+ availlist.sort()
+ for rel in availlist:
+ availtext += ' %s: %s\n' % (rel, avail[rel])
+
+ if not ui.yes_no(
+ ('\nYour version (%s) of %s appears to be out of date.\nThe '
+ 'following newer release(s) are available in the Debian '
+ 'archive:\n' % (pkgversion, package))+availtext+
+ 'Do you still want to file a report',
+ 'Ignore this problem and continue. This may be '
+ 'appropriate if you know this bug is still present in more '
+ 'recent releases of the package.',
+ 'Exit without filing a report.', False, nowrap=True):
+ efail("Newer released version; stopping.\n")
+
+ bts = DEFAULT_BTS
+ if self.options.bts:
+ bts = self.options.bts
+ ewrite("Will send report to %s (per request).\n",
+ debianbts.SYSTEMS[bts].get('name', bts))
+ elif origin:
+ if origin.lower() == bts:
+ ewrite("Package originates from %s.\n", vendor or origin)
+ reportinfo = None
+ elif origin.lower() in debianbts.SYSTEMS.keys():
+ ewrite("Package originates from %s; overriding your system "
+ "selection.\n", vendor or origin)
+ bts = origin.lower()
+ sysinfo = debianbts.SYSTEMS[bts]
+ elif reportinfo:
+ ewrite("Unknown origin %s; will send to %s.\n", origin,
+ reportinfo[1])
+ rtype, submitto = reportinfo
+ elif submitto:
+ ewrite("Unknown origin %s; will send to %s.\n", origin, submitto)
+ else:
+ ewrite("Unknown origin %s; will send to %s.\n", origin, bts)
+ elif reportinfo:
+ rtype, submitto = reportinfo
+ ewrite("Will use %s protocol talking to %s.\n", rtype, submitto)
+ dontquery = True
+ else:
+ lsbr = commands.getoutput('lsb_release -si 2>/dev/null')
+ if lsbr:
+ distro = lsbr.strip().lower()
+ if distro in debianbts.SYSTEMS:
+ bts = distro
+ ewrite("Will send report to %s (per lsb_release).\n",
+ debianbts.SYSTEMS[bts].get('name', bts))
+
+ if rtype == 'mailto':
+ rtype = 'debbugs'
+ dontquery = True
+
+ special = False
+ if not body and not subject and not notatty:
+ res = special_prompts(package, bts, ui, fromaddr)
+ if res:
+ (subject, severity, h, ph, body, query) = res
+ headers += h
+ pseudos += ph
+ if not query:
+ dontquery = True
+ special = True
+
+ exinfo = None
+ if not (dontquery or notatty or self.options.kudos):
+ pkg, src = package, issource
+ if self.options.query_src:
+ src = True
+ if src_name:
+ pkg = src_name
+ try:
+ exinfo = ui.handle_bts_query(pkg, bts, self.options.mirrors,
+ self.options.http_proxy,
+ source=src,
+ queryonly=self.options.queryonly,
+ version=pkgversion)
+ except UINotImplemented:
+ exinfo = None
+ except NoNetwork:
+ sys.exit(1)
+ except NoPackage:
+ if not self.options.queryonly and maintainer and ui.yes_no(
+ 'There is no record of this package in the bug tracking '
+ 'system.\nSend report directly to maintainer',
+ 'Send the report to the maintainer (%s).' % maintainer,
+ 'Send the report to the BTS anyway.'):
+ rtype = 'debbugs'
+ sendto = maintainer
+ except NoBugs:
+ ewrite('No bug reports found.\n')
+ except NoReport:
+ if self.options.queryonly:
+ ewrite('Exiting at user request.\n')
+ else:
+ ewrite('Nothing new to report; exiting.\n')
+ return
+
+ if self.options.queryonly and not exinfo:
+ return
+
+ ccaddr = os.environ.get('MAILCC')
+ if self.options.nocc:
+ bccaddr = os.environ.get('MAILBCC')
+ else:
+ bccaddr = os.environ.get('MAILBCC', fromaddr)
+
+ if maintainer:
+ mstr = u"Maintainer for %s is '%s'.\n" % (package, maintainer)
+ ewrite(mstr.encode(charset, 'replace'))
+ if 'qa.debian.org' in maintainer:
+ ui.long_message('''\
+This package is currently "orphaned"; if you are a current or prospective
+Debian developer, you might consider adopting it. Please be aware that your
+report may not be resolved for a while, and that packages that have been
+orphaned for a long period of time are often removed from the archive.\n''')
+ ui.ewrite('\nFor more details, please see: http://www.debian.org/devel/wnpp/\n')
+
+ if self.options.kudos:
+ sendto = '%s at packages.debian.org' % package
+
+ depinfo = ""
+ # Grab dependency list, removing version conditions.
+ if (depends or recommends or suggests) and not self.options.kudos:
+ ewrite("Looking up dependencies of %s...\n", package)
+ depinfo = (reportbug.get_dependency_info(package, depends) +
+ reportbug.get_dependency_info(package, recommends, "recommends") +
+ reportbug.get_dependency_info(package, suggests, "suggests"))
+
+ if reportwith and not self.options.kudos:
+ for extrapackage in reportwith:
+ ewrite("Getting status for related package %s...\n", extrapackage)
+ extrastatus = reportbug.get_package_status(extrapackage)
+ if extrastatus[2]:
+ extradepends = [x for x in extrastatus[2] if package not in x]
+ ewrite("Looking up dependencies of related package %s...\n", extrapackage)
+ depinfo += reportbug.get_dependency_info(extrapackage, extradepends)
+
+ if supplemental and not self.options.kudos:
+ ewrite("Looking up status of additional packages...\n")
+ depinfo += reportbug.get_dependency_info(
+ package, [[x] for x in supplemental], rel='is related to')
+
+ confinfo = []
+ if conffiles and not self.options.kudos:
+ ewrite("Getting changed configuration files...\n")
+ confinfo, changed = reportbug.get_changed_config_files(
+ conffiles, nocompress)
+
+ if self.options.noconf and changed:
+ for f in changed:
+ confinfo[f] = 'changed [not included]'
+ elif changed and not notatty:
+ while 1:
+ x = ui.select_self.options(
+ "*** WARNING: The following configuration files have been "
+ "modified:\n"+ "\n".join(changed)+
+ "\nSend modified configuration files", 'Ynd',
+ {'y':'Send your modified configuration files.',
+ 'n':"Don't send modified configuration files.",
+ 'd':'Display modified configuration files.'})
+ if x == 'n':
+ for f in changed:
+ confinfo[f] = 'changed [not included]'
+ break
+ elif x == 'd':
+ PAGER = os.environ.get('PAGER', '/usr/bin/sensible-pager')
+ system(PAGER+' '+' '.join(changed))
+ else:
+ break
+
+ conftext = u''
+ if confinfo:
+ conftext = u'\n-- Configuration Files:\n'
+ files = confinfo.keys()
+ files.sort()
+ for f in files:
+ conftext = conftext + u'%s %s\n' % (f, confinfo[f])
+
+ if (self.options.debconf and os.path.exists('/usr/bin/debconf-show') and
+ not self.options.kudos and installed):
+ showpkgs = package
+ if reportwith:
+ showpkgs += ' ' + ' '.join(reportwith)
+ (status, output) = commands.getstatusoutput(
+ 'DEBCONF_SYSTEMRC=1 DEBCONF_NOWARNINGS=yes '
+ '/usr/bin/debconf-show %s' % showpkgs )
+ if status:
+ conftext += '\n-- debconf-show failed\n'
+ elif output:
+ output = output.decode('utf-8', 'replace')
+ outstr = output.encode(charset, 'replace')
+ if (notatty or ui.yes_no(
+ "*** The following debconf settings were detected:\n"
+ +outstr+"\nInclude these settings in your report",
+ 'Send your debconf settings.',
+ "Don't send your debconf settings.", nowrap=True)):
+ conftext += u'\n-- debconf information:\n%s\n' % output
+ else:
+ conftext += u'\n-- debconf information excluded\n'
+ else:
+ conftext += u'\n-- no debconf information\n'
+
+ ewrite('\n')
+ prompted = False
+ if interactive and not (self.options.kudos or exinfo) and presubj:
+ ui.display_report(file(presubj).read()+'\n')
+
+ if self.options.kudos:
+ subject = subject or ('Thanks for packaging %s!' % package)
+ elif exinfo:
+ if special:
+ body = ''
+ prompted = True
+ subject = ui.get_string(
+ 'Please provide a subject for your response; no subject will '
+ 'stop reportbug.', force_prompt=True)
+ # Check to make sure the bug still exists to avoid auto-reopens
+ if subject and pkgversion:
+ if not ui.yes_no('Does this bug still exist in version %s '
+ 'of this package?' % pkgversion,
+ 'Yes, it does.',
+ 'No, it doesn\'t (or I don\'t know).',
+ default=False):
+ pkgversion = None
+ elif not subject and not notatty:
+ prompted = True
+ subject = ui.get_string(
+ 'Please briefly describe your problem (you can elaborate in '
+ 'a moment; an empty response will stop reportbug). This will '
+ 'be the bug email subject, so write a concise summary of what '
+ 'is wrong with the package, for example, "fails to send email" '
+ 'or "does not start with -q option specified."', force_prompt=True)
+
+ if not subject:
+ efail("No subject specified; stopping.\n")
+
+ if len(subject) > 100 and prompted and mode < MODE_EXPERT:
+ subject = ui.get_string(
+ 'Your description is a bit long; please enter a shorter subject. '
+ '(An empty response will retain the existing subject.)',
+ force_prompt=True) or subject
+ if package != 'wnpp' and prompted and mode < MODE_EXPERT:
+ if foundfile:
+ subject = foundfile + ": " + subject
+ ewrite("Rewriting subject to '%s'\n", subject)
+ elif (not re.match(r"\S+:\s", subject) and package not in subject):
+ subject = package + ": " + subject
+ ewrite("Rewriting subject to '%s'\n", subject)
+
+ listcc = self.options.listcc
+ if not listcc:
+ listcc = []
+
+ if not listcc and mode > MODE_STANDARD and rtype == 'debbugs' and not self.options.testmode and not self.options.template:
+ listcc += ui.get_multiline('Enter any additional addresses this report should be sent to; press ENTER after each address.')
+
+ if severity and rtype:
+ severity = debianbts.convert_severity(severity, rtype)
+
+ klass = self.options.klass
+ if not notatty and not (exinfo or self.options.kudos):
+ if not severity:
+ if rtype == 'gnats':
+ severities = debianbts.SEVERITIES_gnats
+ default = 'non-critical'
+ else:
+ severities = debianbts.SEVERITIES
+ default = 'normal'
+
+ severity = ui.menu("How would you rate the severity of this "
+ "problem or report?", severities,
+ 'Please select a severity level: ',
+ default=default, order=debianbts.SEVLIST)
+
+ if rtype == 'gnats':
+ # Class of report
+ klass = ui.menu("What sort of problem are you reporting?",
+ debianbts.CLASSES, 'Please select a class: ',
+ default='sw-bug', order=debianbts.CLASSLIST)
+
+ severity = severity or 'normal'
+
+ justification = self.options.justification
+ if rtype == 'debbugs' and package != 'wnpp' and mode < MODE_EXPERT:
+ if severity in ('critical', 'grave'):
+ justification = ui.menu(
+ 'You are reporting a ' +severity+' bug; which of the '
+ 'following criteria does it meet?',
+ debianbts.JUSTIFICATIONS[severity],
+ 'Please select the impact of the bug: ', default='unknown')
+ elif severity == 'serious':
+ justification = ui.get_string(
+ 'You are reporting a serious bug; which section of the '
+ 'Debian Policy Manual contains the "must" or "required" '
+ 'directive that it violates (E.g., "1.2.3")? '
+ 'Just type "unknown" if you are not sure (that would '
+ 'downgrade severity to normal).', force_prompt=True)
+ if re.match('[0-9]+\.[0-9.]+', justification):
+ justification = 'Policy ' + justification
+ elif not justification:
+ justification = 'unknown'
+
+ if justification == 'unknown':
+ justification = ''
+ severity = 'normal'
+ ewrite('Severity downgraded to "normal".\n')
+
+ if severity == 'does-not-build':
+ if pkgversion and not src_name:
+ src_name = package
+ if src_name and check_available and not notatty:
+ ewrite('Checking buildd.debian.org for past builds of %s...\n',
+ src_name)
+ built = checkbuildd.check_built(src_name,
+ http_proxy=self.options.http_proxy)
+
+ if built:
+ ewrite('Successful past builds... treating as serious.\n')
+ severity = 'serious'
+ justification = 'no longer builds from source'
+ else:
+ ewrite('No successful builds... treating as important.\n')
+ severity = 'important'
+ justification = 'fails to build from source'
+ else:
+ if notatty:
+ severity = 'important'
+ justification = 'fails to build from source'
+ else:
+ if ui.yes_no(
+ 'Has this package successfully been built for this '
+ 'architecture in the past (you can look this up at '
+ 'buildd.debian.org)',
+ 'Yes, this is a recently-introduced problem.',
+ 'No, it has always been this way.'):
+ severity = 'serious'
+ justification = 'no longer builds from source'
+ else:
+ severity = 'important'
+ justification = 'fails to build from source'
+
+ HOMEDIR = os.environ.get('HOME', '/')
+
+ if (rtype == 'debbugs' and not self.options.tags and
+ not (notatty or self.options.kudos or exinfo) and package not in ('wnpp','ftp.debian.org') and
+ mode > MODE_NOVICE):
+ # Multiple-choice checkbox
+ if severity in ('grave', 'critical', 'serious'):
+ tags = debianbts.TAGS.copy()
+ tags.update(debianbts.CRITICAL_TAGS)
+ tagorder = debianbts.TAGLIST + debianbts.CRITICAL_TAGLIST
+ else:
+ tags = debianbts.TAGS
+ tagorder = debianbts.TAGLIST
+
+ taglist = ui.select_multiple(
+ 'Do any of the following apply to this report?', tags,
+ 'Please select tags: ', order=tagorder,
+ extras=debianbts.EXTRA_TAGS)
+
+ patch = ('patch' in taglist)
+
+ if justification and 'security' not in taglist and 'security' in \
+ justification:
+ ewrite('Adding security tag to this report.\n')
+ taglist += ['security']
+
+ if taglist:
+ tags = ' '.join(taglist)
+ else:
+ tags = ''
+
+ # Execute bug script
+ if (interactive or self.options.template) and bugexec and not self.options.kudos:
+ if os.path.exists('handle_bugscript'):
+ handler = './handle_bugscript'
+ else:
+ handler = '/usr/share/reportbug/handle_bugscript'
+
+ fh, filename = TempFile(prefix=tfprefix)
+ fh.close()
+ system('%s %s %s' % (handler, commands.mkarg(bugexec),
+ commands.mkarg(filename)))
+
+ addinfo = None
+ if not self.options.noconf:
+ fp = open(filename)
+ addinfo = u"\n-- Package-specific info:\n"+fp.read().decode('utf-8', 'replace')
+ fp.close()
+
+ cleanup_temp_file(filename)
+ if addinfo and incfiles:
+ incfiles = addinfo + u"\n" + incfiles
+ elif addinfo:
+ incfiles = addinfo
+
+ if bts == 'debian' and 'security' in taglist:
+ ewrite('Will send a CC of this report to the Debian Security and Testing Security Team.\n')
+ listcc += ['Debian Security Team <team at security.debian.org>']
+ listcc += ['Debian Testing Security Team <secure-testing-team at lists.alioth.debian.org>']
+
+ if listcc:
+ headers.append('X-Debbugs-CC: '+', '.join(listcc))
+
+ # Prepare bug report
+ if self.options.kudos:
+ message = u'\n\n'
+ if not mua:
+ SIGFILE = os.path.join(HOMEDIR, '.signature')
+ try:
+ message = u"\n\n-- \n"+file(SIGFILE).read().decode('utf-8', 'replace')
+ except IOError:
+ pass
+ else:
+ message = reportbug.generate_blank_report(
+ submitas or package, pkgversion, severity, justification,
+ depinfo, conftext, foundfile, incfiles, bts, exinfo, rtype,
+ klass, subject, tags, body, mode, pseudos)
+
+ # Substitute server email address
+ if submitto and '@' not in sendto:
+ if '@' in submitto:
+ sendto = submitto
+ else:
+ if exinfo:
+ if sendto != 'submit':
+ sendto = '%d-%s' % (exinfo, sendto)
+ else:
+ sendto = str(exinfo)
+
+ sendto = sendto+'@'+submitto
+ elif '@' not in sendto:
+ if exinfo:
+ if sendto != 'submit':
+ sendto = '%d-%s' % (exinfo, sendto)
+ else:
+ sendto = str(exinfo)
+
+ try:
+ sendto = sysinfo['email'] % sendto
+ except TypeError:
+ sendto = sysinfo['email']
+
+ sendto = rfc822.dump_address_pair((sysinfo['name']+
+ ' Bug Tracking System', sendto))
+
+ mailing = not (mua or self.options.printonly or self.options.template)
+ message = u"Subject: %s\n%s" % (subject, message)
+
+ if mailing:
+ fh, filename = TempFile(prefix=tfprefix)
+ fh.write(message.encode(charset, 'replace'))
+ fh.close()
+ oldmua = mua or self.options.mua
+ if not self.options.body and not self.options.bodyfile:
+ message = handle_editing(filename, message, self.options,
+ sendto, attachments, package,
+ charset=charset)
+ if not oldmua and self.options.mua:
+ mua = self.options.mua
+ if mua:
+ mailing = False
+ elif not sendto:
+ print message,
+ cleanup_temp_file(filename)
+ return
+
+ cleanup_temp_file(filename)
+
+ if not mua and patch and not attachments and not notatty:
+ while True:
+ patchfile = ui.get_filename(
+ 'What is the filename of the patch (if none, or you have '
+ 'already included it, just press ENTER)?',
+ force_prompt=True)
+ if patchfile:
+ attachfile = os.path.expanduser(patchfile)
+ if os.path.exists(attachfile):
+ attachments.append(attachfile)
+ break
+ else:
+ ewrite('%s not found!', attachfile)
+ else:
+ break
+
+ body, headers, pseudoheaders = reportbug.cleanup_msg(message,headers,rtype)
+
+ if sign:
+ ewrite('Passing message to %s for signature...\n', sign)
+ oldbody = body
+ body = reportbug_submit.sign_message(body, fromaddr, package, pgp_addr,
+ sign)
+ if not body:
+ ewrite('Signature failed; sending message unsigned.\n')
+ body = oldbody
+
+ if pseudoheaders:
+ body = '\n'.join(pseudoheaders)+'\n\n'+body
+
+ # Strip the body of useless whitespace at the end, then put a final
+ # newline in the message. See #234963.
+ body = body.rstrip('\n')+'\n'
+
+ reportbug_submit.send_report(
+ body, attachments, mua, fromaddr, sendto, ccaddr, bccaddr,
+ headers, package, charset, mailing, sysinfo, rtype, exinfo,
+ self.options.replyto, self.options.printonly, self.options.template,
+ self.options.outfile, self.options.mta, self.options.kudos, self.options.smtptls,
+ smtphost, self.options.smtpuser, self.options.smtppasswd, self.options.paranoid)
+
+ if self.options.exitprompt:
+ ui.get_string('Please press ENTER to exit reportbug: ')
+ return
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ ewrite("\nreportbug: exiting due to user interrupt.\n")
+ except debianbts.Error, x:
+ ewrite('error accessing BTS: %s\n' % x)
Property changes on: trunk/reportbug_4merge
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mergeinfo
+
More information about the Reportbug-commits
mailing list