comparison mxtool/mx.py @ 12521:ef0de9485627

Merge
author Mick Jordan <mick.jordan@oracle.com>
date Tue, 22 Oct 2013 08:35:26 -0700
parents 8ee3a8dd762e 8c64f10f86b7
children 5ccee20550ea
comparison
equal deleted inserted replaced
12520:8ee3a8dd762e 12521:ef0de9485627
502 """ 502 """
503 Encapsulates access to Mercurial (hg) 503 Encapsulates access to Mercurial (hg)
504 """ 504 """
505 def __init__(self): 505 def __init__(self):
506 self.missing = 'no hg executable found' 506 self.missing = 'no hg executable found'
507 try: 507 self.has_hg = None
508 subprocess.check_output(['hg']) 508
509 self.has_hg = True 509 def check(self, abortOnFail=True):
510 except OSError: 510 if self.has_hg is None:
511 self.has_hg = False 511 try:
512 warn(self.missing) 512 subprocess.check_output(['hg'])
513 513 self.has_hg = True
514 def _check(self, abortOnFail=True): 514 except OSError:
515 self.has_hg = False
516 warn(self.missing)
517
515 if not self.has_hg: 518 if not self.has_hg:
516 if abortOnFail: 519 if abortOnFail:
517 abort(self.missing) 520 abort(self.missing)
518 else: 521 else:
519 warn(self.missing) 522 warn(self.missing)
520 return self.has_hg 523
521 524 def tip(self, s, abortOnError=True):
522 def _tip(self, s, abortOnError=True):
523 if not self.has_hg:
524 return None
525 try: 525 try:
526 version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}']) 526 version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}'])
527 if s.version is not None and s.version != version: 527 if s.version is not None and s.version != version:
528 abort('version of suite ' + s.name +' has changed during run') 528 abort('version of suite ' + s.name +' has changed during run')
529 return version 529 return version
530 except OSError:
531 warn(self.missing)
530 except subprocess.CalledProcessError: 532 except subprocess.CalledProcessError:
531 if abortOnError: 533 if abortOnError:
532 abort('failed to get tip revision id') 534 abort('failed to get tip revision id')
533 else: 535 else:
534 return None 536 return None
535 537
536 def _canpush(self, s, strict=True): 538 def can_push(self, s, strict=True):
537 try: 539 try:
538 output = subprocess.check_output(['hg', '-R', s.dir, 'status']) 540 output = subprocess.check_output(['hg', '-R', s.dir, 'status'])
539 # super strict 541 # super strict
540 return output == '' 542 return output == ''
543 except OSError:
544 warn(self.missing)
541 except subprocess.CalledProcessError: 545 except subprocess.CalledProcessError:
542 return False 546 return False
543 547
544 def _default_push(self, sdir): 548 def default_push(self, sdir):
545 with open(join(sdir, '.hg', 'hgrc')) as f: 549 with open(join(sdir, '.hg', 'hgrc')) as f:
546 for line in f: 550 for line in f:
547 line = line.rstrip() 551 line = line.rstrip()
548 if line.startswith('default = '): 552 if line.startswith('default = '):
549 return line[len('default = '):] 553 return line[len('default = '):]
761 self.dists = [] 765 self.dists = []
762 self.imports = [] 766 self.imports = []
763 self.commands = None 767 self.commands = None
764 self.primary = primary 768 self.primary = primary
765 self.name = _suitename(mxDir) # validated in _load_projects 769 self.name = _suitename(mxDir) # validated in _load_projects
766 self.version = None # _hg._tip checks current version if not None 770 self.version = None # _hg.tip checks current version if not None
767 self.version = _hg._tip(self, False) 771 # TODO this forces hg to be run every time mx is run
772 #self.version = _hg.tip(self, False)
768 if load: 773 if load:
769 # load suites bottom up to make sure command overriding works properly 774 # load suites bottom up to make sure command overriding works properly
770 self._load_imports() 775 self._load_imports()
771 self._load_env() 776 self._load_env()
772 self._load_commands() 777 self._load_commands()
2977 out.element('name', data=buildCommand) 2982 out.element('name', data=buildCommand)
2978 out.element('arguments', data='') 2983 out.element('arguments', data='')
2979 out.close('buildCommand') 2984 out.close('buildCommand')
2980 2985
2981 if _isAnnotationProcessorDependency(p): 2986 if _isAnnotationProcessorDependency(p):
2982 _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no') 2987 _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no')
2983 _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True) 2988 _genEclipseBuilder(out, p, 'Refresh', '', refresh=True, async=True)
2984 2989
2985 if projToDist.has_key(p.name): 2990 if projToDist.has_key(p.name):
2986 dist, distDeps = projToDist[p.name] 2991 dist, distDeps = projToDist[p.name]
2987 _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist.launch', 'archive @' + dist.name, refresh=False, async=True) 2992 _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist', 'archive @' + dist.name, logToFile=True, refresh=False, async=True)
2988 2993
2989 out.close('buildSpec') 2994 out.close('buildSpec')
2990 out.open('natures') 2995 out.open('natures')
2991 out.element('nature', data='org.eclipse.jdt.core.javanature') 2996 out.element('nature', data='org.eclipse.jdt.core.javanature')
2992 if exists(csConfig): 2997 if exists(csConfig):
3044 """ 3049 """
3045 Determines if a given project is part of an annotation processor. 3050 Determines if a given project is part of an annotation processor.
3046 """ 3051 """
3047 return p in sorted_deps(annotation_processors()) 3052 return p in sorted_deps(annotation_processors())
3048 3053
3049 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, xmlIndent='\t', xmlStandalone=None): 3054 def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False, logToFile=False, appendToLogFile=True, xmlIndent='\t', xmlStandalone=None):
3055 externalToolDir = join(p.dir, '.externalToolBuilders')
3050 launchOut = XMLDoc() 3056 launchOut = XMLDoc()
3051 consoleOn = 'true' if logToConsole else 'false' 3057 consoleOn = 'true' if logToConsole else 'false'
3052 launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'}) 3058 launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'})
3053 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn}) 3059 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn})
3054 launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'}) 3060 launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'})
3057 3063
3058 if refresh: 3064 if refresh:
3059 launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'}) 3065 launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'})
3060 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn}) 3066 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn})
3061 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'}) 3067 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'})
3068 if logToFile:
3069 logFile = join(externalToolDir, name + '.log')
3070 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE', 'value': logFile})
3071 launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_APPEND_TO_FILE', 'value': 'true' if appendToLogFile else 'false'})
3062 3072
3063 # expect to find the OS command to invoke mx in the same directory 3073 # expect to find the OS command to invoke mx in the same directory
3064 baseDir = dirname(os.path.abspath(__file__)) 3074 baseDir = dirname(os.path.abspath(__file__))
3065 3075
3066 cmd = 'mx.sh' 3076 cmd = 'mx.sh'
3080 launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': p.suite.dir}) 3090 launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': p.suite.dir})
3081 3091
3082 3092
3083 launchOut.close('launchConfiguration') 3093 launchOut.close('launchConfiguration')
3084 3094
3085 externalToolDir = join(p.dir, '.externalToolBuilders')
3086
3087 if not exists(externalToolDir): 3095 if not exists(externalToolDir):
3088 os.makedirs(externalToolDir) 3096 os.makedirs(externalToolDir)
3089 update_file(join(externalToolDir, name), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n')) 3097 update_file(join(externalToolDir, name + '.launch'), launchOut.xml(indent=xmlIndent, standalone=xmlStandalone, newl='\n'))
3090 3098
3091 dotProjectDoc.open('buildCommand') 3099 dotProjectDoc.open('buildCommand')
3092 dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder') 3100 dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder')
3093 dotProjectDoc.element('triggers', data='auto,full,incremental,') 3101 dotProjectDoc.element('triggers', data='auto,full,incremental,')
3094 dotProjectDoc.open('arguments') 3102 dotProjectDoc.open('arguments')
3095 dotProjectDoc.open('dictionary') 3103 dotProjectDoc.open('dictionary')
3096 dotProjectDoc.element('key', data='LaunchConfigHandle') 3104 dotProjectDoc.element('key', data='LaunchConfigHandle')
3097 dotProjectDoc.element('value', data='<project>/.externalToolBuilders/' + name) 3105 dotProjectDoc.element('value', data='<project>/.externalToolBuilders/' + name + '.launch')
3098 dotProjectDoc.close('dictionary') 3106 dotProjectDoc.close('dictionary')
3099 dotProjectDoc.open('dictionary') 3107 dotProjectDoc.open('dictionary')
3100 dotProjectDoc.element('key', data='incclean') 3108 dotProjectDoc.element('key', data='incclean')
3101 dotProjectDoc.element('value', data='true') 3109 dotProjectDoc.element('value', data='true')
3102 dotProjectDoc.close('dictionary') 3110 dotProjectDoc.close('dictionary')
3941 return kwargs.pop(0) 3949 return kwargs.pop(0)
3942 return None 3950 return None
3943 3951
3944 def sclone(args): 3952 def sclone(args):
3945 """clone a suite repository, and its imported suites""" 3953 """clone a suite repository, and its imported suites"""
3946 _hg._check(True) 3954 _hg.check(True)
3947 parser = ArgumentParser(prog='mx sclone') 3955 parser = ArgumentParser(prog='mx sclone')
3948 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') 3956 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>')
3949 parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='<path>') 3957 parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='<path>')
3950 parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites') 3958 parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites')
3951 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') 3959 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
4030 _sclone(importee_source, importee_dest, suite_import.version, False) 4038 _sclone(importee_source, importee_dest, suite_import.version, False)
4031 # _clone handles the recursive visit of the new imports 4039 # _clone handles the recursive visit of the new imports
4032 4040
4033 def scloneimports(args): 4041 def scloneimports(args):
4034 """clone the imports of an existing suite""" 4042 """clone the imports of an existing suite"""
4035 _hg._check(True) 4043 _hg.check(True)
4036 parser = ArgumentParser(prog='mx scloneimports') 4044 parser = ArgumentParser(prog='mx scloneimports')
4037 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') 4045 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>')
4038 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') 4046 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
4039 args = parser.parse_args(args) 4047 args = parser.parse_args(args)
4040 # check for non keyword args 4048 # check for non keyword args
4044 if not os.path.isdir(args.source): 4052 if not os.path.isdir(args.source):
4045 abort(args.source + ' is not a directory') 4053 abort(args.source + ' is not a directory')
4046 4054
4047 s = _scloneimports_suitehelper(args.source) 4055 s = _scloneimports_suitehelper(args.source)
4048 4056
4049 default_path = _hg._default_push(args.source) 4057 default_path = _hg.default_push(args.source)
4050 4058
4051 if default_path is None: 4059 if default_path is None:
4052 abort('no default path in ' + join(args.source, '.hg', 'hgrc')) 4060 abort('no default path in ' + join(args.source, '.hg', 'hgrc'))
4053 4061
4054 # We can now set the primary dir for the dst suitemodel 4062 # We can now set the primary dir for the dst suitemodel
4063 dest = _dst_suitemodel._importee_dir(dest, suite_import.name) 4071 dest = _dst_suitemodel._importee_dir(dest, suite_import.name)
4064 _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing) 4072 _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing)
4065 4073
4066 def _spush_check_import_visitor(s, suite_import, **extra_args): 4074 def _spush_check_import_visitor(s, suite_import, **extra_args):
4067 """push check visitor for Suite._visit_imports""" 4075 """push check visitor for Suite._visit_imports"""
4068 currentTip = _hg._tip(suite(suite_import.name)) 4076 currentTip = _hg.tip(suite(suite_import.name))
4069 if currentTip != suite_import.version: 4077 if currentTip != suite_import.version:
4070 abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') 4078 abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip')
4071 4079
4072 def _spush(s, suite_import, dest, checks, clonemissing): 4080 def _spush(s, suite_import, dest, checks, clonemissing):
4073 if checks: 4081 if checks:
4074 if not _hg._canpush(s): 4082 if not _hg.can_push(s):
4075 abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted') 4083 abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted')
4076 4084
4077 # check imports first 4085 # check imports first
4078 if checks: 4086 if checks:
4079 s._visit_imports(_spush_check_import_visitor) 4087 s._visit_imports(_spush_check_import_visitor)
4109 cmd.append(dest) 4117 cmd.append(dest)
4110 run(cmd) 4118 run(cmd)
4111 4119
4112 def spush(args): 4120 def spush(args):
4113 """push primary suite and all its imports""" 4121 """push primary suite and all its imports"""
4114 _hg._check(True) 4122 _hg.check(True)
4115 parser = ArgumentParser(prog='mx spush') 4123 parser = ArgumentParser(prog='mx spush')
4116 parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='<path>') 4124 parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='<path>')
4117 parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled') 4125 parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled')
4118 parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)') 4126 parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)')
4119 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') 4127 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...')
4147 run(['hg', '-R', s.dir, 'update']) 4155 run(['hg', '-R', s.dir, 'update'])
4148 4156
4149 def supdate(args): 4157 def supdate(args):
4150 """update primary suite and all its imports""" 4158 """update primary suite and all its imports"""
4151 4159
4152 _hg._check(True) 4160 _hg.check(True)
4153 s = _check_primary_suite() 4161 s = _check_primary_suite()
4154 4162
4155 _supdate(s, None) 4163 _supdate(s, None)
4156 4164
4157 def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports): 4165 def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports):
4160 4168
4161 def _scheck_imports(s, suite_import, update_versions, updated_imports): 4169 def _scheck_imports(s, suite_import, update_versions, updated_imports):
4162 # check imports recursively 4170 # check imports recursively
4163 s._visit_imports(_scheck_imports_visitor, update_versions=update_versions) 4171 s._visit_imports(_scheck_imports_visitor, update_versions=update_versions)
4164 4172
4165 currentTip = _hg._tip(s) 4173 currentTip = _hg.tip(s)
4166 if currentTip != suite_import.version: 4174 if currentTip != suite_import.version:
4167 print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else '')) 4175 print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else ''))
4168 4176
4169 if update_versions: 4177 if update_versions:
4170 suite_import.version = currentTip 4178 suite_import.version = currentTip
4181 def _spull_import_visitor(s, suite_import, update_versions, updated_imports): 4189 def _spull_import_visitor(s, suite_import, update_versions, updated_imports):
4182 """pull visitor for Suite._visit_imports""" 4190 """pull visitor for Suite._visit_imports"""
4183 _spull(suite(suite_import.name), update_versions, updated_imports) 4191 _spull(suite(suite_import.name), update_versions, updated_imports)
4184 4192
4185 def _spull(s, update_versions, updated_imports): 4193 def _spull(s, update_versions, updated_imports):
4186 _hg._check(True) 4194 _hg.check(True)
4187 # pull imports first 4195 # pull imports first
4188 s._visit_imports(_spull_import_visitor, update_versions=update_versions) 4196 s._visit_imports(_spull_import_visitor, update_versions=update_versions)
4189 4197
4190 run(['hg', '-R', s.dir, 'pull', '-u']) 4198 run(['hg', '-R', s.dir, 'pull', '-u'])
4191 if update_versions and updated_imports is not None: 4199 if update_versions and updated_imports is not None:
4192 tip = _hg._tip(s) 4200 tip = _hg.tip(s)
4193 updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n') 4201 updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n')
4194 4202
4195 def spull(args): 4203 def spull(args):
4196 """pull primary suite and all its imports""" 4204 """pull primary suite and all its imports"""
4197 _hg._check(True) 4205 _hg.check(True)
4198 parser = ArgumentParser(prog='mx spull') 4206 parser = ArgumentParser(prog='mx spull')
4199 parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites') 4207 parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites')
4200 args = parser.parse_args(args) 4208 args = parser.parse_args(args)
4201 4209
4202 _spull(_check_primary_suite(), args.update_versions, None) 4210 _spull(_check_primary_suite(), args.update_versions, None)