[Pkg-mozext-commits] [adblock-plus] 157/464: Generalized command line parsing/help texts, prepared build tool to support non-Gecko extensions
David Prévot
taffit at moszumanska.debian.org
Tue Jul 22 20:44:13 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository adblock-plus.
commit 5454e351acacbf055a46f0d888c89d6029a1df32
Author: Wladimir Palant <trev at adblockplus.org>
Date: Fri May 20 13:30:52 2011 +0200
Generalized command line parsing/help texts, prepared build tool to support non-Gecko extensions
---
build.py | 332 ++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 200 insertions(+), 132 deletions(-)
diff --git a/build.py b/build.py
index 7d3bd80..4506f9f 100644
--- a/build.py
+++ b/build.py
@@ -10,42 +10,146 @@ from getopt import getopt, GetoptError
import buildtools.packager as packager
import buildtools.releaseAutomation as releaseAutomation
-def usage_build(scriptName):
- print '''%(name)s build [options] [output_file]
+class Command(object):
+ name = property(lambda self: self._name)
+ shortDescription = property(lambda self: self._shortDescription,
+ lambda self, value: self.__dict__.update({'_shortDescription': value}))
+ description = property(lambda self: self._description,
+ lambda self, value: self.__dict__.update({'_description': value}))
+ params = property(lambda self: self._params,
+ lambda self, value: self.__dict__.update({'_params': value}))
+ supportedTypes = property(lambda self: self._supportedTypes,
+ lambda self, value: self.__dict__.update({'_supportedTypes': value}))
+ options = property(lambda self: self._options)
+
+ def __init__(self, handler, name):
+ self._handler = handler
+ self._name = name
+ self._shortDescription = ''
+ self._description = ''
+ self._params = ''
+ self._supportedTypes = None
+ self._options = []
+ self.addOption('Show this message and exit', short='h', long='help')
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ pass
+
+ def __call__(self, baseDir, scriptName, opts, args, type):
+ return self._handler(baseDir, scriptName, opts, args, type)
+
+ def isSupported(self, type):
+ return self._supportedTypes == None or type in self._supportedTypes
+
+ def addOption(self, description, short=None, long=None, value=None):
+ self._options.append((description, short, long, value))
+
+ def parseArgs(self, args):
+ shortOptions = map(lambda o: o[1]+':' if o[3] != None else o[1], filter(lambda o: o[1] != None, self._options))
+ longOptions = map(lambda o: o[2]+'=' if o[3] != None else o[2], filter(lambda o: o[2] != None, self._options))
+ return getopt(args, ''.join(shortOptions), longOptions)
+
+
+commandsList = []
+commands = {}
+def addCommand(handler, name):
+ if isinstance(name, basestring):
+ aliases = ()
+ else:
+ name, aliases = (name[0], name[1:])
+
+ global commandsList, commands
+ command = Command(handler, name)
+ commandsList.append(command)
+ commands[name] = command
+ for alias in aliases:
+ commands[alias] = command
+ return command
+
+def splitByLength(string, maxLen):
+ parts = []
+ currentPart = ''
+ for match in re.finditer(r'\s*(\S+)', string):
+ if len(match.group(0)) + len(currentPart) < maxLen:
+ currentPart += match.group(0)
+ else:
+ parts.append(currentPart)
+ currentPart = match.group(1)
+ if len(currentPart):
+ parts.append(currentPart)
+ return parts
+
+def usage(scriptName, type, commandName=None):
+ if commandName == None:
+ global commandsList
+ descriptions = []
+ for command in commandsList:
+ if not command.isSupported(type):
+ continue
+ commandText = ('%s %s' % (command.name, command.params)).ljust(39)
+ descriptionParts = splitByLength(command.shortDescription, 29)
+ descriptions.append(' %s %s %s' % (scriptName, commandText, descriptionParts[0]))
+ for part in descriptionParts[1:]:
+ descriptions.append(' %s %s %s' % (' ' * len(scriptName), ' ' * len(commandText), part))
+ print '''Usage:
+
+%(descriptions)s
+
+For details on a command run:
-Creates an extension build with given file name. If output_file is missing a
-default name will be chosen.
+ %(scriptName)s <command> --help
+''' % {
+ 'scriptName': scriptName,
+ 'descriptions': '\n'.join(descriptions)
+ }
+ else:
+ global commands
+ command = commands[commandName]
+ description = '\n'.join(map(lambda s: '\n'.join(splitByLength(s, 80)), command.description.split('\n')))
+ options = []
+ for descr, short, long, value in command.options:
+ if short == None:
+ shortText = ''
+ elif value == None:
+ shortText = '-%s' % short
+ else:
+ shortText = '-%s %s' % (short, value)
+ if long == None:
+ longText = ''
+ elif value == None:
+ longText = '--%s' % long
+ else:
+ longText = '--%s=%s' % (long, value)
+ descrParts = splitByLength(descr, 46)
+ options.append(' %s %s %s' % (shortText.ljust(11), longText.ljust(19), descrParts[0]))
+ for part in descrParts[1:]:
+ options.append(' %s %s %s' % (' ' * 11, ' ' * 19, part))
+ print '''%(scriptName)s %(name)s %(params)s
+
+%(description)s
Options:
- -h --help Show this message and exit
- -l l1,l2,l3 --locales=l1,l2,l3 Only include the given locales (if omitted:
- all locales not marked as incomplete)
- -b num --build=num Use given build number (if omitted the build
- number will be retrieved from Mercurial)
- -k file --key=file File containing private key and certificates
- required to sign the package
- -r --release Create a release build
- --babelzilla Create a build for Babelzilla
-''' % {"name": scriptName}
-
-def runBuild(baseDir, scriptName, args):
- try:
- opts, args = getopt(args, 'hl:b:k:r:', ['help', 'locales', 'build=', 'key=', 'release', 'babelzilla'])
- except GetoptError, e:
- print str(e)
- usage_build(scriptName)
- sys.exit(2)
+%(options)s
+''' % {
+ 'scriptName': scriptName,
+ 'name': command.name,
+ 'params': command.params,
+ 'description': description,
+ 'options': '\n'.join(options)
+ }
+
+def runBuild(baseDir, scriptName, opts, args, type):
locales = None
buildNum = None
releaseBuild = False
keyFile = None
limitMetadata = False
for option, value in opts:
- if option in ('-h', '--help'):
- usage_build(scriptName)
- return
- elif option in ('-l', '--locales'):
+ if option in ('-l', '--locales'):
locales = value.split(',')
elif option in ('-b', '--build'):
buildNum = int(value)
@@ -63,35 +167,10 @@ def runBuild(baseDir, scriptName, args):
limitMetadata=limitMetadata)
-def usage_testenv(scriptName):
- print '''%(name)s testenv [options] [profile_dir] ...
-
-Sets up the extension in given profiles in such a way that most files are read
-from the current directory. Changes in the files here will be available to these
-profiles immediately after a restart without having to reinstall the extension.
-If no directories are given the list of directories is read from a file.
-
-Options
- -h --help Show this message and exit
- -d file --dirs=file File listing profile directories to set up if
- none are given on command line (default is
- .profileDirs)
-''' % {"name": scriptName}
-
-def setupTestEnvironment(baseDir, scriptName, args):
- try:
- opts, args = getopt(args, 'hd:', ['help', 'dirs='])
- except GetoptError, e:
- print str(e)
- usage_testenv(scriptName)
- sys.exit(2)
-
+def setupTestEnvironment(baseDir, scriptName, opts, args, type):
dirsFile = '.profileDirs'
for option, value in opts:
- if option in ('-h', '--help'):
- usage_testenv(scriptName)
- return
- elif option in ('-d', '--dirs'):
+ if option in ('-d', '--dirs'):
dirsFile = value
profileDirs = args
@@ -102,31 +181,10 @@ def setupTestEnvironment(baseDir, scriptName, args):
packager.setupTestEnvironment(baseDir, profileDirs)
-def usage_showdesc(scriptName):
- print '''%(name)s showdesc [options]
-
-Display description strings for all locales as specified in the corresponding
-meta.properties files.
-
-Options
- -h --help Show this message and exit
- -l l1,l2,l3 --locales=l1,l2,l3 Only include the given locales
-''' % {"name": scriptName}
-
-def showDescriptions(baseDir, scriptName, args):
- try:
- opts, args = getopt(args, 'hl:', ['help', 'locales='])
- except GetoptError, e:
- print str(e)
- usage_showdesc(scriptName)
- sys.exit(2)
-
+def showDescriptions(baseDir, scriptName, opts, args, type):
locales = None
for option, value in opts:
- if option in ('-h', '--help'):
- usage_showdesc(scriptName)
- return
- elif option in ('-l', '--locales'):
+ if option in ('-l', '--locales'):
locales = value.split(',')
if locales == None:
@@ -151,50 +209,25 @@ def showDescriptions(baseDir, scriptName, args):
locale['description.long'] if 'description.long' in locale else 'None',
)).encode('utf-8')
-def usage_release(scriptName):
- print '''%(name)s release [options] <version>
-
-Note: If you are not the project owner then you probably don't want to run this!
-
-Runs release automation: creates downloads for the new version, tags source code
-repository as well as downloads and buildtools repository.
-
-Options
- -h --help Show this message and exit
- -k file --key=file File containing private key and certificates
- required to sign the release
- -d dir --downloads=dir Directory containing downloads repository
- (if omitted ../downloads is assumed)
-''' % {"name": scriptName}
-
-def runReleaseAutomation(baseDir, scriptName, args):
- try:
- opts, args = getopt(args, 'hk:d:', ['help', 'key=', 'downloads='])
- except GetoptError, e:
- print str(e)
- usage_release(scriptName)
- sys.exit(2)
+def runReleaseAutomation(baseDir, scriptName, opts, args, type):
buildtoolsRepo = buildtools.__path__[0]
keyFile = None
downloadsRepo = os.path.join(baseDir, '..', 'downloads')
for option, value in opts:
- if option in ('-h', '--help'):
- usage_release(scriptName)
- return
- elif option in ('-k', '--key'):
+ if option in ('-k', '--key'):
keyFile = value
elif option in ('-d', '--downloads'):
downloadsRepo = value
if len(args) == 0:
print 'No version number specified for the release'
- usage_release(scriptName)
+ usage(scriptName, type, 'release')
return
version = args[0]
if re.search(r'[^\w\.]', version):
print 'Wrong version number format'
- usage_release(scriptName)
+ usage(scriptName, type, 'release')
return
if keyFile == None:
@@ -202,23 +235,52 @@ def runReleaseAutomation(baseDir, scriptName, args):
releaseAutomation.run(baseDir, version, keyFile, downloadsRepo, buildtoolsRepo)
+with addCommand(lambda baseDir, scriptName, opts, args, type: usage(scriptName, type), ('help', '-h', '--help')) as command:
+ command.shortDescription = 'Show this message'
+
+with addCommand(runBuild, 'build') as command:
+ command.shortDescription = 'Create a build'
+ command.description = 'Creates an extension build with given file name. If output_file is missing a default name will be chosen.'
+ command.params = '[options] [output_file]'
+ command.addOption('Only include the given locales (if omitted: all locales not marked as incomplete)', short='l', long='locales', value='l1,l2,l3')
+ command.addOption('Use given build number (if omitted the build number will be retrieved from Mercurial)', short='b', long='build', value='num')
+ command.addOption('File containing private key and certificates required to sign the package', short='k', long='key', value='file')
+ command.addOption('Create a release build', short='r', long='release')
+ command.addOption('Create a build for Babelzilla', long='babelzilla')
+ command.supportedTypes = ('gecko')
+
+with addCommand(setupTestEnvironment, 'testenv') as command:
+ command.shortDescription = 'Set up test environment'
+ command.description = 'Sets up the extension in given profiles in such a way '\
+ 'that most files are read from the current directory. Changes in the files '\
+ 'here will be available to these profiles immediately after a restart '\
+ 'without having to reinstall the extension. If no directories are given the '\
+ 'list of directories is read from a file.'
+ command.addOption('File listing profile directories to set up if none are given on command line (default is .profileDirs)', short='d', long='dirs', value='file')
+ command.params = '[options] [profile_dir] ...'
+ command.supportedTypes = ('gecko')
+
+with addCommand(showDescriptions, 'showdesc') as command:
+ command.shortDescription = 'Print description strings for all locales'
+ command.description = 'Display description strings for all locales as specified in the corresponding meta.properties files.'
+ command.addOption('Only include the given locales', short='l', long='locales', value='l1,l2,l3')
+ command.params = '[options]'
+ command.supportedTypes = ('gecko')
+
+with addCommand(runReleaseAutomation, 'release') as command:
+ command.shortDescription = 'Run release automation'
+ command.description = 'Note: If you are not the project owner then you '\
+ 'probably don\'t want to run this!\n\n'\
+ 'Runs release automation: creates downloads for the new version, tags '\
+ 'source code repository as well as downloads and buildtools repository.'
+ command.addOption('File containing private key and certificates required to sign the release', short='k', long='key', value='file')
+ command.addOption('Directory containing downloads repository (if omitted ../downloads is assumed)', short='d', long='downloads', value='dir')
+ command.params = '[options] <version>'
+ command.supportedTypes = ('gecko')
+
+def processArgs(baseDir, args, type='gecko'):
+ global commands
-def usage(scriptName):
- print '''Usage:
-
- %(name)s help Show this message
- %(name)s build [options] [output_file] Create a build
- %(name)s testenv [options] [profile_dir] ... Set up test environment
- %(name)s showdesc [options] Print description strings for
- all locales
- %(name)s release [options] <version> Run release automation
-
-For details on a command run:
-
- %(name)s <command> --help
-''' % {"name": scriptName}
-
-def processArgs(baseDir, args):
scriptName = os.path.basename(args[0])
args = args[1:]
if len(args) == 0:
@@ -230,16 +292,22 @@ No command given, assuming "build". For a list of commands run:
''' % scriptName
command = args[0]
- if command == 'help' or command == '--help' or command == '-h':
- usage(scriptName)
- elif command == 'build':
- runBuild(baseDir, scriptName, args[1:])
- elif command == 'testenv':
- setupTestEnvironment(baseDir, scriptName, args[1:])
- elif command == 'showdesc':
- showDescriptions(baseDir, scriptName, args[1:])
- elif command == 'release':
- runReleaseAutomation(baseDir, scriptName, args[1:])
+ if command in commands:
+ if commands[command].isSupported(type):
+ try:
+ opts, args = commands[command].parseArgs(args[1:])
+ except GetoptError, e:
+ print str(e)
+ usage(scriptName, type, command)
+ sys.exit(2)
+ for option, value in opts:
+ if option in ('-h', '--help'):
+ usage(scriptName, type, command)
+ sys.exit()
+ commands[command](baseDir, scriptName, opts, args, type)
+ else:
+ print 'Command %s is not supported for this application type' % command
+ usage(scriptName, type)
else:
print 'Command %s is unrecognized' % command
- usage(scriptName)
+ usage(scriptName, type)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git
More information about the Pkg-mozext-commits
mailing list