| # Copyright 2018 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import collections |
| import functools |
| import json |
| |
| |
| class File(object): |
| '''Wrapper class for file definitions.''' |
| |
| def __init__(self, json): |
| self.source = json['source'] |
| self.destination = json['destination'] |
| |
| def __str__(self): |
| return '{%s <-- %s}' % (self.destination, self.source) |
| |
| |
| @functools.total_ordering |
| class Atom(object): |
| '''Wrapper class for atom data, adding convenience methods.''' |
| |
| def __init__(self, json): |
| self.json = json |
| self.id = json['id'] |
| self.metadata = json['meta'] |
| self.label = json['gn-label'] |
| self.category = json['category'] |
| self.deps = json['deps'] |
| self.files = [File(f) for f in json['files']] |
| self.type = json['type'] |
| |
| def __str__(self): |
| return str(self.id) |
| |
| def __hash__(self): |
| return hash(self.label) |
| |
| def __eq__(self, other): |
| return self.label == other.label |
| |
| def __ne__(self, other): |
| return not __eq__(self, other) |
| |
| def __lt__(self, other): |
| return self.id < other.id |
| |
| |
| def gather_dependencies(manifests): |
| '''Extracts the set of all required atoms from the given manifests, as well |
| as the set of names of all the direct dependencies. |
| ''' |
| direct_deps = set() |
| atoms = set() |
| |
| if manifests is None: |
| return (direct_deps, atoms) |
| |
| for dep in manifests: |
| with open(dep, 'r') as dep_file: |
| dep_manifest = json.load(dep_file) |
| direct_deps.update(dep_manifest['ids']) |
| atoms.update([Atom(a) for a in dep_manifest['atoms']]) |
| return (direct_deps, atoms) |
| |
| |
| def detect_collisions(atoms): |
| '''Detects name collisions in a given atom list.''' |
| mappings = collections.defaultdict(lambda: []) |
| for atom in atoms: |
| mappings[atom.id].append(atom) |
| has_collisions = False |
| for id, group in mappings.items(): |
| if len(group) == 1: |
| continue |
| has_collisions = True |
| labels = [a.label for a in group] |
| print('Targets sharing the SDK id %s:' % id) |
| for label in labels: |
| print(' - %s' % label) |
| return has_collisions |
| |
| |
| CATEGORIES = [ |
| 'excluded', |
| 'experimental', |
| 'internal', |
| 'cts', |
| 'partner', |
| 'public', |
| ] |
| |
| |
| def index_for_category(category): |
| if not category in CATEGORIES: |
| raise Exception('Unknown SDK category "%s"' % category) |
| return CATEGORIES.index(category) |
| |
| |
| def detect_category_violations(category, atoms): |
| '''Detects mismatches in publication categories.''' |
| has_violations = False |
| category_index = index_for_category(category) |
| for atom in atoms: |
| if index_for_category(atom.category) < category_index: |
| has_violations = True |
| print( |
| '%s has publication level %s, incompatible with %s' % |
| (atom, atom.category, category)) |
| return has_violations |