# 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__importabsolute_import,unicode_literalsimportsysimportosimportstatimportplatformimporterrnofrommach.decoratorsimport(CommandArgument,CommandProvider,Command,)frommozbuild.baseimportMachCommandBase,MozbuildObject@CommandProviderclassSearchProvider(object):@Command('dxr',category='misc',description='Search for something in DXR.')@CommandArgument('term',nargs='+',help='Term(s) to search for.')defdxr(self,term):importwebbrowserterm=' '.join(term)uri='http://dxr.mozilla.org/mozilla-central/search?q=%s&redirect=true'%termwebbrowser.open_new_tab(uri)@Command('mdn',category='misc',description='Search for something on MDN.')@CommandArgument('term',nargs='+',help='Term(s) to search for.')defmdn(self,term):importwebbrowserterm=' '.join(term)uri='https://developer.mozilla.org/search?q=%s'%termwebbrowser.open_new_tab(uri)@Command('google',category='misc',description='Search for something on Google.')@CommandArgument('term',nargs='+',help='Term(s) to search for.')defgoogle(self,term):importwebbrowserterm=' '.join(term)uri='https://www.google.com/search?q=%s'%termwebbrowser.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.')defsearch(self,term):self.google(term)self.mdn(term)self.dxr(term)@CommandProviderclassUUIDProvider(object):@Command('uuid',category='misc',description='Generate a uuid.')@CommandArgument('--format','-f',choices=['idl','cpp','c++'],help='Output format for the generated uuid.')defuuid(self,format=None):importuuidu=uuid.uuid4()ifformatin[None,'idl']:print(u)ifformatisNone:print('')ifformatin[None,'cpp','c++']:u=u.hexprint('{ 0x%s, 0x%s, 0x%s, \\'%(u[0:8],u[8:12],u[12:16]))pairs=tuple(map(lambdan:u[n:n+2],range(16,32,2)))print((' { '+'0x%s, '*7+'0x%s } }')%pairs)@CommandProviderclassPastebinProvider(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')defpastebin(self,language,poster,duration,file):importurllibimporturllib2URL='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=''iffile:try:withopen(file,'r')asf:content=f.read()# TODO: Use mime-types instead of extensions; suprocess('file <f_name>')# Guess File-type based on file extensionextension=file.split('.')[-1]forlinFILE_TYPES:ifextension==l['extension']:print('Identified file as %s'%l['name'])lang=l['value']exceptIOError:print('ERROR. No such file')return1else:content=sys.stdin.read()duration=duration[0]iflanguage:lang=languageparams=[('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()ifhttp_response_code==200:print(response.geturl())else:print('Could not upload the file, ''HTTP Response Code %s'%(http_response_code))excepturllib2.URLError:print('ERROR. Could not connect to pastebin.mozilla.org.')return1return0@CommandProviderclassFormatProvider(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')defclang_format(self,show=False):importurllib2plat=platform.system()fmt=plat.lower()+"/clang-format-5.0~svn297730"fmt_diff="clang-format-diff-5.0~svn297730"# We are currently using an unmodified snapshot of upstream clang-format.# This is a temporary work around until clang 5.0 has been released with our changes.ifplat=="Windows":fmt+=".exe"else:arch=os.uname()[4]if(plat!="Linux"andplat!="Darwin")orarch!='x86_64':print("Unsupported platform "+plat+"/"+arch+". Supported platforms are Windows/*, Linux/x86_64 and Darwin/x86_64")return1os.chdir(self.topsrcdir)self.prompt=Truetry:ifnotself.locate_or_fetch(fmt):return1clang_format_diff=self.locate_or_fetch(fmt_diff,python_script=True)ifnotclang_format_diff:return1excepturllib2.HTTPErrorase:print("HTTP error {0}: {1}".format(e.code,e.reason))return1fromsubprocessimportPopen,PIPEifos.path.exists(".hg"):diff_process=Popen(["hg","diff","-U0","-r",".^","--include","glob:**.c","--include","glob:**.cpp","--include","glob:**.h","--exclude","listfile:.clang-format-ignore"],stdout=PIPE)else:git_process=Popen(["git","diff","--no-color","-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)exceptOSErrorase:ife.errno==errno.ENOENT:print("Can't find filterdiff. Please install patchutils.")else:print("OSError {0}: {1}".format(e.code,e.reason))return1args=[sys.executable,clang_format_diff,"-p1"]ifnotshow:args.append("-i")cf_process=Popen(args,stdin=diff_process.stdout)returncf_process.communicate()[0]deflocate_or_fetch(self,root,python_script=False):importurllib2importhashlibbin_sha={"Windows":"0cbfc306df48f01bfe804e5e89cef73b3abe8f884fb7a5208f8895897f19ec45c13760787298192bd37de057d0ded091640c7d504438e06ec880f071a38db89c",# noqa: E501"Linux":"e6da4f6df074bfb15caefcf7767eb5670c02bb4768ba86ae4ab6b35235b53db012900a4f9e9a950ee140158a19532a71f21b986f511826bebc16f2ef83984e57",# noqa: E501"Darwin":"18000940a11e5ab0c1fe950d4360292216c8e963dd708679c4c5fb8cc845f5919cef3f58a7e092555b8ea6b8d8a809d66153ea6d1e7c226a2c4f2b0b7ad1b2f3",# noqa: E501"python_script":"34b6934a48a263ea3f88d48c2981d61ae6698823cfa689b9b0c8a607c224437ca0b9fdd434d260bd790d52a98455e2c2e2c745490d327ba84b4e22b7bb55b757",# noqa: E501}target=os.path.join(self._mach_context.state_dir,os.path.basename(root))ifnotos.path.exists(target):tooltool_url="https://api.pub.build.mozilla.org/tooltool/sha512/"ifself.promptandraw_input("Download clang-format executables from {0} (yN)? ".format(tooltool_url)).lower()!='y':# noqa: E501,F821print("Download aborted.")returnNoneself.prompt=Falseplat=platform.system()ifpython_script:# We want to download the python script (clang-format-diff)dl=bin_sha["python_script"]else:dl=bin_sha[plat]u=tooltool_url+dlprint("Downloading {0} to {1}".format(u,target))data=urllib2.urlopen(url=u).read()temp=target+".tmp"# Check that the checksum of the downloaded data matches the hash# of the filesha512Hash=hashlib.sha512(data).hexdigest()ifsha512Hash!=dl:print("Checksum verification for {0} failed: {1} found instead of {2} ".format(target,sha512Hash,dl))# noqa: E501return1withopen(temp,"wb")asfh: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)returntargetdefmozregression_import():# Lazy loading of mozregression.# Note that only the mach_interface module should be used from this file.try:importmozregression.mach_interfaceexceptImportError:returnNonereturnmozregression.mach_interfacedefmozregression_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()ifnotmozregression:# mozregression is not here at all, install itcmd.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 availablerelease=mozregression.new_release_on_pypi()ifrelease: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.returnmozregression.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)@CommandProviderclassMozregressionCommand(MachCommandBase):@Command('mozregression',category='misc',description=("Regression range finder for nightly"" and inbound builds."),parser=mozregression_create_parser)defrun(self,**options):self._activate_virtualenv()mozregression=mozregression_import()mozregression.run(options)