Bug 974219 - Redirect users to new repository location default tip
authorEd Morley <emorley@mozilla.com>
Sun, 02 Mar 2014 01:46:14 +0000
changeset 81 532a85be8b49
parent 80 414b18290a92
push id61
push useremorley@mozilla.com
push dateSun, 02 Mar 2014 01:46:31 +0000
bugs974219
Bug 974219 - Redirect users to new repository location
README
__init__.py
bz.py
bzhandler.py
pb.py
scp.py
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,11 @@
+qimportbz: Imports patches from bugzilla to your mercurial queue.
+
+THIS EXTENSION HAS MOVED REPOSITORIES. IT CAN NOW BE FOUND IN:
+https://hg.mozilla.org/hgcustom/version-control-tools/
+
+Please delete this repository, clone the new one, and adjust your
+hgrc to reference the new location.
+
+If you are using mach to build Firefox, you can run
+`mach mercurial-setup` to have your configuration updated
+automatically.
--- a/__init__.py
+++ b/__init__.py
@@ -1,229 +1,16 @@
 """qimportbz
 
 Imports patches from bugzilla to your mercurial queue
 
-Example:
-
-  hg qimport bz://1234567
-
-Configuration section is entirely optional but potentially useful::
-
-  [qimportbz]
-  bugzilla = server-address (defaults to BUGZILLA environment varable or bugzilla.mozilla.org)
-  joinstr = string to join flags for commit messages (default is ' ')
-  patch_format = Formatting string used to create patch names automatically. Set it to empty to use the initial filename.
-  msg_format = Formatting string used to create commit messages automatically
-  auto_choose_all = If multiple patches associated with a bug choose them all without prompting (default is False)
-
-Formatting strings are the standard python format strings where a dictionary is used to supply the data.
-For users of Mercurial 1.2: any % characters must be escaped since Python's configuration parser will try to interpret them.
-
-There are 7 pieces of patch metadata available for use::
-
-  "bugnum" : the bug number
-  "id" : the patch id (internal bugzilla number)
-  "title" : the bug title
-  "desc" : the patch description
-  "flags" : all the flags
-  "filename" : the initial patch filename
-  "bugdesc" : the bug description
-
-The default values are::
-
-  patch_format = %(filename)s
-  msg_format = Bug %(bugnum)s - "%(title)s" [%(flags)s]
+This extension has moved repositories and now lives in:
+https://hg.mozilla.org/hgcustom/version-control-tools/
 """
-from mercurial import hg, commands, cmdutil, extensions, url, error, httppeer
-from hgext import mq
-
-import re
-import os
-import urllib
-
-import bz
-import bzhandler
-import pb
-import scp
-
-def extsetup(ui=None):
-  # "Mercurial version 8e6019b16a7d and later (that is post-1.3.1) will pass a
-  # ui argument to extsetup."
-  # 'None': support pre/post Hg v1.3.1 versions.
-
-  # Insert preview flag into qimport:
-  # For HG 1.3.1 and earlier, commands.table has the commands for mq
-  # For HG 1.4, commands.table does not have the commands for mq so we
-  #   use mq.cmdtable
-  #
-  # Note that we cannot just use mq.cmdtable always because each command entry
-  # is a tuple so wrapping the qimport function will not update the right
-  # table
-  #
-  # Hence our strategy is to try commands.table and fall back to mq.cmdtable
-  # rather than do an explicit version check.
-  try:
-    qimport_cmd = cmdutil.findcmd("qimport", commands.table)
-    cmdtable = commands.table
-  except error.UnknownCommand:
-    qimport_cmd = cmdutil.findcmd("qimport", mq.cmdtable)
-    cmdtable = mq.cmdtable
-  qimport_cmd[1][1].append(('p', 'preview', False, "preview commit message"))
-
-  # re to match our url syntax
-  bz_matcher = re.compile("bz:(?://)?(\d+)(?:/(\w+))?")
-  pb_matcher = re.compile("pb:(?://)?(\d+)")
-  scp_matcher= re.compile(r"scp:(?://)?(.*)")
-
-  def makebzurl(num, attachid):
-    return "bz://%s%s" % (num, "/" + attachid if attachid else "")
-
-  def makepburl(num):
-    return "pb://%s" % num
-
-  def makescpurl(path):
-    return "scp://%s" % urllib.quote(path, safe='')
-
-  def fixuppath(path):
-    m = bz_matcher.search(path)
-    if m:
-      bug, attachment = m.groups()
-      return makebzurl(bug, attachment)
-
-    m = pb_matcher.search(path)
-    if m:
-      num, = m.groups()
-      return makepburl(num)
-
-    m = scp_matcher.search(path)
-    if m:
-      scppath, = m.groups()
-      return makescpurl(scppath)
-
-    return path
-
-  # hook the mq import so we can fixup the patchname and handle multiple
-  # patches per url
-  def qimporthook(orig, ui, repo, *files, **opts):
-    q = repo.mq
 
