blob: 258b6c4cb56dfd06343a8aac7fee9990ecf5edf6 [file] [log] [blame]
#!/usr/bin/python2.6
# Copyright (c) 2010 The Chromium OS 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 json
import portage
import sys
from parallel_emerge import DepGraphGenerator
def FlattenDepTree(deptree, pkgtable={}, parentcpv=None):
"""
Turn something like this (the parallel_emerge DepsTree format):
{
"app-admin/eselect-1.2.9": {
"action": "merge",
"deps": {
"sys-apps/coreutils-7.5-r1": {
"action": "merge",
"deps": {},
"deptype": "runtime"
},
...
}
}
}
...into something like this (the cros_extract_deps format):
{
"app-admin/eselect-1.2.9": {
"deps": ["coreutils-7.5-r1"],
"rev_deps": [],
"name": "eselect",
"category": "app-admin",
"version": "1.2.9",
"full_name": "app-admin/eselect-1.2.9",
"action": "merge"
},
"sys-apps/coreutils-7.5-r1": {
"deps": [],
"rev_deps": ["app-admin/eselect-1.2.9"],
"name": "coreutils",
"category": "sys-apps",
"version": "7.5-r1",
"full_name": "sys-apps/coreutils-7.5-r1",
"action": "merge"
}
}
"""
for cpv, record in deptree.items():
if cpv not in pkgtable:
cat, nam, ver, rev = portage.catpkgsplit(cpv)
pkgtable[cpv] = {"deps": [],
"rev_deps": [],
"name": nam,
"category": cat,
"version": "%s-%s" % (ver, rev),
"full_name": cpv,
"action": record["action"]}
# If we have a parent, that is a rev_dep for the current package.
if parentcpv:
pkgtable[cpv]["rev_deps"].append(parentcpv)
# If current package has any deps, record those.
for childcpv in record["deps"]:
pkgtable[cpv]["deps"].append(childcpv)
# Visit the subtree recursively as well.
FlattenDepTree(record["deps"], pkgtable=pkgtable, parentcpv=cpv)
return pkgtable
def Usage():
"""Print usage."""
print """Usage:
cros_extract_deps [--board=BOARD] [emerge args] package
This extracts the dependency tree for the specified package, and outputs it
to stdout, in a serialized JSON format. Emerge flags such as --root-deps
can be used to influence what sort of dependency tree is extracted.
"""
def main():
if len(sys.argv) == 1:
Usage()
sys.exit(1)
# We want the toolchain to be quiet because we are going to output
# a well-formed json payload.
argv = ['--quiet', '--pretend']
# cros_extract_deps defaults to rdeps. However, only use this if
# there was no explicit --root-deps command line switch.
default_rootdeps_arg = ['--root-deps=rdeps']
for arg in sys.argv:
if arg.startswith('--root-deps'):
default_rootdeps_arg = []
# Now, assemble the overall argv as the concatenation of the
# default list + possible rootdeps-default + actual command line.
argv.extend(default_rootdeps_arg)
argv.extend(sys.argv[1:])
deps = DepGraphGenerator()
deps.Initialize(argv)
deps_tree, deps_info = deps.GenDependencyTree()
print json.dumps(FlattenDepTree(deps_tree), sort_keys=True, indent=2)
if __name__ == "__main__":
main()