mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
a87a2c07d6
RBTools as released on PyPI has a number of bugs and deficiencies with the Mercurial implementation. These have been fixed in an unreleased version of RBTools. Until RBTools with the desired patches is released to PyPI, we will install RBTools direct from its source repository. DONTBUILD (NPOTB) --HG-- extra : rebase_source : 8fe09b80d8dd5583ba957b4525563cde678b3b3d extra : amend_source : b41e0d492ff7d1f78bd0462782459c3dc8e95041
384 lines
14 KiB
Python
384 lines
14 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, # You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
import sys
|
|
import os
|
|
import stat
|
|
import platform
|
|
import urllib2
|
|
|
|
from mach.decorators import (
|
|
CommandArgument,
|
|
CommandProvider,
|
|
Command,
|
|
)
|
|
|
|
from mozbuild.base import MachCommandBase
|
|
|
|
|
|
@CommandProvider
|
|
class SearchProvider(object):
|
|
@Command('mxr', category='misc',
|
|
description='Search for something in MXR.')
|
|
@CommandArgument('term', nargs='+', help='Term(s) to search for.')
|
|
def mxr(self, term):
|
|
import webbrowser
|
|
term = ' '.join(term)
|
|
uri = 'https://mxr.mozilla.org/mozilla-central/search?string=%s' % term
|
|
webbrowser.open_new_tab(uri)
|
|
|
|
@Command('dxr', category='misc',
|
|
description='Search for something in DXR.')
|
|
@CommandArgument('term', nargs='+', help='Term(s) to search for.')
|
|
def dxr(self, term):
|
|
import webbrowser
|
|
term = ' '.join(term)
|
|
uri = 'http://dxr.mozilla.org/search?tree=mozilla-central&q=%s' % term
|
|
webbrowser.open_new_tab(uri)
|
|
|
|
@Command('mdn', category='misc',
|
|
description='Search for something on MDN.')
|
|
@CommandArgument('term', nargs='+', help='Term(s) to search for.')
|
|
def mdn(self, term):
|
|
import webbrowser
|
|
term = ' '.join(term)
|
|
uri = 'https://developer.mozilla.org/search?q=%s' % term
|
|
webbrowser.open_new_tab(uri)
|
|
|
|
@Command('google', category='misc',
|
|
description='Search for something on Google.')
|
|
@CommandArgument('term', nargs='+', help='Term(s) to search for.')
|
|
def google(self, term):
|
|
import webbrowser
|
|
term = ' '.join(term)
|
|
uri = 'https://www.google.com/search?q=%s' % term
|
|
webbrowser.open_new_tab(uri)
|
|
|
|
@Command('search', category='misc',
|
|
description='Search for something on the Internets. '
|
|
'This will open 3 new browser tabs and search for the term on Google, '
|
|
'MDN, and MXR.')
|
|
@CommandArgument('term', nargs='+', help='Term(s) to search for.')
|
|
def search(self, term):
|
|
self.google(term)
|
|
self.mdn(term)
|
|
self.mxr(term)
|
|
|
|
|
|
class Interface(object):
|
|
'''
|
|
Represents an XPIDL interface, in what file it is defined, what it derives
|
|
from, what its uuid is, and where in the source file the uuid is.
|
|
'''
|
|
def __init__(self, filename, production):
|
|
import xpidl
|
|
assert isinstance(production, xpidl.Interface)
|
|
self.name = production.name
|
|
self.base = production.base
|
|
self.filename = filename
|
|
self.uuid = production.attributes.uuid
|
|
location = production.location
|
|
data = location._lexdata
|
|
attr_pos = data.rfind(b'[', 0, location._lexpos)
|
|
# uuid is always lowercase, but actual file content may not be.
|
|
self.uuid_pos = data[attr_pos:location._lexpos].lower() \
|
|
.rfind(self.uuid) + attr_pos
|
|
|
|
|
|
class InterfaceRegistry(object):
|
|
'''
|
|
Tracks XPIDL interfaces, and allow to search them by name and by the
|
|
interface they derive from.
|
|
'''
|
|
def __init__(self):
|
|
self.by_name = {}
|
|
self.by_base = {}
|
|
|
|
def get_by_name(self, name):
|
|
return self.by_name.get(name, [])
|
|
|
|
def get_by_base(self, base):
|
|
return self.by_base.get(base, [])
|
|
|
|
def add(self, interface):
|
|
l = self.by_name.setdefault(interface.name, [])
|
|
l.append(interface)
|
|
l = self.by_base.setdefault(interface.base, [])
|
|
l.append(interface)
|
|
|
|
|
|
class IDLUpdater(object):
|
|
'''
|
|
Updates interfaces uuids in IDL files.
|
|
'''
|
|
def __init__(self, interfaces):
|
|
from mozpack.copier import FileRegistry
|
|
self.interfaces = interfaces;
|
|
self.registry = FileRegistry()
|
|
|
|
def add(self, name):
|
|
for interface in self.interfaces.get_by_name(name):
|
|
self._add(interface)
|
|
|
|
def _add(self, interface):
|
|
from mozpack.files import GeneratedFile
|
|
from uuid import uuid4
|
|
path = interface.filename
|
|
if not self.registry.contains(path):
|
|
self.registry.add(path, GeneratedFile(open(path).read()))
|
|
content = self.registry[path].content
|
|
content = content[:interface.uuid_pos] + str(uuid4()) + \
|
|
content[interface.uuid_pos + len(interface.uuid):]
|
|
self.registry[path].content = content
|
|
|
|
# Recurse through all the interfaces deriving from this one
|
|
for derived in self.interfaces.get_by_base(interface.name):
|
|
self._add(derived)
|
|
|
|
def update(self):
|
|
for p, f in self.registry:
|
|
f.copy(p)
|
|
|
|
|
|
@CommandProvider
|
|
class UUIDProvider(object):
|
|
@Command('uuid', category='misc',
|
|
description='Generate a uuid.')
|
|
@CommandArgument('--format', '-f', choices=['idl', 'cpp', 'c++'],
|
|
help='Output format for the generated uuid.')
|
|
def uuid(self, format=None):
|
|
import uuid
|
|
u = uuid.uuid4()
|
|
if format in [None, 'idl']:
|
|
print(u)
|
|
if format is None:
|
|
print('')
|
|
if format in [None, 'cpp', 'c++']:
|
|
u = u.hex
|
|
print('{ 0x%s, 0x%s, 0x%s, \\' % (u[0:8], u[8:12], u[12:16]))
|
|
pairs = tuple(map(lambda n: u[n:n+2], range(16, 32, 2)))
|
|
print((' { ' + '0x%s, ' * 7 + '0x%s } }') % pairs)
|
|
|
|
@Command('update-uuids', category='misc',
|
|
description='Update IDL files with new UUIDs.')
|
|
@CommandArgument('--path', default='.',
|
|
help='Base path under which uuids will be searched.')
|
|
@CommandArgument('interfaces', nargs='+',
|
|
help='Changed interfaces whose UUIDs need to be updated. ' +
|
|
'Their descendants are updated as well.')
|
|
def update_uuids(self, path, interfaces):
|
|
import os
|
|
import xpidl
|
|
from mozpack.files import FileFinder
|
|
import mozpack.path
|
|
from tempfile import mkdtemp
|
|
|
|
finder = FileFinder(path, find_executables=False)
|
|
# Avoid creating xpidllex and xpidlyacc in the current directory.
|
|
tmpdir = mkdtemp()
|
|
try:
|
|
parser = xpidl.IDLParser(outputdir=tmpdir)
|
|
registry = InterfaceRegistry()
|
|
for p, f in finder.find('**/*.idl'):
|
|
p = mozpack.path.join(path, p)
|
|
try:
|
|
content = f.open().read()
|
|
idl = parser.parse(content, filename=p)
|
|
except Exception:
|
|
continue
|
|
for prod in idl.productions:
|
|
if isinstance(prod, xpidl.Interface):
|
|
registry.add(Interface(p, prod))
|
|
finally:
|
|
import shutil
|
|
shutil.rmtree(tmpdir)
|
|
|
|
updates = IDLUpdater(registry)
|
|
|
|
for interface in interfaces:
|
|
updates.add(interface)
|
|
|
|
updates.update()
|
|
|
|
@CommandProvider
|
|
class PastebinProvider(object):
|
|
@Command('pastebin', category='misc',
|
|
description='Command line interface to pastebin.mozilla.org.')
|
|
@CommandArgument('--language', default=None,
|
|
help='Language to use for syntax highlighting')
|
|
@CommandArgument('--poster', default=None,
|
|
help='Specify your name for use with pastebin.mozilla.org')
|
|
@CommandArgument('--duration', default='day',
|
|
choices=['d', 'day', 'm', 'month', 'f', 'forever'],
|
|
help='Keep for specified duration (default: %(default)s)')
|
|
@CommandArgument('file', nargs='?', default=None,
|
|
help='Specify the file to upload to pastebin.mozilla.org')
|
|
|
|
def pastebin(self, language, poster, duration, file):
|
|
import sys
|
|
import urllib
|
|
|
|
URL = 'http://pastebin.mozilla.org/'
|
|
|
|
FILE_TYPES = [{'value': 'text', 'name': 'None', 'extension': 'txt'},
|
|
{'value': 'bash', 'name': 'Bash', 'extension': 'sh'},
|
|
{'value': 'c', 'name': 'C', 'extension': 'c'},
|
|
{'value': 'cpp', 'name': 'C++', 'extension': 'cpp'},
|
|
{'value': 'html4strict', 'name': 'HTML', 'extension': 'html'},
|
|
{'value': 'javascript', 'name': 'Javascript', 'extension': 'js'},
|
|
{'value': 'javascript', 'name': 'Javascript', 'extension': 'jsm'},
|
|
{'value': 'lua', 'name': 'Lua', 'extension': 'lua'},
|
|
{'value': 'perl', 'name': 'Perl', 'extension': 'pl'},
|
|
{'value': 'php', 'name': 'PHP', 'extension': 'php'},
|
|
{'value': 'python', 'name': 'Python', 'extension': 'py'},
|
|
{'value': 'ruby', 'name': 'Ruby', 'extension': 'rb'},
|
|
{'value': 'css', 'name': 'CSS', 'extension': 'css'},
|
|
{'value': 'diff', 'name': 'Diff', 'extension': 'diff'},
|
|
{'value': 'ini', 'name': 'INI file', 'extension': 'ini'},
|
|
{'value': 'java', 'name': 'Java', 'extension': 'java'},
|
|
{'value': 'xml', 'name': 'XML', 'extension': 'xml'},
|
|
{'value': 'xml', 'name': 'XML', 'extension': 'xul'}]
|
|
|
|
lang = ''
|
|
|
|
if file:
|
|
try:
|
|
with open(file, 'r') as f:
|
|
content = f.read()
|
|
# TODO: Use mime-types instead of extensions; suprocess('file <f_name>')
|
|
# Guess File-type based on file extension
|
|
extension = file.split('.')[-1]
|
|
for l in FILE_TYPES:
|
|
if extension == l['extension']:
|
|
print('Identified file as %s' % l['name'])
|
|
lang = l['value']
|
|
except IOError:
|
|
print('ERROR. No such file')
|
|
return 1
|
|
else:
|
|
content = sys.stdin.read()
|
|
duration = duration[0]
|
|
|
|
if language:
|
|
lang = language
|
|
|
|
|
|
params = [
|
|
('parent_pid', ''),
|
|
('format', lang),
|
|
('code2', content),
|
|
('poster', poster),
|
|
('expiry', duration),
|
|
('paste', 'Send')]
|
|
|
|
data = urllib.urlencode(params)
|
|
print('Uploading ...')
|
|
try:
|
|
req = urllib2.Request(URL, data)
|
|
response = urllib2.urlopen(req)
|
|
http_response_code = response.getcode()
|
|
if http_response_code == 200:
|
|
print(response.geturl())
|
|
else:
|
|
print('Could not upload the file, '
|
|
'HTTP Response Code %s' %(http_response_code))
|
|
except urllib2.URLError:
|
|
print('ERROR. Could not connect to pastebin.mozilla.org.')
|
|
return 1
|
|
return 0
|
|
|
|
|
|
@CommandProvider
|
|
class ReviewboardToolsProvider(MachCommandBase):
|
|
@Command('rbt', category='devenv', allow_all_args=True,
|
|
description='Run Reviewboard Tools')
|
|
@CommandArgument('args', nargs='...', help='Arguments to rbt tool')
|
|
def rbt(self, args):
|
|
if not args:
|
|
args = ['help']
|
|
|
|
self._activate_virtualenv()
|
|
# We install RBTools from source control because the currently released
|
|
# version doesn't have patches that make Mercurial usable in many
|
|
# scenarios.
|
|
commit = '416a728292dff3f279e5d695f48a29749b51b77a'
|
|
self.virtualenv_manager.install_pip_package(
|
|
'git+https://github.com/reviewboard/rbtools.git@%s#egg=RBTools' %
|
|
commit)
|
|
|
|
from rbtools.commands.main import main
|
|
|
|
# main() doesn't accept arguments and instead reads from sys.argv. So,
|
|
# we fake it out.
|
|
sys.argv = ['rbt'] + args
|
|
return main()
|
|
|
|
@CommandProvider
|
|
class FormatProvider(MachCommandBase):
|
|
@Command('clang-format', category='devenv', allow_all_args=True,
|
|
description='Run clang-format on current changes')
|
|
@CommandArgument('args', nargs='...', help='Arguments to clang-format tool')
|
|
def clang_format(self, args):
|
|
if not args:
|
|
args = ['help']
|
|
|
|
fmt = "clang-format-3.5"
|
|
fmt_diff = "clang-format-diff-3.5"
|
|
|
|
# We are currently using a modified verion of clang-format hosted on people.mozilla.org.
|
|
# This is a temporary work around until we upstream the necessary changes and we can use
|
|
# a system version of clang-format. See bug 961541.
|
|
self.prompt = 1
|
|
plat = platform.system()
|
|
if plat == "Windows":
|
|
fmt += ".exe"
|
|
else:
|
|
arch = os.uname()[4]
|
|
if plat != "Linux" or arch != 'x86_64':
|
|
print("Unsupported platform " + plat + "/" + arch +
|
|
". Supported platforms are Windows/* and Linux/x86_64")
|
|
return 1
|
|
|
|
os.chdir(self.topsrcdir)
|
|
|
|
try:
|
|
if not self.locate_or_fetch(fmt):
|
|
return 1
|
|
clang_format_diff = self.locate_or_fetch(fmt_diff)
|
|
if not clang_format_diff:
|
|
return 1
|
|
|
|
except urllib2.HTTPError as e:
|
|
print("HTTP error {0}: {1}".format(e.code, e.reason))
|
|
return 1
|
|
|
|
from subprocess import Popen, PIPE
|
|
p1 = Popen(["hg", "diff", "-U0", "-r", "tip^", "--include", "glob:**.c", "--include", "glob:**.cpp",
|
|
"--include", "glob:**.h", "--exclude", "listfile:.clang-format-ignore"], stdout=PIPE)
|
|
p2 = Popen([sys.executable, clang_format_diff, "-i", "-p1", "-style=Mozilla"], stdin=p1.stdout)
|
|
return p2.communicate()[0]
|
|
|
|
def locate_or_fetch(self, root):
|
|
target = os.path.join(self._mach_context.state_dir, root)
|
|
if not os.path.exists(target):
|
|
site = "http://people.mozilla.org/~ajones/clang-format/"
|
|
if self.prompt and raw_input("Download clang-format executables from {0} (yN)? ".format(site)).lower() != 'y':
|
|
print("Download aborted.")
|
|
return 1
|
|
self.prompt = 0
|
|
|
|
u = site + root
|
|
print("Downloading {0} to {1}".format(u, target))
|
|
data = urllib2.urlopen(url=u).read()
|
|
temp = target + ".tmp"
|
|
with open(temp, "wb") as fh:
|
|
fh.write(data)
|
|
fh.close()
|
|
os.chmod(temp, os.stat(temp).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
|
os.rename(temp, target)
|
|
return target
|
|
|