| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """ A collator for Service Manifests """ | |
| 7 | |
| 8 import argparse | |
| 9 import json | |
| 10 import os | |
| 11 import shutil | |
| 12 import sys | |
| 13 import urlparse | |
| 14 | |
| 15 | |
| 16 # Keys which are completely overridden by manifest overlays | |
| 17 _MANIFEST_OVERLAY_OVERRIDE_KEYS = [ | |
| 18 "display_name", | |
| 19 "process-group", | |
| 20 ] | |
| 21 | |
| 22 eater_relative = '../../../../../../tools/json_comment_eater' | |
| 23 eater_relative = os.path.join(os.path.abspath(__file__), eater_relative) | |
| 24 sys.path.insert(0, os.path.normpath(eater_relative)) | |
| 25 try: | |
| 26 import json_comment_eater | |
| 27 finally: | |
| 28 sys.path.pop(0) | |
| 29 | |
| 30 | |
| 31 def ParseJSONFile(filename): | |
| 32 with open(filename) as json_file: | |
| 33 try: | |
| 34 return json.loads(json_comment_eater.Nom(json_file.read())) | |
| 35 except ValueError as e: | |
| 36 print "%s is not a valid JSON document" % filename | |
| 37 raise e | |
| 38 | |
| 39 | |
| 40 def MergeDicts(left, right): | |
| 41 for k, v in right.iteritems(): | |
| 42 if k not in left: | |
| 43 left[k] = v | |
| 44 else: | |
| 45 if isinstance(v, dict): | |
| 46 assert isinstance(left[k], dict) | |
| 47 MergeDicts(left[k], v) | |
| 48 elif isinstance(v, list): | |
| 49 assert isinstance(left[k], list) | |
| 50 left[k].extend(v) | |
| 51 else: | |
| 52 raise "Refusing to merge conflicting non-collection values." | |
| 53 return left | |
| 54 | |
| 55 | |
| 56 def MergeManifestOverlay(manifest, overlay): | |
| 57 MergeDicts(manifest["capabilities"], overlay["capabilities"]) | |
| 58 | |
| 59 if "services" in overlay: | |
| 60 if "services" not in manifest: | |
| 61 manifest["services"] = [] | |
| 62 manifest["services"].extend(overlay["services"]) | |
| 63 | |
| 64 for key in _MANIFEST_OVERLAY_OVERRIDE_KEYS: | |
| 65 if key in overlay: | |
| 66 manifest[key] = overlay[key] | |
| 67 | |
| 68 | |
| 69 def main(): | |
| 70 parser = argparse.ArgumentParser( | |
| 71 description="Collate Service Manifests.") | |
| 72 parser.add_argument("--parent") | |
| 73 parser.add_argument("--output") | |
| 74 parser.add_argument("--name") | |
| 75 parser.add_argument("--overlays", nargs="+", dest="overlays", default=[]) | |
| 76 args, children = parser.parse_known_args() | |
| 77 | |
| 78 parent = ParseJSONFile(args.parent) | |
| 79 | |
| 80 service_path = parent['name'].split(':')[1] | |
| 81 if service_path.startswith('//'): | |
| 82 raise ValueError("Service name path component '%s' must not start " \ | |
| 83 "with //" % service_path) | |
| 84 | |
| 85 if args.name != service_path: | |
| 86 raise ValueError("Service name '%s' specified in build file does not " \ | |
| 87 "match name '%s' specified in manifest." % | |
| 88 (args.name, service_path)) | |
| 89 | |
| 90 services = [] | |
| 91 for child in children: | |
| 92 services.append(ParseJSONFile(child)) | |
| 93 | |
| 94 if len(services) > 0: | |
| 95 parent['services'] = services | |
| 96 | |
| 97 for overlay_path in args.overlays: | |
| 98 MergeManifestOverlay(parent, ParseJSONFile(overlay_path)) | |
| 99 | |
| 100 with open(args.output, 'w') as output_file: | |
| 101 json.dump(parent, output_file) | |
| 102 | |
| 103 return 0 | |
| 104 | |
| 105 if __name__ == "__main__": | |
| 106 sys.exit(main()) | |
| OLD | NEW |