Home | History | Annotate | Download | only in manifest
      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 Mojo Application Manifests """
      7 
      8 import argparse
      9 import json
     10 import os
     11 import shutil
     12 import sys
     13 import urlparse
     14 
     15 eater_relative = '../../../../../tools/json_comment_eater'
     16 eater_relative = os.path.join(os.path.abspath(__file__), eater_relative)
     17 sys.path.insert(0, os.path.normpath(eater_relative))
     18 try:
     19   import json_comment_eater
     20 finally:
     21   sys.path.pop(0)
     22 
     23 def ParseJSONFile(filename):
     24   with open(filename) as json_file:
     25     try:
     26       return json.loads(json_comment_eater.Nom(json_file.read()))
     27     except ValueError:
     28       print "%s is not a valid JSON document" % filename
     29       return None
     30 
     31 def MergeDicts(left, right):
     32   for k, v in right.iteritems():
     33     if k not in left:
     34       left[k] = v
     35     else:
     36       if isinstance(v, dict):
     37         assert isinstance(left[k], dict)
     38         MergeDicts(left[k], v)
     39       elif isinstance(v, list):
     40         assert isinstance(left[k], list)
     41         left[k].extend(v)
     42       else:
     43         raise "Refusing to merge conflicting non-collection values."
     44   return left
     45 
     46 
     47 def MergeBaseManifest(parent, base):
     48   MergeDicts(parent["capabilities"], base["capabilities"])
     49 
     50   if "applications" in base:
     51     if "applications" not in parent:
     52       parent["applications"] = []
     53     parent["applications"].extend(base["applications"])
     54 
     55   if "process-group" in base:
     56     parent["process-group"] = base["process-group"]
     57 
     58 
     59 def main():
     60   parser = argparse.ArgumentParser(
     61       description="Collate Mojo application manifests.")
     62   parser.add_argument("--parent")
     63   parser.add_argument("--output")
     64   parser.add_argument("--application-name")
     65   parser.add_argument("--base-manifest", default=None)
     66   args, children = parser.parse_known_args()
     67 
     68   parent = ParseJSONFile(args.parent)
     69   if parent == None:
     70     return 1
     71 
     72   if args.base_manifest:
     73     base = ParseJSONFile(args.base_manifest)
     74     if base == None:
     75       return 1
     76     MergeBaseManifest(parent, base)
     77 
     78   app_path = parent['name'].split(':')[1]
     79   if app_path.startswith('//'):
     80     raise ValueError("Application name path component '%s' must not start " \
     81                      "with //" % app_path)
     82 
     83   if args.application_name != app_path:
     84     raise ValueError("Application name '%s' specified in build file does not " \
     85                      "match application name '%s' specified in manifest." %
     86                      (args.application_name, app_path))
     87 
     88   applications = []
     89   for child in children:
     90     application = ParseJSONFile(child)
     91     if application == None:
     92       return 1
     93     applications.append(application)
     94 
     95   if len(applications) > 0:
     96     parent['applications'] = applications
     97 
     98   with open(args.output, 'w') as output_file:
     99     json.dump(parent, output_file)
    100 
    101   return 0
    102 
    103 if __name__ == "__main__":
    104   sys.exit(main())
    105