123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- # 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 absolute_import, unicode_literals
- import sys
- import os
- import stat
- import platform
- import errno
- import subprocess
- from mach.decorators import (
- CommandArgument,
- CommandProvider,
- Command,
- )
- from mozbuild.base import MachCommandBase, MozbuildObject
- @CommandProvider
- class SearchProvider(object):
- @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/mozilla-central/search?q=%s&redirect=true' % 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 DXR.')
- @CommandArgument('term', nargs='+', help='Term(s) to search for.')
- def search(self, term):
- self.google(term)
- self.mdn(term)
- self.dxr(term)
- @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)
- @CommandProvider
- class RageProvider(MachCommandBase):
- @Command('rage', category='misc',
- description='Express your frustration')
- def rage(self):
- """Have a bad experience developing Firefox? Run this command to
- express your frustration.
- This command will open your default configured web browser to a short
- form where you can submit feedback. Just close the tab when done.
- """
- import getpass
- import urllib
- import webbrowser
- # Try to resolve the current user.
- user = None
- with open(os.devnull, 'wb') as null:
- if os.path.exists(os.path.join(self.topsrcdir, '.hg')):
- try:
- user = subprocess.check_output(['hg', 'config',
- 'ui.username'],
- cwd=self.topsrcdir,
- stderr=null)
- i = user.find('<')
- if i >= 0:
- user = user[i + 1:-2]
- except subprocess.CalledProcessError:
- pass
- elif os.path.exists(os.path.join(self.topsrcdir, '.git')):
- try:
- user = subprocess.check_output(['git', 'config', '--get',
- 'user.email'],
- cwd=self.topsrcdir,
- stderr=null)
- except subprocess.CalledProcessError:
- pass
- if not user:
- try:
- user = getpass.getuser()
- except Exception:
- pass
- url = 'https://docs.google.com/a/mozilla.com/forms/d/e/1FAIpQLSeDVC3IXJu5d33Hp_ZTCOw06xEUiYH1pBjAqJ1g_y63sO2vvA/viewform'
- if user:
- url += '?entry.1281044204=%s' % urllib.quote(user)
- print('Please leave your feedback in the opened web form')
- webbrowser.open_new_tab(url)
- @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='',
- 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 urllib
- import urllib2
- URL = 'https://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 FormatProvider(MachCommandBase):
- @Command('clang-format', category='misc',
- description='Run clang-format on current changes')
- @CommandArgument('--show', '-s', action = 'store_true',
- help = 'Show diff output on instead of applying changes')
- def clang_format(self, show=False):
- import urllib2
- plat = platform.system()
- fmt = plat.lower() + "/clang-format-3.5"
- fmt_diff = "clang-format-diff-3.5"
- # We are currently using a modified version 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.
- if plat == "Windows":
- fmt += ".exe"
- else:
- arch = os.uname()[4]
- if (plat != "Linux" and plat != "Darwin") or arch != 'x86_64':
- print("Unsupported platform " + plat + "/" + arch +
- ". Supported platforms are Windows/*, Linux/x86_64 and Darwin/x86_64")
- return 1
- os.chdir(self.topsrcdir)
- self.prompt = True
- 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
- if os.path.exists(".hg"):
- diff_process = Popen(["hg", "diff", "-U0", "-r", "tip^",
- "--include", "glob:**.c", "--include", "glob:**.cpp", "--include", "glob:**.h",
- "--exclude", "listfile:.clang-format-ignore"], stdout=PIPE)
- else:
- git_process = Popen(["git", "diff", "-U0", "HEAD^"], stdout=PIPE)
- try:
- diff_process = Popen(["filterdiff", "--include=*.h", "--include=*.cpp",
- "--exclude-from-file=.clang-format-ignore"],
- stdin=git_process.stdout, stdout=PIPE)
- except OSError as e:
- if e.errno == errno.ENOENT:
- print("Can't find filterdiff. Please install patchutils.")
- else:
- print("OSError {0}: {1}".format(e.code, e.reason))
- return 1
- args = [sys.executable, clang_format_diff, "-p1"]
- if not show:
- args.append("-i")
- cf_process = Popen(args, stdin=diff_process.stdout)
- return cf_process.communicate()[0]
- def locate_or_fetch(self, root):
- target = os.path.join(self._mach_context.state_dir, os.path.basename(root))
- if not os.path.exists(target):
- site = "https://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 = False
- 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
- def mozregression_import():
- # Lazy loading of mozregression.
- # Note that only the mach_interface module should be used from this file.
- try:
- import mozregression.mach_interface
- except ImportError:
- return None
- return mozregression.mach_interface
- def mozregression_create_parser():
- # Create the mozregression command line parser.
- # if mozregression is not installed, or not up to date, it will
- # first be installed.
- cmd = MozbuildObject.from_environment()
- cmd._activate_virtualenv()
- mozregression = mozregression_import()
- if not mozregression:
- # mozregression is not here at all, install it
- cmd.virtualenv_manager.install_pip_package('mozregression')
- print("mozregression was installed. please re-run your"
- " command. If you keep getting this message please "
- " manually run: 'pip install -U mozregression'.")
- else:
- # check if there is a new release available
- release = mozregression.new_release_on_pypi()
- if release:
- print(release)
- # there is one, so install it. Note that install_pip_package
- # does not work here, so just run pip directly.
- cmd.virtualenv_manager._run_pip([
- 'install',
- 'mozregression==%s' % release
- ])
- print("mozregression was updated to version %s. please"
- " re-run your command." % release)
- else:
- # mozregression is up to date, return the parser.
- return mozregression.parser()
- # exit if we updated or installed mozregression because
- # we may have already imported mozregression and running it
- # as this may cause issues.
- sys.exit(0)
- @CommandProvider
- class MozregressionCommand(MachCommandBase):
- @Command('mozregression',
- category='misc',
- description=("Regression range finder for nightly"
- " and inbound builds."),
- parser=mozregression_create_parser)
- def run(self, **options):
- self._activate_virtualenv()
- mozregression = mozregression_import()
- mozregression.run(options)
|