-    # checks for an unused patch name. prompts if the patch already exists and
-    # returns the corrected name.
-    def checkpatchname(patch):
-      name = patch.name
-      # Hg v1.4+: "ui.prompt is now a simple prompt and does not accept a list of choices. Use ui.promptchoice instead.".
-      hasPromptchoice = hasattr(ui, 'promptchoice')
-      while os.path.exists(q.join(name)):
-        prompt = "A patch file named '%s' already exists in your patch directory. Rename %s '%s' (%d) (r)/overwrite (o)?" % \
-                 (name,
-                  'patch' if isinstance(patch, bz.Patch) else 'attachment',
-                  patch.desc,
-                  int(patch.id))
-        if hasPromptchoice:
-          choice = ui.promptchoice(prompt,
-                                   ("&readonly", "&overwrite"),
-                                   0)
-          choice = ["r", "o"][choice]
-        else:
-          choice = ui.prompt(prompt,
-                             ("&readonly", "&overwrite"),
-                             "r")
-        if choice == 'r':
-          name = ui.prompt("Enter the new patch name (old one was '%s'):" % name)
-        else: # overwrite
-          break;
-      if name in q.series and q.isapplied(name):
-        ui.warn("Patch was already applied. Changes will not take effect until the patch is reapplied.")
-      return name
-
-    # hook for url.open which lets the user edit the returned 
-    def previewopen(orig, ui, path):
-      fp = orig(ui, path)
-
-      class PreviewReader(object):
-        def read(self):
-          return ui.edit(fp.read(), ui.username())
-
-      return PreviewReader()
-
-    # Install the preview hook if necessary. This will preview non-bz:// bugs
-    # and that's OK.
-    if opts['preview']:
-      extensions.wrapfunction(url, "open", previewopen)
-
-    # mercurial's url.search_re includes the // and that doesn't match what we
-    # want which is bz:dddddd(/ddddd)?
-    files = map(fixuppath, files)
-
-    # Do the import as normal. The first patch of any bug is actually imported
-    # and the rest are stored in the global delayed_imports. The imported
-    # patches have dumb filenames because there's no way to tell mq to pick the
-    # patch name *after* download.
-    ret = orig(ui, repo, *files, **opts)
-    if ret or bzhandler.last_imported_patch() is None:
-      return ret
-
-    # If the user passed a name, then mq used that so we don't need to rename
-    if not opts['name']:
-      # cache the lookup of the name. findcmd is not fast.
-      qrename = cmdutil.findcmd("qrename", commands.table)[1][0]
+ERROR = 'WARNING: The qimportbz extension has switched repositories and now lives in: \n\
+https://hg.mozilla.org/hgcustom/version-control-tools/\n\
+Please clone this repository and update your hgrc to point to the new location.\n\
+If you use mach to build Firefox, run `mach mercurial-setup` to do this for you.\n\n'
 
-      # Rename the already imported patch. If there are multiple patches, the
-      # rest will be in bzhandler.delayed_imports, which we'll name correctly
-      # in the first place.
-      try:
-        # hg 1.9+
-        oldpatchname = q.fullseries[q.fullseriesend()]
-      except:
-        oldpatchname = q.full_series[q.full_series_end()]
-      newpatchname = checkpatchname(bzhandler.last_imported_patch())
-      if newpatchname != oldpatchname:
-        qrename(ui, repo, oldpatchname, newpatchname)
-        # mq always reports the original name, which is confusing so we'll
-        # report the rename. But if ui.verbose is on, qrename will have already
-        # reported it.
-        if not ui.verbose:
-          ui.write("renamed %s -> %s\n" % (oldpatchname, newpatchname))
 
