1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#!/usr/bin/env python 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# Copyright 2016 The Chromium Authors. All rights reserved. 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# Use of this source code is governed by a BSD-style license that can be 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# found in the LICENSE file. 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez""" A collator for Mojo Application Manifests """ 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport argparse 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport json 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport os 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport shutil 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport sys 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport urlparse 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezeater_relative = '../../../../../tools/json_comment_eater' 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezeater_relative = os.path.join(os.path.abspath(__file__), eater_relative) 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezsys.path.insert(0, os.path.normpath(eater_relative)) 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztry: 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez import json_comment_eater 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfinally: 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sys.path.pop(0) 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef ParseJSONFile(filename): 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez with open(filename) as json_file: 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return json.loads(json_comment_eater.Nom(json_file.read())) 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except ValueError: 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez print "%s is not a valid JSON document" % filename 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return None 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef MergeDicts(left, right): 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for k, v in right.iteritems(): 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if k not in left: 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez left[k] = v 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(v, dict): 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert isinstance(left[k], dict) 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MergeDicts(left[k], v) 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif isinstance(v, list): 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert isinstance(left[k], list) 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez left[k].extend(v) 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise "Refusing to merge conflicting non-collection values." 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return left 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef MergeBaseManifest(parent, base): 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MergeDicts(parent["capabilities"], base["capabilities"]) 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if "applications" in base: 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if "applications" not in parent: 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent["applications"] = [] 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent["applications"].extend(base["applications"]) 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if "process-group" in base: 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent["process-group"] = base["process-group"] 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef main(): 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parser = argparse.ArgumentParser( 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez description="Collate Mojo application manifests.") 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parser.add_argument("--parent") 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parser.add_argument("--output") 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parser.add_argument("--application-name") 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parser.add_argument("--base-manifest", default=None) 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez args, children = parser.parse_known_args() 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent = ParseJSONFile(args.parent) 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if parent == None: 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 1 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if args.base_manifest: 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base = ParseJSONFile(args.base_manifest) 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if base == None: 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 1 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MergeBaseManifest(parent, base) 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez app_path = parent['name'].split(':')[1] 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if app_path.startswith('//'): 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise ValueError("Application name path component '%s' must not start " \ 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "with //" % app_path) 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if args.application_name != app_path: 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise ValueError("Application name '%s' specified in build file does not " \ 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "match application name '%s' specified in manifest." % 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (args.application_name, app_path)) 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez applications = [] 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for child in children: 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez application = ParseJSONFile(child) 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if application == None: 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 1 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez applications.append(application) 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if len(applications) > 0: 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez parent['applications'] = applications 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez with open(args.output, 'w') as output_file: 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez json.dump(parent, output_file) 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 0 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezif __name__ == "__main__": 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sys.exit(main()) 105