Improved the hm command a little more (made argument handling easier)

This commit is contained in:
Nick Bolton 2010-04-11 02:22:15 +00:00
parent 63d8668497
commit 10a3a5300c
2 changed files with 736 additions and 659 deletions

View File

@ -1,7 +1,9 @@
import sys, os, ConfigParser, subprocess, shutil # TODO: split this file up, it's too long!
if sys.platform == 'win32': import sys, os, ConfigParser, subprocess, shutil
import _winreg from getopt import getopt
class InternalCommands:
project = 'synergy-plus' project = 'synergy-plus'
setup_version = 3 setup_version = 3
@ -64,23 +66,23 @@ darwin_generators = {
'6' : 'KDevelop3 - Unix Makefiles', '6' : 'KDevelop3 - Unix Makefiles',
} }
def config_filepath(): def config_filepath(self):
return '%s/%s' % (bin_dir, config_filename) return '%s/%s' % (self.bin_dir, self.config_filename)
def sln_filepath(): def sln_filepath(self):
return '%s\%s' % (bin_dir, sln_filename) return '%s\%s' % (self.bin_dir, self.sln_filename)
def xcodeproj_filepath(): def xcodeproj_filepath(self):
return '%s/%s' % (bin_dir, xcodeproj_filename) return '%s/%s' % (self.bin_dir, self.xcodeproj_filename)
def usage(argv): def usage(self):
app = sys.argv[0] app = sys.argv[0]
print ('Usage: %s [command]\n' print ('Usage: %s [command]\n'
'\n' '\n'
'Replace [command] with one of:\n' 'Replace [command] with one of:\n'
' about Show information about this script\n' ' about Show information about this script\n'
' setup Runs the initial setup for this script\n' ' setup Runs the initial setup for this script\n'
' configure Runs cmake (generates project files)\n' ' conf Runs cmake (generates project files)\n'
' open Attempts to open the generated project file\n' ' open Attempts to open the generated project file\n'
' build Builds using the platform build chain\n' ' build Builds using the platform build chain\n'
' clean Cleans using the platform build chain\n' ' clean Cleans using the platform build chain\n'
@ -94,30 +96,29 @@ def usage(argv):
' reformat Reformat .cpp and .h files using AStyle\n' ' reformat Reformat .cpp and .h files using AStyle\n'
' usage Shows the help screen\n' ' usage Shows the help screen\n'
'\n' '\n'
'Example: %s configure' 'Example: %s conf'
) % (app, app) ) % (app, app)
def configure(argv, generator = None): def configure(self, generator):
err = self.configure_internal(generator)
err = configure_internal(generator)
if err == 0: if err == 0:
print ('Configure complete!\n\n' print ('Configure complete!\n\n'
'Open project now: %s open\n' 'Open project now: %s open\n'
'Command line build: %s build' 'Command line build: %s build'
) % (this_cmd, this_cmd) ) % (self.this_cmd, self.this_cmd)
return True return True
else: else:
return False return False
# TODO: handle svn not installed # TODO: handle svn not installed
# TODO: implement for other platforms # TODO: implement for other platforms
def persist_cmake(): def persist_cmake(self):
if sys.platform == 'win32': if sys.platform == 'win32':
version = '2.8.0' version = '2.8.0'
found_cmd = '' found_cmd = ''
for test_cmd in (cmake_cmd, r'tool\cmake\bin\%s' % cmake_cmd): for test_cmd in (self.cmake_cmd, r'tool\cmake\bin\%s' % self.cmake_cmd):
print 'Testing for CMake version %s at `%s`...' % (version, test_cmd) print 'Testing for CMake version %s at `%s`...' % (version, test_cmd)
p = subprocess.Popen([test_cmd, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) p = subprocess.Popen([test_cmd, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
@ -126,8 +127,8 @@ def persist_cmake():
print 'Found valid CMake version' print 'Found valid CMake version'
found_cmd = test_cmd found_cmd = test_cmd
# HACK: gotta go out so just hacking this for now # HACK: gotta go out so just hacking this for now
if found_cmd == r'tool\cmake\bin\%s' % cmake_cmd: if found_cmd == r'tool\cmake\bin\%s' % self.cmake_cmd:
found_cmd = r'..\tool\cmake\bin\%s' % cmake_cmd found_cmd = r'..\tool\cmake\bin\%s' % self.cmake_cmd
break break
if not found_cmd: if not found_cmd:
@ -146,51 +147,51 @@ def persist_cmake():
return found_cmd return found_cmd
else: else:
return cmake_cmd return self.cmake_cmd
def configure_internal(generator = None): def configure_internal(self, generator = None):
ensure_setup_latest(generator) self.ensure_setup_latest(generator)
_cmake_cmd = persist_cmake() _cmake_cmd = self.persist_cmake()
generator = get_generator() generator = self.get_generator()
if generator != '': if generator != '':
cmake_args = '%s -G "%s"' % (source_dir, generator) cmake_args = '%s -G "%s"' % (self.source_dir, generator)
else: else:
cmake_args = source_dir cmake_args = self.source_dir
cmake_cmd_string = '%s %s' % (_cmake_cmd, cmake_args) cmake_cmd_string = '%s %s' % (_cmake_cmd, cmake_args)
print "Configuring with CMake (%s)..." % cmake_cmd_string print "Configuring with CMake (%s)..." % cmake_cmd_string
# Run from build dir so we have an out-of-source build. # Run from build dir so we have an out-of-source build.
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
err = os.system(cmake_cmd_string) err = os.system(cmake_cmd_string)
restore_chdir() self.restore_chdir()
if err != 0: if err != 0:
print 'CMake encountered error:', err print 'CMake encountered error:', err
else: else:
set_conf_run() self.set_conf_run()
return err; return err;
def build(mode): def build(self, mode = None):
ensure_setup_latest() self.ensure_setup_latest()
if not has_conf_run(): if not self.has_conf_run():
if configure_internal() != 0: if self.configure_internal() != 0:
return False return False
generator = get_generator() generator = self.get_generator()
if generator == "Unix Makefiles": if generator == "Unix Makefiles":
print 'Building with GNU Make...' print 'Building with GNU Make...'
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
err = os.system(make_cmd) err = os.system(make_cmd)
restore_chdir() self.restore_chdir()
if err == 0: if err == 0:
return True return True
@ -200,7 +201,7 @@ def build(mode):
elif generator.startswith('Visual Studio 10') or generator.startswith('Visual Studio 8') or generator.startswith('Visual Studio 9'): elif generator.startswith('Visual Studio 10') or generator.startswith('Visual Studio 8') or generator.startswith('Visual Studio 9'):
ret = run_vcbuild(generator, mode) ret = self.run_vcbuild(generator, mode)
if ret == 0: if ret == 0:
return True return True
@ -211,9 +212,9 @@ def build(mode):
elif generator == 'Xcode': elif generator == 'Xcode':
print 'Building with Xcode...' print 'Building with Xcode...'
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
err = os.system(xcodebuild_cmd) err = os.system(xcodebuild_cmd)
restore_chdir() self.restore_chdir()
if err == 0: if err == 0:
return True return True
@ -225,16 +226,16 @@ def build(mode):
print 'Not supported with generator:',generator print 'Not supported with generator:',generator
return False return False
def clean(mode): def clean(self, mode = None):
generator = get_generator() generator = self.get_generator()
if generator == "Unix Makefiles": if generator == "Unix Makefiles":
print 'Cleaning with GNU Make...' print 'Cleaning with GNU Make...'
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
err = os.system(make_cmd + ' clean') err = os.system(make_cmd + ' clean')
restore_chdir() self.restore_chdir()
if err == 0: if err == 0:
return True return True
@ -244,7 +245,7 @@ def clean(mode):
elif generator.startswith('Visual Studio 10'): elif generator.startswith('Visual Studio 10'):
ret = run_vcbuild(generator, mode, '/target:clean') ret = self.run_vcbuild(generator, mode, '/target:clean')
if ret == 0: if ret == 0:
return True return True
@ -254,7 +255,7 @@ def clean(mode):
elif generator.startswith('Visual Studio 8') or generator.startswith('Visual Studio 9'): elif generator.startswith('Visual Studio 8') or generator.startswith('Visual Studio 9'):
ret = run_vcbuild(generator, mode, '/clean') ret = self.run_vcbuild(generator, mode, '/clean')
if ret == 0: if ret == 0:
return True return True
@ -265,9 +266,9 @@ def clean(mode):
elif generator == 'Xcode': elif generator == 'Xcode':
print 'Cleaning with Xcode...' print 'Cleaning with Xcode...'
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
err = os.system(xcodebuild_cmd + ' clean') err = os.system(xcodebuild_cmd + ' clean')
restore_chdir() self.restore_chdir()
if err == 0: if err == 0:
return True return True
@ -279,23 +280,25 @@ def clean(mode):
print 'clean: Not supported on platform:',sys.platform print 'clean: Not supported on platform:',sys.platform
return False return False
def open_project(): def open(self):
generator = get_generator() generator = self.get_generator()
if generator.startswith('Visual Studio'): if generator.startswith('Visual Studio'):
open_project_internal(sln_filepath()) print 'Opening with %s...' % generator
self.open_internal(self.sln_filepath())
return True return True
elif generator.startswith('Xcode'): elif generator.startswith('Xcode'):
open_project_internal(xcodeproj_filepath(), 'open') print 'Opening with %s...' % generator
self.open_internal(xcodeproj_filepath(), 'open')
return True return True
else: else:
print 'Not supported with generator:',generator print 'Not supported with generator:',generator
return False return False
def update(): def update(self):
print "Running Subversion update..." print "Running Subversion update..."
os.system('svn update') os.system('svn update')
def revision(): def revision(self):
# While this doesn't print out the revision specifically, it will do. # While this doesn't print out the revision specifically, it will do.
os.system('svn info') os.system('svn info')
@ -306,11 +309,11 @@ def destroy(argv):
yn = raw_input() yn = raw_input()
if yn in ['y', 'Y']: if yn in ['y', 'Y']:
try: try:
shutil.rmtree(bin_dir) shutil.rmtree(self.bin_dir)
except: except:
print "Warning: Could not remove ./bin/ directory." print "Warning: Could not remove ./bin/ directory."
def kill(): def kill(self):
if sys.platform == 'win32': if sys.platform == 'win32':
os.system('taskkill /F /FI "IMAGENAME eq synergy*"') os.system('taskkill /F /FI "IMAGENAME eq synergy*"')
return True return True
@ -318,36 +321,36 @@ def kill():
print 'kill: Error: Command not implemented for current platform' print 'kill: Error: Command not implemented for current platform'
return False return False
def package(type): def package(self, type):
# Package is supported by default. # Package is supported by default.
package_unsupported = False package_unsupported = False
if type == None: if type == None:
package_usage() self.package_usage()
elif type == 'src': elif type == 'src':
if sys.platform in ['linux2', 'darwin']: if sys.platform in ['linux2', 'darwin']:
package_tgz() self.package_tgz()
else: else:
package_unsupported = True package_unsupported = True
elif type == 'rpm': elif type == 'rpm':
if sys.platform == 'linux2': if sys.platform == 'linux2':
package_rpm() self.package_rpm()
else: else:
package_unsupported = True package_unsupported = True
elif type == 'deb': elif type == 'deb':
if sys.platform == 'linux2': if sys.platform == 'linux2':
package_deb() self.package_deb()
else: else:
package_unsupported = True package_unsupported = True
elif type == 'win': elif type == 'win':
if sys.platform == 'win32': if sys.platform == 'win32':
package_win() self.package_win()
else: else:
package_unsupported = True package_unsupported = True
elif type == 'mac': elif type == 'mac':
if sys.platform == 'darwin': if sys.platform == 'darwin':
package_mac() self.package_mac()
else: else:
package_unsupported = True package_unsupported = True
else: else:
@ -357,32 +360,32 @@ def package(type):
print ('Package type, %s is not ' print ('Package type, %s is not '
'supported for platform, %s') % (type, sys.platform) 'supported for platform, %s') % (type, sys.platform)
def package_tgz(): def package_tgz(self):
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
os.system('make package_source') os.system('make package_source')
restore_chdir() self.restore_chdir()
def package_rpm(): def package_rpm(self):
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
os.system('cpack -G RPM') os.system('cpack -G RPM')
restore_chdir() self.restore_chdir()
def package_deb(): def package_deb(self):
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
os.system('cpack -G DEB') os.system('cpack -G DEB')
restore_chdir() self.restore_chdir()
def package_win(): def package_win(self):
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
os.system('cpack -G NSIS') os.system('cpack -G NSIS')
restore_chdir() self.restore_chdir()
def package_mac(): def package_mac(self):
try_chdir(bin_dir) self.try_chdir(self.bin_dir)
os.system('cpack -G PackageMaker') os.system('cpack -G PackageMaker')
restore_chdir() self.restore_chdir()
def package_usage(): def package_usage(self):
print ('Usage: %s package [package-type]\n' print ('Usage: %s package [package-type]\n'
'\n' '\n'
'Replace [package-type] with one of:\n' 'Replace [package-type] with one of:\n'
@ -392,25 +395,15 @@ def package_usage():
' win .exe installer (Windows)\n' ' win .exe installer (Windows)\n'
' mac .dmg package (Mac OS X)\n' ' mac .dmg package (Mac OS X)\n'
'\n' '\n'
'Example: %s package src-tgz') % (this_cmd, this_cmd) 'Example: %s package src-tgz') % (self.this_cmd, self.this_cmd)
def about(): def about(self):
print ('Help Me script, from the Synergy+ project.\n' print ('Help Me script, from the Synergy+ project.\n'
'%s\n' '%s\n'
'\n' '\n'
'For help, run: %s help') % (website_url, this_cmd) 'For help, run: %s help') % (self.website_url, self.this_cmd)
# def try_chdir(self, dir):
# Important!
#
# From here on, it's just internal stuff, no need to
# change anything here unless adding new commands, or
# editing the way the script works.
#
def try_chdir(dir):
# Ensure temp build dir exists. # Ensure temp build dir exists.
if not os.path.exists(dir): if not os.path.exists(dir):
@ -422,11 +415,11 @@ def try_chdir(dir):
# It will exist by this point, so it's safe to chdir. # It will exist by this point, so it's safe to chdir.
os.chdir(dir) os.chdir(dir)
def restore_chdir(): def restore_chdir(self):
global prevdir global prevdir
os.chdir(prevdir) os.chdir(prevdir)
def open_project_internal(project_filename, application = ''): def open_internal(self, project_filename, application = ''):
if not os.path.exists(project_filename): if not os.path.exists(project_filename):
print 'Project file (%s) not found, run hm conf first.' % project_filename print 'Project file (%s) not found, run hm conf first.' % project_filename
@ -438,27 +431,27 @@ def open_project_internal(project_filename, application = ''):
os.system(path) os.system(path)
return True return True
def setup(generator = None): def setup(self, generator = None):
print "Running setup..." print "Running setup..."
# If no generator specified, prompt the user. # If no generator specified, prompt the user.
if generator == None: if generator == None:
if sys.platform == 'win32': if sys.platform == 'win32':
generator = setup_generator_get(win32_generators) generator = self.get_setup_generator(self.win32_generators)
elif sys.platform in ['linux2', 'sunos5', 'freebsd7']: elif sys.platform in ['linux2', 'sunos5', 'freebsd7']:
generator = setup_generator_get(unix_generators) generator = self.get_setup_generator(self.unix_generators)
elif sys.platform == 'darwin': elif sys.platform == 'darwin':
generator = setup_generator_get(darwin_generators) generator = self.get_setup_generator(self.darwin_generators)
else: else:
raise Exception('Unsupported platform: ' + sys.platform) raise Exception('Unsupported platform: ' + sys.platform)
# Create build dir, since config file resides there. # Create build dir, since config file resides there.
if not os.path.exists(bin_dir): if not os.path.exists(self.bin_dir):
os.mkdir(bin_dir) os.mkdir(self.bin_dir)
if os.path.exists(config_filepath()): if os.path.exists(self.config_filepath()):
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
config.read(config_filepath()) config.read(self.config_filepath())
else: else:
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
@ -468,31 +461,31 @@ def setup(generator = None):
if not config.has_section('cmake'): if not config.has_section('cmake'):
config.add_section('cmake') config.add_section('cmake')
config.set('hm', 'setup_version', setup_version) config.set('hm', 'setup_version', self.setup_version)
config.set('cmake', 'generator', generator) config.set('cmake', 'generator', generator)
write_config(config) self.write_config(config)
cmakecache_filename = '%s/CMakeCache.txt' % bin_dir cmakecache_filename = '%s/CMakeCache.txt' % self.bin_dir
if os.path.exists(cmakecache_filename): if os.path.exists(cmakecache_filename):
print "Removing %s, since generator changed." % cmakecache_filename print "Removing %s, since generator changed." % cmakecache_filename
os.remove(cmakecache_filename) os.remove(cmakecache_filename)
print "\nSetup complete." print "\nSetup complete."
def write_config(config): def write_config(self, config):
configfile = open(config_filepath(), 'wb') configfile = open(self.config_filepath(), 'wb')
config.write(configfile) config.write(configfile)
def get_generator(): def get_generator(self):
config = ConfigParser.RawConfigParser() config = ConfigParser.RawConfigParser()
config.read(config_filepath()) config.read(self.config_filepath())
return config.get('cmake', 'generator') return config.get('cmake', 'generator')
def has_setup_version(version): def min_setup_version(self, version):
if os.path.exists(config_filepath()): if os.path.exists(self.config_filepath()):
config = ConfigParser.RawConfigParser() config = ConfigParser.RawConfigParser()
config.read(config_filepath()) config.read(self.config_filepath())
try: try:
return config.getint('hm', 'setup_version') >= version return config.getint('hm', 'setup_version') >= version
@ -501,10 +494,10 @@ def has_setup_version(version):
else: else:
return False return False
def has_conf_run(): def has_conf_run(self):
if has_setup_version(2): if self.min_setup_version(2):
config = ConfigParser.RawConfigParser() config = ConfigParser.RawConfigParser()
config.read(config_filepath()) config.read(self.config_filepath())
try: try:
return config.getboolean('hm', 'has_conf_run') return config.getboolean('hm', 'has_conf_run')
except: except:
@ -512,16 +505,16 @@ def has_conf_run():
else: else:
return False return False
def set_conf_run(): def set_conf_run(self):
if has_setup_version(3): if self.min_setup_version(3):
config = ConfigParser.RawConfigParser() config = ConfigParser.RawConfigParser()
config.read(config_filepath()) config.read(self.config_filepath())
config.set('hm', 'has_conf_run', True) config.set('hm', 'has_conf_run', True)
write_config(config) self.write_config(config)
else: else:
raise Exception("User does not have correct setup version.") raise Exception("User does not have correct setup version.")
def setup_generator_get(generators): def get_setup_generator(self, generators):
generator_options = '' generator_options = ''
generators_sorted = sorted(generators.iteritems(), key=lambda t: int(t[0])) generators_sorted = sorted(generators.iteritems(), key=lambda t: int(t[0]))
@ -532,9 +525,9 @@ def setup_generator_get(generators):
print ('\nChoose a CMake generator:%s' print ('\nChoose a CMake generator:%s'
) % generator_options ) % generator_options
return setup_generator_prompt(generators) return self.setup_generator_prompt(generators)
def setup_generator_prompt(generators): def setup_generator_prompt(self, generators):
prompt = 'Enter a number:' prompt = 'Enter a number:'
print prompt, print prompt,
@ -545,12 +538,12 @@ def setup_generator_prompt(generators):
print 'Selected generator:', generators[generator_id] print 'Selected generator:', generators[generator_id]
else: else:
print 'Invalid number, try again.' print 'Invalid number, try again.'
setup_generator_prompt(generators) self.setup_generator_prompt(generators)
return generators[generator_id] return generators[generator_id]
def get_vcvarsall(generator): def get_vcvarsall(self, generator):
import platform import platform, _winreg
# os_bits should be loaded with '32bit' or '64bit' # os_bits should be loaded with '32bit' or '64bit'
(os_bits, other) = platform.architecture() (os_bits, other) = platform.architecture()
@ -581,7 +574,7 @@ def get_vcvarsall(generator):
raise Exception("'%s' not found." % path) raise Exception("'%s' not found." % path)
return path return path
def run_vcbuild(generator, mode, args=''): def run_vcbuild(self, generator, mode, args=''):
import platform import platform
# os_bits should be loaded with '32bit' or '64bit' # os_bits should be loaded with '32bit' or '64bit'
@ -612,54 +605,53 @@ def run_vcbuild(generator, mode, args=''):
cmd = ('@echo off\n' cmd = ('@echo off\n'
'call "%s" %s \n' 'call "%s" %s \n'
'msbuild /nologo %s /p:Configuration="%s" /p:Platform="%s" "%s"' 'msbuild /nologo %s /p:Configuration="%s" /p:Platform="%s" "%s"'
) % (get_vcvarsall(generator), vcvars_platform, args, config, config_platform, sln_filepath()) ) % (self.get_vcvarsall(generator), vcvars_platform, args, config, config_platform, self.sln_filepath())
else: else:
config = config + '|' + config_platform config = config + '|' + config_platform
cmd = ('@echo off\n' cmd = ('@echo off\n'
'call "%s" %s \n' 'call "%s" %s \n'
'vcbuild /nologo %s "%s" "%s"' 'vcbuild /nologo %s "%s" "%s"'
) % (get_vcvarsall(generator), vcvars_platform, args, sln_filepath(), config) ) % (self.get_vcvarsall(generator), vcvars_platform, args, self.sln_filepath(), config)
print cmd print cmd
# Generate a batch file, since we can't use environment variables directly. # Generate a batch file, since we can't use environment variables directly.
temp_bat = bin_dir + r'\vcbuild.bat' temp_bat = self.bin_dir + r'\vcbuild.bat'
file = open(temp_bat, 'w') file = open(temp_bat, 'w')
file.write(cmd) file.write(cmd)
file.close() file.close()
return os.system(temp_bat) return os.system(temp_bat)
def ensure_setup_latest(generator = None): def ensure_setup_latest(self, generator = None):
if not has_setup_version(setup_version): if not self.min_setup_version(self.setup_version):
setup(generator) self.setup(generator)
class HammerBuild: class HammerBuild:
generator = None generator = None
target_dir = None target_dir = None
def __init__(self, _generator, _target_dir): def __init__(self, _generator, _target_dir, ic):
self.generator = _generator self.generator = _generator
self.target_dir = _target_dir self.target_dir = _target_dir
def run(self): def run(self):
global bin_dir ic.bin_dir = self.target_dir
bin_dir = self.target_dir
configure(self.generator) configure(self.generator)
build('debug') build(['debug'])
build('release') build(['release'])
def hammer(): def hammer(self):
hammer_builds = [] hammer_builds = []
if sys.platform == 'win32': if sys.platform == 'win32':
hammer_builds += [ hammer_builds += [
HammerBuild('Visual Studio 9 2008', 'bin32'), HammerBuild('Visual Studio 9 2008', 'bin32', self),
HammerBuild('Visual Studio 9 2008 Win64', 'bin64')] HammerBuild('Visual Studio 9 2008 Win64', 'bin64', self)]
elif sys.platform in ['linux2', 'sunos5', 'freebsd7']: elif sys.platform in ['linux2', 'sunos5', 'freebsd7']:
hammer_builds += [ hammer_builds += [
HammerBuild('Unix Makefiles', 'bin')] HammerBuild('Unix Makefiles', 'bin', self)]
elif sys.platform == 'darwin': elif sys.platform == 'darwin':
hammer_builds += [ hammer_builds += [
HammerBuild('Xcode', 'bin')] HammerBuild('Xcode', 'bin', self)]
for hb in hammer_builds: for hb in hammer_builds:
hb.run() hb.run()
@ -675,9 +667,85 @@ def hammer():
for pt in package_types: for pt in package_types:
package(pt) package(pt)
def reformat(): def reformat(self):
# TODO: error handling # TODO: error handling
os.system( os.system(
r'tool\astyle\AStyle.exe ' r'tool\astyle\AStyle.exe '
'--quiet --suffix=none --style=java --indent=force-tab=4 --recursive ' '--quiet --suffix=none --style=java --indent=force-tab=4 --recursive '
'lib/*.cpp lib/*.h cmd/*.cpp cmd/*.h') 'lib/*.cpp lib/*.h cmd/*.cpp cmd/*.h')
# the command handler should be called only from hm.py (i.e. directly
# from the command prompt). the purpose of this class is so that we
# don't need to do argument handling all over the place in the internal
# commands class.
class CommandHandler:
ic = InternalCommands()
def __init__(self, argv, optarg_data):
self.opts, self.args = getopt(argv, optarg_data[0], optarg_data[1])
def get_build_mode(self):
mode = None
if len(self.args) > 0:
mode = self.args[0]
else:
for o, a in self.opts:
if o == '-d':
mode = 'debug'
elif o == '-r':
mode = 'release'
return mode
def about(self):
self.ic.about()
def setup(self):
self.ic.setup()
def configure(self):
generator = None
if len(self.args) > 0:
generator = self.args[0]
self.ic.configure(generator)
def build(self):
self.ic.build(self.get_build_mode())
def clean(self):
self.ic.clean(self.get_build_mode())
def update(self):
self.ic.update()
def install(self):
print 'Not yet implemented: install'
def package(self):
self.ic.package()
def destroy(self):
self.ic.destroy()
def package(self):
type = None
if len(self.args) > 0:
type = self.args[0]
self.ic.package(type)
def kill(self):
self.ic.kill()
def usage(self):
self.ic.usage()
def revision(self):
self.ic.revision()
def hammer(self):
self.ic.hammer()
def reformat(self):
self.ic.reformat()
def open(self):
self.ic.open()

73
hm.py
View File

@ -17,29 +17,29 @@
import sys, os import sys, os
from build import commands from build import commands
# Valid commands. # list of valid commands as keys. the values are optarg strings, but most
cmd_list = [ # are None for now (this is mainly for extensibility)
'about', cmd_dict = {
'setup', 'about' : [None, []],
'configure', 'setup' : [None, []],
'build', 'configure' : [None, []],
'clean', 'build' : ['dr', []],
'update', 'clean' : ['dr', []],
'install', 'update' : [None, []],
'package', 'install' : [None, []],
'dist', 'package' : [None, []],
'open', 'destroy' : [None, []],
'destroy', 'kill' : [None, []],
'kill', 'usage' : [None, []],
'usage', 'revision' : [None, []],
'revision', 'hammer' : [None, []],
'hammer', 'reformat' : [None, []],
'reformat', 'open' : [None, []],
] }
# aliases to valid commands
cmd_alias_dict = { cmd_alias_dict = {
'info' : 'usage', 'info' : 'about',
'about' : 'usage',
'help' : 'usage', 'help' : 'usage',
'dist' : 'package', 'dist' : 'package',
'make' : 'build', 'make' : 'build',
@ -49,7 +49,7 @@ cmd_alias_dict = {
def complete_command(arg): def complete_command(arg):
completions = [] completions = []
for cmd in cmd_list: for cmd, optarg in cmd_dict.iteritems():
if cmd.startswith(arg): if cmd.startswith(arg):
completions.append(cmd) completions.append(cmd)
@ -60,6 +60,7 @@ def complete_command(arg):
return completions return completions
def start_cmd(argv): def start_cmd(argv):
cmd_arg = '' cmd_arg = ''
if len(argv) > 1: if len(argv) > 1:
cmd_arg = argv[1] cmd_arg = argv[1]
@ -70,18 +71,20 @@ def start_cmd(argv):
completions = complete_command(cmd_arg) completions = complete_command(cmd_arg)
if len(completions) > 0: if cmd_arg and len(completions) > 0:
if len(completions) == 1: if len(completions) == 1:
# get the only completion (since in this case we have 1) # get the only completion (since in this case we have 1)
cmd = completions[0] cmd = completions[0]
# build up the first part of the map (for illustrative purposes)
cmd_map = list() cmd_map = list()
if cmd_arg != cmd: if cmd_arg != cmd:
cmd_map.append(cmd_arg) cmd_map.append(cmd_arg)
cmd_map.append(cmd) cmd_map.append(cmd)
# map an alias to the command, and build up the map
if cmd in cmd_alias_dict.keys(): if cmd in cmd_alias_dict.keys():
alias = cmd alias = cmd
if cmd_arg == cmd: if cmd_arg == cmd:
@ -89,20 +92,23 @@ def start_cmd(argv):
cmd = cmd_alias_dict[cmd] cmd = cmd_alias_dict[cmd]
cmd_map.append(cmd) cmd_map.append(cmd)
# show command map to avoid confusion
if len(cmd_map) != 0: if len(cmd_map) != 0:
print 'Mapping command: %s' % ' -> '.join(cmd_map) print 'Mapping command: %s' % ' -> '.join(cmd_map)
# pass args and optarg data to command handler, which figures out
# how to handle the arguments
optarg_data = cmd_dict[cmd]
handler = commands.CommandHandler(argv[2:], optarg_data)
# use reflection to get the function pointer # use reflection to get the function pointer
cmd_func = getattr(commands, cmd) cmd_func = getattr(handler, cmd)
cmd_func()
if cmd_func: return 0
# run the function with all of the remaining args
cmd_func(argv[2:])
else:
print 'Command not yet implemented:', cmd
else: else:
print ('Command `%s` too ambiguous, ' print (
'Command `%s` too ambiguous, '
'could mean any of: %s' 'could mean any of: %s'
) % (cmd_arg, ', '.join(completions)) ) % (cmd_arg, ', '.join(completions))
else: else:
@ -114,6 +120,9 @@ def start_cmd(argv):
commands.usage(argv[2:]) commands.usage(argv[2:])
# generic error code if not returned sooner
return 1
def main(argv): def main(argv):
if sys.version_info < (2, 4): if sys.version_info < (2, 4):
@ -121,7 +130,7 @@ def main(argv):
sys.exit(1) sys.exit(1)
try: try:
start_cmd(argv) sys.exit(start_cmd(argv))
except KeyboardInterrupt: except KeyboardInterrupt:
print '\n\nUser aborted, exiting.' print '\n\nUser aborted, exiting.'