OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """ A collator for Service Manifests """ | 6 """ A collator for Service Manifests """ |
7 | 7 |
8 import argparse | 8 import argparse |
9 import json | 9 import json |
10 import os | 10 import os |
11 import shutil | 11 import shutil |
12 import sys | 12 import sys |
13 import urlparse | 13 import urlparse |
14 | 14 |
15 | 15 |
16 # Keys which are completely overridden by manifest overlays | 16 # Keys which are completely overridden by manifest overlays |
17 _MANIFEST_OVERLAY_OVERRIDE_KEYS = [ | 17 _MANIFEST_OVERLAY_OVERRIDE_KEYS = [ |
18 "display_name", | 18 "display_name", |
19 ] | 19 ] |
20 | 20 |
21 eater_relative = "../../../../../../tools/json_comment_eater" | 21 eater_relative = '../../../../../../tools/json_comment_eater' |
22 eater_relative = os.path.join(os.path.abspath(__file__), eater_relative) | 22 eater_relative = os.path.join(os.path.abspath(__file__), eater_relative) |
23 sys.path.insert(0, os.path.normpath(eater_relative)) | 23 sys.path.insert(0, os.path.normpath(eater_relative)) |
24 try: | 24 try: |
25 import json_comment_eater | 25 import json_comment_eater |
26 finally: | 26 finally: |
27 sys.path.pop(0) | 27 sys.path.pop(0) |
28 | 28 |
29 | 29 |
30 def ParseJSONFile(filename): | 30 def ParseJSONFile(filename): |
31 with open(filename) as json_file: | 31 with open(filename) as json_file: |
(...skipping 27 matching lines...) Expand all Loading... |
59 if "services" in overlay: | 59 if "services" in overlay: |
60 if "services" not in manifest: | 60 if "services" not in manifest: |
61 manifest["services"] = [] | 61 manifest["services"] = [] |
62 manifest["services"].extend(overlay["services"]) | 62 manifest["services"].extend(overlay["services"]) |
63 | 63 |
64 for key in _MANIFEST_OVERLAY_OVERRIDE_KEYS: | 64 for key in _MANIFEST_OVERLAY_OVERRIDE_KEYS: |
65 if key in overlay: | 65 if key in overlay: |
66 manifest[key] = overlay[key] | 66 manifest[key] = overlay[key] |
67 | 67 |
68 | 68 |
69 def SanityCheckManifestServices(manifest): | |
70 """Ensures any given service name appears only once within a manifest.""" | |
71 known_services = set() | |
72 def has_no_dupes(root): | |
73 if "name" in root: | |
74 name = root["name"] | |
75 if name in known_services: | |
76 raise ValueError( | |
77 "Duplicate manifest entry found for service: %s" % name) | |
78 known_services.add(name) | |
79 if "services" not in root: | |
80 return True | |
81 return all(has_no_dupes(service) for service in root["services"]) | |
82 return has_no_dupes(manifest) | |
83 | |
84 | |
85 def main(): | 69 def main(): |
86 parser = argparse.ArgumentParser( | 70 parser = argparse.ArgumentParser( |
87 description="Collate Service Manifests.") | 71 description="Collate Service Manifests.") |
88 parser.add_argument("--parent") | 72 parser.add_argument("--parent") |
89 parser.add_argument("--output") | 73 parser.add_argument("--output") |
90 parser.add_argument("--name") | 74 parser.add_argument("--name") |
91 parser.add_argument("--pretty", action="store_true") | 75 parser.add_argument("--pretty", action="store_true") |
92 parser.add_argument("--overlays", nargs="+", dest="overlays", default=[]) | 76 parser.add_argument("--overlays", nargs="+", dest="overlays", default=[]) |
93 parser.add_argument("--packaged-services", nargs="+", | 77 parser.add_argument("--packaged-services", nargs="+", |
94 dest="packaged_services", default=[]) | 78 dest="packaged_services", default=[]) |
95 args, _ = parser.parse_known_args() | 79 args, _ = parser.parse_known_args() |
96 | 80 |
97 parent = ParseJSONFile(args.parent) | 81 parent = ParseJSONFile(args.parent) |
98 | 82 |
99 service_name = parent["name"] if "name" in parent else "" | 83 service_path = parent['name'] |
100 if args.name and args.name != service_name: | 84 if args.name and args.name != service_path: |
101 raise ValueError("Service name '%s' specified in build file does not " \ | 85 raise ValueError("Service name '%s' specified in build file does not " \ |
102 "match name '%s' specified in manifest." % | 86 "match name '%s' specified in manifest." % |
103 (args.name, service_name)) | 87 (args.name, service_path)) |
104 | 88 |
105 packaged_services = [] | 89 packaged_services = [] |
106 for child_manifest in args.packaged_services: | 90 for child_manifest in args.packaged_services: |
107 packaged_services.append(ParseJSONFile(child_manifest)) | 91 packaged_services.append(ParseJSONFile(child_manifest)) |
108 | 92 |
109 if len(packaged_services) > 0: | 93 if len(packaged_services) > 0: |
110 if "services" not in parent: | 94 if 'services' not in parent: |
111 parent["services"] = packaged_services | 95 parent['services'] = packaged_services |
112 else: | 96 else: |
113 parent["services"].extend(packaged_services) | 97 parent['services'].extend(packaged_services) |
114 | 98 |
115 for overlay_path in args.overlays: | 99 for overlay_path in args.overlays: |
116 MergeManifestOverlay(parent, ParseJSONFile(overlay_path)) | 100 MergeManifestOverlay(parent, ParseJSONFile(overlay_path)) |
117 | 101 |
118 with open(args.output, "w") as output_file: | 102 with open(args.output, 'w') as output_file: |
119 json.dump(parent, output_file, indent=2 if args.pretty else -1) | 103 json.dump(parent, output_file, indent=2 if args.pretty else -1) |
120 | 104 |
121 # NOTE: We do the sanity check and possible failure *after* outputting the | |
122 # aggregate manifest so it's easier to inspect erroneous output. | |
123 SanityCheckManifestServices(parent) | |
124 | |
125 return 0 | 105 return 0 |
126 | 106 |
127 if __name__ == "__main__": | 107 if __name__ == "__main__": |
128 sys.exit(main()) | 108 sys.exit(main()) |
OLD | NEW |