-    # now process the delayed imports
-
-    # these opts are invariant for all patches
-    newopts = {}
-    newopts.update(opts)
-    newopts['force'] = True
-
-    # loop through the Patches and import them by calculating their url. The
-    # bz:// handler will have cached the lookup so we don't hit the network
-    # here. Each one of these pushes an unapplied patch onto the beginning of
-    # the queue, and unapplied patches are ignored when importing them, so do
-    # these in reverse order.
-    for patch in reversed(list(bzhandler.delayed_imports)):
-      newopts['name'] = checkpatchname(patch)
-      path = makebzurl(patch.bug.num, patch.id)
-
-      ret = orig(ui, repo, path, **newopts)
-      if ret:
-        return ret
-
-  extensions.wrapcommand(cmdtable, 'qimport', qimporthook)
-
-  # Here we setup the protocol handlers
-  processors = {
-    'bz' : bzhandler.Handler,
-    'pb' : pb.Handler,
-    'scp' : scp.Handler
-  }
-
-  # Mercurial 1.4 has an easy way to do this for bz://dddddd urls
-  if hasattr(url, 'handlerfuncs') and hasattr(hg, 'schemes'):
-    for s, p in processors.items():
-      url.handlerfuncs.append(p)
-      hg.schemes[s] = httppeer
-  else: # monkey patching for 1.3.1 :(
-    # patch in bz: and pb: url support
-    def bzopener(orig, ui, authinfo=None):
-      result = orig(ui, authinfo)
-      for p in processors:
-        result.add_handler(p(ui, authinfo))
-      return result
-
-    extensions.wrapfunction(url, "opener", bzopener)
+def extsetup(ui):
+    ui.warn(ERROR)
deleted file mode 100644
--- a/bz.py
+++ /dev/null
@@ -1,278 +0,0 @@
-import base64
-import os
-import re
-import sys
-import urllib2
-from xml.etree.ElementTree import fromstring as xmlfromstring
-try:
-  import cStringIO as StringIO
-except ImportError:
-  import StringIO
-
-from mercurial import patch
-
-# int(bug num) -> Bug
-cache = {}
-
-class Settings(object):
-  def __init__(self, ui):
-    self.ui = ui
-    self.msg_format = ui.config('qimportbz', 'msg_format',
-                                'Bug %(bugnum)s - "%(title)s" [%(flags)s]')
-    self.joinstr = ui.config('qimportbz', 'joinstr', ' ')
-    self.patch_format = ui.config('qimportbz', 'patch_format', "%(filename)s")
-
-class Attachment(object):
-  def __init__(self, bug, node):
-    self.bug = bug
-    self.obsolete = node.attrib['isobsolete'] == "1"
-    self.id = node.find('attachid').text
-    self.desc = node.find('desc').text
-    self.filename = node.find('filename').text
-
-  def parse(bug, node):
-    ctor = Attachment
-    if node.attrib['ispatch'] == "1":
-      ctor = Patch
-    return ctor(bug, node)
-
-  parse = staticmethod(parse)
-
-class Flag(object):
-  def __init__(self, bug, node):
-    def removeDomain(emailAddress):
-      """Removes domain from email address if (old) Bugzilla didn't do it."""
-      # Bugzilla v3.2.1+: "Email Addresses Hidden From Logged-Out Users For Oracle Users"
-      # Bugzilla v3.4.1+: "Email Addresses Hidden From Logged-Out Users"
-      at_idx = emailAddress.find('@')
-      return emailAddress if at_idx < 0 else emailAddress[:at_idx]
-
-    # Ignored node attributes: 'id' and 'type_id'.
-
-    self.name = node.attrib['name']
-    if self.name not in ('review', 'superreview', 'ui-review', 'feedback', 'checked-in') and not self.name.startswith('approval'):
-      bug.settings.ui.warn("Unknown flag %s\n" % self.name)
-
-    self.setter = removeDomain(node.attrib['setter'])
-
-    self.status = node.attrib['status']
-
-    self.requestee = removeDomain(node.attrib['requestee']) if 'requestee' in node.attrib else None
-
-  # detailedApproval: False = first letter only, True = more explicit abbrev.
-  def abbrev(self, detailedApproval=False):
-    name = self.name
-
-    if name == "superreview":
-      return "sr"
-
-    if name == "ui-review":
-      return "ui-r"
-
-    if detailedApproval and name.startswith("approval"):
-      # Keep the additional part, Add a "-" if there is not one yet.
-      return "a-%s" % (name[8:] if name[8] != "-" else name[9:],)
-
-    # Just use the first letter of the other flags.
-    return name[0]
-
-  # Compare by flag name
-  def __cmp__(self, other):
-    flagorder = ['r', 'sr', 'ui-r', 'a', 'c', 'f']
-    return cmp(flagorder.index(self.abbrev()), flagorder.index(other.abbrev()))
-
-class Patch(Attachment):
-  def __init__(self, bug, node):
-    Attachment.__init__(self, bug, node)
-    self.flags = list(sorted(Flag(bug, n) for n in node.findall('flag')))
-    rawtext = base64.b64decode(node.find('data').text)
-    filename, message, user, date, branch, nodeid, p1, p2 = \
-        patch.extract(bug.settings.ui, StringIO.StringIO(rawtext))
-    # for some reason, patch.extract writes a temporary file with the diff hunks
-    if filename:
-      fp = file(filename)
-      try:
-        # BugZilla is not explicit about patch encoding. We need to check it's utf-8.
-        # utf-8: convert from 8-bit encoding to internal (16/32-bit) Unicode.
-        self.data = fp.read().decode('utf-8')
-        # Attempt to detect the start of the diff. Borrowed from:
-        # http://selenic.com/hg/file/79e5de2bfa8c/mercurial/patch.py#l163
-        diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
-                            r'retrieving revision [0-9]+(\.[0-9]+)*$|'
-                            r'---[ \t].*?^\+\+\+[ \t]|'
-                            r'\*\*\*[ \t].*?^---[ \t])', re.MULTILINE|re.DOTALL)
-        m = diffre.search(self.data)
-        if m:
-          # Remove the patch header, since we'll be re-adding a cleaned up version later.
-          self.data = self.data[m.start(0):]
-      except UnicodeDecodeError:
-        # Ftr, this could be due to the (included) message part: see later message block.
-        bug.settings.ui.warn("Patch id=%s desc=\"%s\" diff data were discarded:\n" % (self.id, self.desc))
-        # Print the exception without its traceback.
-        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
-        # Can't do better than discard data:
-        # trying |.decode('utf-8', 'replace')| as a fallback would be too risky
-        #   if user imports the result then forgets to fix it.
-        self.data = ''
-      fp.close()
-      os.remove(filename)
-    else:
-      self.data = ''
-
-    # Remove seconds (which are always ':00') and timezone from the patch date:
-    # keep 'yyyy-mm-dd hh:mn' only.
-    self.date = date or node.find('date').text[:16]
-
-    if user:
-      try:
-        # See previous self.data block about utf-8 handling.
-        self.author = user.decode('utf-8')
-      except UnicodeDecodeError:
-        bug.settings.ui.warn("Patch id=%s desc=\"%s\" user data were discarded:\n" % (self.id, self.desc))
-        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
-        user = None
-    if not user:
-      # Bugzilla v3.4.1+: "Email Addresses Hidden From Logged-Out Users"
-      patchAttacherEmail = node.find('attacher').text
-      # 'patchAttacherEmail' may not be enough, compare date too to be as precise as possible...
-      posts = [p for p in self.bug.comments if p.date == self.date and p.who_email == patchAttacherEmail]
-      who = posts[0].who
-      for p in posts:
-        if p.who == who:
-          continue
-        print "Warning: could not figure out exact author (multiple names for same date and email address)!"
-        who = ""
-        break
-      # Email domain may need to be retrieved/added manually...
-      self.author = "%s <%s>" % (
-        # Scrub the :cruft and any '[...]' or '(...)' too from the username.
-        re.sub("\[.*?\]|\(.*?\)|:\S+", "", who).strip(),
-        patchAttacherEmail)
-
-    self.commit_message = None
-    # (Mercurial v1.4.3(-!?)) "No message" is extracted as '\n' :-/
-    # Want to strip the message anyway.
-    if message:
-      try:
-        # See previous self.data block about utf-8 handling.
-        self.commit_message = message.decode('utf-8') \
-                                     .strip()
-      except UnicodeDecodeError:
-        bug.settings.ui.warn("Patch id=%s desc=\"%s\" message data were discarded too:\n" % (self.id, self.desc))
-        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
-        message = None
-    if not self.commit_message:
-      self.commit_message = self.bug.settings.msg_format % self.metadata
-
-  def __unicode__(self):
-    return u"""# vim: se ft=diff :
-# HG changeset patch
-# User %s
-# Date %s
-%s
-
-%s""" % (self.author, self.date, self.commit_message, self.data)
-
-  @property
-  def metadata(self):
-    return {
-      "bugnum" : self.bug.num,
-      "id" : self.id,
-      "title" : self.bug.title,
-      "desc" : self.desc,
-      "flags" : self.joinFlags(),
-      "filename" : self.filename,
-      "bugdesc" : self.bug.desc
-    }
-
-  @property
-  def name(self):
-    if self.bug.settings.patch_format:
-      # Create new patch name.
-      patchname = self.bug.settings.patch_format % self.metadata
-    else:
-      # Use filename from bug attachment.
-      patchname = self.filename
-
-    # The patch name might have some illegal characters so we need to scrub those
-    replacements = {
-      '_' : [' ', ':'],
-      '' : ['"', "'", '<', '>', '[', ']', '(', ')', '*']
-    }
-    for replacement, items in replacements.items():
-      for char in items:
-        patchname = patchname.replace(char, replacement)
-
-    return patchname
-
-  def joinFlags(self, commitfmt=True):
-    """Join any flags together that have the same setter, returning a string in sorted order.
-    If commitfmt is False, simply list all flags.
-    """
-    if not commitfmt:
-      return ', '.join('%s: %s%s%s' % (f.setter, f.name, f.status, " (%s)" % f.requestee if f.requestee else "") for f in self.flags)
-
-    flags = []
-    setteridx = {}
-
-    for f in self.flags:
-      setter = f.setter
-      if setter in setteridx:
-        setteridx[setter].append(f)
-      else:
-        setteridx[setter] = [f]
-
-    for f in self.flags:
-      fs = setteridx.pop(f.setter, None)
-      if fs:
-        flagnames = [f.abbrev(True) for f in fs]
-        flags.append('%s=%s' % ('+'.join(flagnames), fs[0].setter))
-
-    return self.bug.settings.joinstr.join(flags)
-
-class Comment(object):
-  def __init__(self, node):
-    who = node.find('who')
-    self.who = who.attrib['name']
-    self.who_email = who.text
-
-    # Remove seconds and timezone from the post date:
-    # keep 'yyyy-mm-dd hh:mn' only.
-    self.date = node.find('bug_when').text[:16]
-
-    self.text = node.find('thetext').text
-
-class Bug(object):
-  def __init__(self, ui, data):
-    self.settings = Settings(ui)
-    xml = xmlfromstring(data)
-    bug = xml.find("bug")
-    self.num = int(bug.find('bug_id').text)
-    sdesc = bug.find('short_desc')
-    self.title = sdesc.text if sdesc is not None else "[empty]"
-    self.comments = [Comment(n) for n in xml.findall("bug/long_desc")]
-    self.desc = self.comments[0].text if len(self.comments)>0 else ""
-    self.attachments = [Attachment.parse(self, a) for a in xml.findall("bug/attachment")]
-    if bug.get("error") == "NotPermitted":
-      raise PermissionError("Not allowed to access bug.  (Perhaps it is marked with a security group?)")
-
-    # Add to cache so we can avoid network lookup later in this process
-    cache[self.num] = self
-
-  def get_patch(self, attachid):
-    for attachment in self.attachments:
-      if attachment.id == attachid:
-        return attachment
-
-    return None
-
-  @property
-  def patches(self):
-    return [attachment for attachment in self.attachments if isinstance(attachment, Patch)]
-
-class PermissionError(Exception):
-  def __init__(self, msg):
-    self.msg = msg
-
-  def __str__(self):
-    return self.msg
deleted file mode 100644
--- a/bzhandler.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# std python modules
-import urllib2
-try:
-  import cStringIO as StringIO
-except ImportError:
-  import StringIO
-import os
-import re
-
-# qimportbz modules
-import bz
-
-# Patch list
-delayed_imports = []
-
-# The patch that got imported
-imported_patch = None
-
-def last_imported_patch():
-  return imported_patch
-
-class ObjectResponse(object):
-  def __init__(self, obj):
-    self.obj = obj
-
-  def read(self):
-    return self.obj
-
-class Handler(urllib2.BaseHandler):
-  def __init__(self, ui, passmgr):
-    self.ui = ui
-    self.passmgr = passmgr
-
-    self.base = ui.config('qimportbz', 'bugzilla',
-                          os.environ.get('BUGZILLA', "bugzilla.mozilla.org"))
-
-    self.autoChoose = ui.config('qimportbz', 'auto_choose_all', False)
-
-  # Change the request to the https for the bug XML
-  def bz_open(self, req):
-    num = int(req.get_host())
-    if num in bz.cache:
-      bug = bz.cache[num]
-      # strip the /
-      attachid = req.get_selector()[1:]
-      if attachid:
-        return ObjectResponse(bug.get_patch(attachid))
-
-      return ObjectResponse(bug)
-
-    # Normal case, return a stream of text
-    url = "https://%s/show_bug.cgi?ctype=xml&id=%s" % (self.base, num)
-    self.ui.status("Fetching...")
-    return self.parent.open(url)
-
-  # Once the XML is fetched, parse and decide what to return
-  def bz_response(self, req, res):
-    patch = None
-    # Check if we're doing a cached lookup - no ui in this case since we're
-    # working around mq's limitations
-    data = res.read()
-    if isinstance(data, bz.Bug):
-      bug = data
-    elif isinstance(data, bz.Patch):
-      patch = data
-    else: # network read
-      self.ui.status(" done\n")
-      self.ui.status("Parsing...")
-      try:
-        bug = bz.Bug(self.ui, data)
-      # TODO: update syntax when mercurial requires Python 2.6
-      except bz.PermissionError, e:
-        self.ui.warn(" %s\n" % e.msg)
-        return
-      self.ui.status(" done\n")
-
-    attachid = req.get_selector()[1:]
-    if not patch and attachid:
-      patch = bug.get_patch(attachid)
-
-    if not patch:
-      patches = [p for p in bug.patches if not p.obsolete]
-      if len(patches) == 0:
-        patches = bug.patches
-        if len(patches) == 0:
-          self.ui.warn("No patches found for this bug\n")
-          return
-
-        if len(patches) > 1:
-          self.ui.warn("Only obsolete patches found\n")
-        else:
-          if 'y' != self.ui.prompt("Only found one patch and it is obsolete. Import anyways? [Default is 'y']", default='y'):
-            return
-      if len(patches) == 1:
-        patch = patches[0]
-      elif len(patches) > 0:
-        for i, p in enumerate(patches):
-          flags = p.joinFlags(False)
-          self.ui.write("%s: %s%s\n" % (i + 1, p.desc, "\n  %s" % flags if flags else ""))
-        choicestr = ' '.join([str(n) for n in xrange(1,len(patches)+1)])
-        choicestr = choicestr if self.autoChoose else self.ui.prompt("Which patches do you want to import? [Default is '1', use '1-%d' for all]" % len(patches), default="1")
-        for choice in (s.strip() for t in choicestr.split(',') for s in t.split()):
-          try:
-            m = re.match(r'(\d+)-(\d+)$', choice)
-            if m:
-              delayed_imports.extend([ patches[p] for p in xrange(int(m.group(1)) - 1, int(m.group(2))) ])
-            else:
-              if int(choice) <= 0:
-                raise IndexError()
-              delayed_imports.append(patches[int(choice) - 1])
-          except (ValueError, IndexError):
-            self.ui.warn("Invalid patch number = '%s'\n" % choice)
-            continue
-        if not patch and len(delayed_imports) > 0:
-          patch = delayed_imports.pop()
-
-    # and finally return the response
-    if patch:
-      global imported_patch
-      imported_patch = patch
-      return PatchResponse(patch)
-
-# interface reverse engineered from urllib.addbase
-class PatchResponse(object):
-  def __init__(self, p):
-    self.patch = p
-    # utf-8: convert from internal (16/32-bit) Unicode to 8-bit encoding.
-    # NB: Easier output to deal with, as most (code) patches are ASCII only.
-    self.fp = StringIO.StringIO(unicode(p).encode('utf-8'))
-    self.read = self.fp.read
-    self.readline = self.fp.readline
-    self.close = self.fp.close
-
-  def fileno(self):
-    return None
deleted file mode 100644
--- a/pb.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# std python modules
-import urllib2
-try:
-  import cStringIO as StringIO
-except ImportError:
-  import StringIO
-import os
-
-class Handler(urllib2.BaseHandler):
-  def __init__(self, ui, passmgr):
-    self.ui = ui
-    self.passmgr = passmgr
-
-    self.base = ui.config('qimportbz', 'pastebin',
-                          os.environ.get('PASTEBIN', "pastebin.mozilla.org"))
-
-  # Change the request to the http to fetch the raw text
-  def pb_open(self, req):
-    url = "http://%s/?dl=%s" % (self.base, req.get_host())
-    return self.parent.open(url)
deleted file mode 100644
--- a/scp.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import os
-import re
-try:
-  import cStringIO as StringIO
-except ImportError:
-  import StringIO
-import subprocess
-import sys
-import tempfile
-import urllib
-import urllib2
-
-def _relpath(filepath, start=os.curdir):
-  """os.path.relpath is 2.6+, so don't rely on it being present.
-See the os.path.relpath docs for further reference."""
-  path, filename = os.path.split(filepath)
-  pathdrive, path = os.path.splitdrive(os.path.abspath(path))
-  startdrive, start = os.path.splitdrive(os.path.abspath(start))
-  prefix = os.path.commonprefix((path, start))
-
-  # interesting question: is it possible to construct a relative path
-  # on windows that specifies a location on a drive different than the
-  # drive in which the cwd is?
-  assert pathdrive == startdrive
-
-  def splitparts(p):  return filter(lambda s: s != '', p.split(os.sep))
-  prefixlen = len(splitparts(prefix))
-  pathparts = splitparts(path)[prefixlen:]
-  startparts = splitparts(start)[prefixlen:]
-
-  # walk from |start| to the LCA ...
-  relpath = os.sep.join([ '..' ] * len(startparts))
-
-  # then back down to |filepath|
-  relpath = os.path.join(relpath, path)
-
-  return os.path.join(relpath, filename)
-
-
-class Handler(urllib2.BaseHandler):
-  def __init__(self, ui, passmgr):
-    self.ui = ui
-    self.passmgr = passmgr
-    self.scp = ui.config('qimportbz', 'scp', os.environ.get('SCP', "scp"))
-
-  def scp_escape(self, path):
-    return re.sub(r'(?<![\\])[ ]', '\\ ', path)
-
-  def scp_open(self, req):
-    scppath = self.scp_escape(
-        urllib.unquote(req.get_full_url()[len('scp://'):]))
-
-    _, tmpfilename = tempfile.mkstemp('.patch', 'qimportbz_scp')
-    os.close(_)
-    tmpfilename = self.scp_escape(tmpfilename)
-    # Windows drive letters fool scp into thinking a path refers to a
-    # remote machine in the mingw shell.  So instead, use a relative
-    # path
-    tmpfilename = _relpath(tmpfilename)
-
-    output = ''
-    try:
-        if 0 != subprocess.call([ self.scp, scppath, tmpfilename ]):
-            raise urllib2.URLError(
-                "can't |scp '%s' '%s'|"% (scppath, tmpfilename))
-        outf = open(tmpfilename)
-        output = outf.read()
-        outf.close()
-    finally:
-        os.remove(tmpfilename)
-
-    return StringIO.StringIO(output)