Mercurial > hg > graal-jvmci-8
comparison mxtool/mx.py @ 12508:5cde653f58f9
mxtool: handle missing hg executable gracefully
author | Mick Jordan <mick.jordan@oracle.com> |
---|---|
date | Mon, 21 Oct 2013 15:14:43 -0700 |
parents | 1d68b3962a10 |
children | 21aa1ce5c666 8ee3a8dd762e |
comparison
equal
deleted
inserted
replaced
12507:d72864a2886e | 12508:5cde653f58f9 |
---|---|
161 _dst_suitemodel = None | 161 _dst_suitemodel = None |
162 _opts = None | 162 _opts = None |
163 _java = None | 163 _java = None |
164 _check_global_structures = True # can be set False to allow suites with duplicate definitions to load without aborting | 164 _check_global_structures = True # can be set False to allow suites with duplicate definitions to load without aborting |
165 _warn = False | 165 _warn = False |
166 _hg = None | |
166 | 167 |
167 | 168 |
168 """ | 169 """ |
169 A distribution is a jar or zip file containing the output from one or more Java projects. | 170 A distribution is a jar or zip file containing the output from one or more Java projects. |
170 """ | 171 """ |
495 if not includeLibs or not includeSelf: | 496 if not includeLibs or not includeSelf: |
496 return deps | 497 return deps |
497 deps.append(self) | 498 deps.append(self) |
498 return deps | 499 return deps |
499 | 500 |
501 class HgConfig: | |
502 """ | |
503 Encapsulates access to Mercurial (hg) | |
504 """ | |
505 def __init__(self): | |
506 self.missing = 'no hg executable found' | |
507 try: | |
508 subprocess.check_output(['hg']) | |
509 self.has_hg = True | |
510 except OSError: | |
511 self.has_hg = False | |
512 warn(self.missing) | |
513 | |
514 def _check(self, abortOnFail=True): | |
515 if not self.has_hg: | |
516 if abortOnFail: | |
517 abort(self.missing) | |
518 else: | |
519 warn(self.missing) | |
520 return self.has_hg | |
521 | |
522 def _tip(self, s, abortOnError=True): | |
523 if not self.has_hg: | |
524 return None | |
525 try: | |
526 version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}']) | |
527 if s.version is not None and s.version != version: | |
528 abort('version of suite ' + s.name +' has changed during run') | |
529 return version | |
530 except subprocess.CalledProcessError: | |
531 if abortOnError: | |
532 abort('failed to get tip revision id') | |
533 else: | |
534 return None | |
535 | |
536 def _canpush(self, s, strict=True): | |
537 try: | |
538 output = subprocess.check_output(['hg', '-R', s.dir, 'status']) | |
539 # super strict | |
540 return output == '' | |
541 except subprocess.CalledProcessError: | |
542 return False | |
543 | |
544 def _default_push(self, sdir): | |
545 with open(join(sdir, '.hg', 'hgrc')) as f: | |
546 for line in f: | |
547 line = line.rstrip() | |
548 if line.startswith('default = '): | |
549 return line[len('default = '):] | |
550 return None | |
551 | |
500 class SuiteModel: | 552 class SuiteModel: |
501 """ | 553 """ |
502 Defines how to locate a URL/path for a suite, including imported suites. | 554 Defines how to locate a URL/path for a suite, including imported suites. |
503 Conceptually a SuiteModel is defined by a primary suite URL/path and a | 555 Conceptually a SuiteModel is defined by a primary suite URL/path and a |
504 map from suite name to URL/path for imported suites. | 556 map from suite name to URL/path for imported suites. |
588 src_suitemodel_arg = _get_argvalue(arg, args, i + 1) | 640 src_suitemodel_arg = _get_argvalue(arg, args, i + 1) |
589 elif arg == '--dst-suitemodel': | 641 elif arg == '--dst-suitemodel': |
590 dst_suitemodel_arg = _get_argvalue(arg, args, i + 1) | 642 dst_suitemodel_arg = _get_argvalue(arg, args, i + 1) |
591 elif arg == '--suitemap': | 643 elif arg == '--suitemap': |
592 suitemap_arg = _get_argvalue(arg, args, i + 1) | 644 suitemap_arg = _get_argvalue(arg, args, i + 1) |
645 elif arg == '-w': | |
646 # to get warnings on suite loading issues before command line is parsed | |
647 global _warn | |
648 _warn = True | |
649 | |
593 i = i + 1 | 650 i = i + 1 |
594 | 651 |
595 global _src_suitemodel | 652 global _src_suitemodel |
596 _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg) | 653 _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg) |
597 global _dst_suitemodel | 654 global _dst_suitemodel |
690 | 747 |
691 @staticmethod | 748 @staticmethod |
692 def _tostring(name, version): | 749 def _tostring(name, version): |
693 return name + ',' + version | 750 return name + ',' + version |
694 | 751 |
695 def _self_tostring(self): | 752 def __str__(self): |
696 return self.name + ',' + self.version | 753 return self.name + ',' + self.version |
697 | 754 |
698 class Suite: | 755 class Suite: |
699 def __init__(self, mxDir, primary, load=True): | 756 def __init__(self, mxDir, primary, load=True): |
700 self.dir = dirname(mxDir) | 757 self.dir = dirname(mxDir) |
704 self.dists = [] | 761 self.dists = [] |
705 self.imports = [] | 762 self.imports = [] |
706 self.commands = None | 763 self.commands = None |
707 self.primary = primary | 764 self.primary = primary |
708 self.name = _suitename(mxDir) # validated in _load_projects | 765 self.name = _suitename(mxDir) # validated in _load_projects |
709 self.version = None # _hgtip checks current version if not None | 766 self.version = None # _hg._tip checks current version if not None |
710 self.version = _hgtip(self, False) | 767 self.version = _hg._tip(self, False) |
711 if load: | 768 if load: |
712 # load suites bottom up to make sure command overriding works properly | 769 # load suites bottom up to make sure command overriding works properly |
713 self._load_imports() | 770 self._load_imports() |
714 self._load_env() | 771 self._load_env() |
715 self._load_commands() | 772 self._load_commands() |
888 if importMxDir is None: | 945 if importMxDir is None: |
889 abort('import ' + suite_import.name + ' not found') | 946 abort('import ' + suite_import.name + ' not found') |
890 suite.imports.append(suite_import) | 947 suite.imports.append(suite_import) |
891 imported_suite = _loadSuite(importMxDir, False) | 948 imported_suite = _loadSuite(importMxDir, False) |
892 if imported_suite.version != suite.version: | 949 if imported_suite.version != suite.version: |
893 warn('import version of ' + imported_suite.name + ' does not match tip of ' + suite.version) | 950 warn('import version of ' + imported_suite.name +' does not match tip of ' + suite.version) |
894 | 951 |
895 def _load_imports(self): | 952 def _load_imports(self): |
896 self._visit_imports(self._find_and_loadsuite) | 953 self._visit_imports(self._find_and_loadsuite) |
897 | 954 |
898 def _load_env(self): | 955 def _load_env(self): |
3884 return kwargs.pop(0) | 3941 return kwargs.pop(0) |
3885 return None | 3942 return None |
3886 | 3943 |
3887 def sclone(args): | 3944 def sclone(args): |
3888 """clone a suite repository, and its imported suites""" | 3945 """clone a suite repository, and its imported suites""" |
3946 _hg._check(True) | |
3889 parser = ArgumentParser(prog='mx sclone') | 3947 parser = ArgumentParser(prog='mx sclone') |
3890 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') | 3948 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') |
3891 parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='<path>') | 3949 parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='<path>') |
3892 parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites') | 3950 parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites') |
3893 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') | 3951 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') |
3969 _sclone(importee_source, importee_dest, suite_import.version, False) | 4027 _sclone(importee_source, importee_dest, suite_import.version, False) |
3970 # _clone handles the recursive visit of the new imports | 4028 # _clone handles the recursive visit of the new imports |
3971 | 4029 |
3972 def scloneimports(args): | 4030 def scloneimports(args): |
3973 """clone the imports of an existing suite""" | 4031 """clone the imports of an existing suite""" |
4032 _hg._check(True) | |
3974 parser = ArgumentParser(prog='mx scloneimports') | 4033 parser = ArgumentParser(prog='mx scloneimports') |
3975 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') | 4034 parser.add_argument('--source', help='url/path of repo containing suite', metavar='<url>') |
3976 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') | 4035 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') |
3977 args = parser.parse_args(args) | 4036 args = parser.parse_args(args) |
3978 # check for non keyword args | 4037 # check for non keyword args |
3982 if not os.path.isdir(args.source): | 4041 if not os.path.isdir(args.source): |
3983 abort(args.source + ' is not a directory') | 4042 abort(args.source + ' is not a directory') |
3984 | 4043 |
3985 s = _scloneimports_suitehelper(args.source) | 4044 s = _scloneimports_suitehelper(args.source) |
3986 | 4045 |
3987 default_path = _hgdefault_push(args.source) | 4046 default_path = _hg._default_push(args.source) |
3988 | 4047 |
3989 if default_path is None: | 4048 if default_path is None: |
3990 abort('no default path in ' + join(args.source, '.hg', 'hgrc')) | 4049 abort('no default path in ' + join(args.source, '.hg', 'hgrc')) |
3991 | 4050 |
3992 # We can now set the primary dir for the dst suitemodel | 4051 # We can now set the primary dir for the dst suitemodel |
4001 dest = _dst_suitemodel._importee_dir(dest, suite_import.name) | 4060 dest = _dst_suitemodel._importee_dir(dest, suite_import.name) |
4002 _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing) | 4061 _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing) |
4003 | 4062 |
4004 def _spush_check_import_visitor(s, suite_import, **extra_args): | 4063 def _spush_check_import_visitor(s, suite_import, **extra_args): |
4005 """push check visitor for Suite._visit_imports""" | 4064 """push check visitor for Suite._visit_imports""" |
4006 currentTip = _hgtip(suite(suite_import.name)) | 4065 currentTip = _hg._tip(suite(suite_import.name)) |
4007 if currentTip != suite_import.version: | 4066 if currentTip != suite_import.version: |
4008 abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') | 4067 abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') |
4009 | 4068 |
4010 def _spush(s, suite_import, dest, checks, clonemissing): | 4069 def _spush(s, suite_import, dest, checks, clonemissing): |
4011 if checks: | 4070 if checks: |
4012 if not _hgcanpush(s): | 4071 if not _hg._canpush(s): |
4013 abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted') | 4072 abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted') |
4014 | 4073 |
4015 # check imports first | 4074 # check imports first |
4016 if checks: | 4075 if checks: |
4017 s._visit_imports(_spush_check_import_visitor) | 4076 s._visit_imports(_spush_check_import_visitor) |
4047 cmd.append(dest) | 4106 cmd.append(dest) |
4048 run(cmd) | 4107 run(cmd) |
4049 | 4108 |
4050 def spush(args): | 4109 def spush(args): |
4051 """push primary suite and all its imports""" | 4110 """push primary suite and all its imports""" |
4111 _hg._check(True) | |
4052 parser = ArgumentParser(prog='mx spush') | 4112 parser = ArgumentParser(prog='mx spush') |
4053 parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='<path>') | 4113 parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='<path>') |
4054 parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled') | 4114 parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled') |
4055 parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)') | 4115 parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)') |
4056 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') | 4116 parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') |
4071 args.nochecks = True | 4131 args.nochecks = True |
4072 | 4132 |
4073 if args.dest is not None: | 4133 if args.dest is not None: |
4074 _dst_suitemodel._set_primary_dir(args.dest) | 4134 _dst_suitemodel._set_primary_dir(args.dest) |
4075 | 4135 |
4076 _spush(s, None, args.dest, not args.nochecks, args.clonemissing) | 4136 _spush(s, None, args.dest, not args.no_checks, args.clonemissing) |
4077 | 4137 |
4078 def _supdate_import_visitor(s, suite_import, **extra_args): | 4138 def _supdate_import_visitor(s, suite_import, **extra_args): |
4079 _supdate(suite(suite_import.name), suite_import) | 4139 _supdate(suite(suite_import.name), suite_import) |
4080 | 4140 |
4081 def _supdate(s, suite_import): | 4141 def _supdate(s, suite_import): |
4084 run(['hg', '-R', s.dir, 'update']) | 4144 run(['hg', '-R', s.dir, 'update']) |
4085 | 4145 |
4086 def supdate(args): | 4146 def supdate(args): |
4087 """update primary suite and all its imports""" | 4147 """update primary suite and all its imports""" |
4088 | 4148 |
4149 _hg._check(True) | |
4089 s = _check_primary_suite() | 4150 s = _check_primary_suite() |
4090 | 4151 |
4091 _supdate(s, None) | 4152 _supdate(s, None) |
4092 | 4153 |
4093 def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports): | 4154 def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports): |
4096 | 4157 |
4097 def _scheck_imports(s, suite_import, update_versions, updated_imports): | 4158 def _scheck_imports(s, suite_import, update_versions, updated_imports): |
4098 # check imports recursively | 4159 # check imports recursively |
4099 s._visit_imports(_scheck_imports_visitor, update_versions=update_versions) | 4160 s._visit_imports(_scheck_imports_visitor, update_versions=update_versions) |
4100 | 4161 |
4101 currentTip = _hgtip(s) | 4162 currentTip = _hg._tip(s) |
4102 if currentTip != suite_import.version: | 4163 if currentTip != suite_import.version: |
4103 print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else '')) | 4164 print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else '')) |
4104 | 4165 |
4105 if update_versions: | 4166 if update_versions: |
4106 suite_import.version = currentTip | 4167 suite_import.version = currentTip |
4107 line = suite_import._self_tostring() | 4168 line = str(suite_import) |
4108 updated_imports.write(line + '\n') | 4169 updated_imports.write(line + '\n') |
4109 | 4170 |
4110 def scheckimports(args): | 4171 def scheckimports(args): |
4111 """check that suite import versions are up to date""" | 4172 """check that suite import versions are up to date""" |
4112 parser = ArgumentParser(prog='mx scheckimports') | 4173 parser = ArgumentParser(prog='mx scheckimports') |
4113 parser.add_argument('--update-versions', help='update imported version ids', action='store_true') | 4174 parser.add_argument('--update-versions', help='update imported version ids', action='store_true') |
4114 args = parser.parse_args(args) | 4175 args = parser.parse_args(args) |
4115 _check_primary_suite()._visit_imports(_scheck_imports_visitor, update_versions=args.update_versions) | 4176 _check_primary_suite()._visit_imports(_scheck_imports_visitor, update_versions=args.update_versions) |
4116 | 4177 |
4117 def _hgtip(s, abortOnError=True): | |
4118 try: | |
4119 version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}']) | |
4120 if s.version is not None and s.version != version: | |
4121 abort('version of suite ' + s.name + ' has changed during run') | |
4122 return version | |
4123 except subprocess.CalledProcessError: | |
4124 if abortOnError: | |
4125 abort('failed to get tip revision id') | |
4126 else: | |
4127 return None | |
4128 | |
4129 def _hgcanpush(s): | |
4130 try: | |
4131 output = subprocess.check_output(['hg', '-R', s.dir, 'status']) | |
4132 # super strict | |
4133 return output == '' | |
4134 except subprocess.CalledProcessError: | |
4135 return False | |
4136 | |
4137 def _hgdefault_push(sdir): | |
4138 with open(join(sdir, '.hg', 'hgrc')) as f: | |
4139 for line in f: | |
4140 line = line.rstrip() | |
4141 if line.startswith('default = '): | |
4142 return line[len('default = '):] | |
4143 return None | |
4144 | |
4145 def _spull_import_visitor(s, suite_import, update_versions, updated_imports): | 4178 def _spull_import_visitor(s, suite_import, update_versions, updated_imports): |
4146 """pull visitor for Suite._visit_imports""" | 4179 """pull visitor for Suite._visit_imports""" |
4147 _spull(suite(suite_import.name), update_versions, updated_imports) | 4180 _spull(suite(suite_import.name), update_versions, updated_imports) |
4148 | 4181 |
4149 def _spull(s, update_versions, updated_imports): | 4182 def _spull(s, update_versions, updated_imports): |
4183 _hg._check(True) | |
4150 # pull imports first | 4184 # pull imports first |
4151 s._visit_imports(_spull_import_visitor, update_versions=update_versions) | 4185 s._visit_imports(_spull_import_visitor, update_versions=update_versions) |
4152 | 4186 |
4153 run(['hg', '-R', s.dir, 'pull', '-u']) | 4187 run(['hg', '-R', s.dir, 'pull', '-u']) |
4154 if update_versions and updated_imports is not None: | 4188 if update_versions and updated_imports is not None: |
4155 tip = _hgtip(s) | 4189 tip = _hg._tip(s) |
4156 updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n') | 4190 updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n') |
4157 | 4191 |
4158 def spull(args): | 4192 def spull(args): |
4159 """pull primary suite and all its imports""" | 4193 """pull primary suite and all its imports""" |
4194 _hg._check(True) | |
4160 parser = ArgumentParser(prog='mx spull') | 4195 parser = ArgumentParser(prog='mx spull') |
4161 parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites') | 4196 parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites') |
4162 args = parser.parse_args(args) | 4197 args = parser.parse_args(args) |
4163 | 4198 |
4164 _spull(_check_primary_suite(), args.update_versions, None) | 4199 _spull(_check_primary_suite(), args.update_versions, None) |
4360 return None | 4395 return None |
4361 | 4396 |
4362 def main(): | 4397 def main(): |
4363 SuiteModel._parse_options() | 4398 SuiteModel._parse_options() |
4364 | 4399 |
4400 global _hg | |
4401 _hg = HgConfig() | |
4402 | |
4365 primarySuiteMxDir = _findPrimarySuiteMxDir() | 4403 primarySuiteMxDir = _findPrimarySuiteMxDir() |
4366 if primarySuiteMxDir: | 4404 if primarySuiteMxDir: |
4367 _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir)) | 4405 _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir)) |
4368 global _mainSuite | 4406 global _mainSuite |
4369 _mainSuite = _loadSuite(primarySuiteMxDir, True) | 4407 _mainSuite = _loadSuite(primarySuiteMxDir, True) |