Mercurial > hg > truffle
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) |