1# Copyright (C) 2010-2013 Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2# Copyright (C) 2019 Yann E. MORIN <yann.morin.1998@free.fr>
3
4import json
5import logging
6import os
7import subprocess
8from collections import defaultdict
9
10
11# This function returns a tuple of four dictionaries, all using package
12# names as keys:
13# - a dictionary which values are the lists of packages that are the
14#   dependencies of the package used as key;
15# - a dictionary which values are the lists of packages that are the
16#   reverse dependencies of the package used as key;
17# - a dictionary which values are the type of the package used as key;
18# - a dictionary which values are the version of the package used as key,
19#   'virtual' for a virtual package, or the empty string for a rootfs.
20def get_dependency_tree():
21    logging.info("Getting dependency tree...")
22
23    deps = {}
24    rdeps = defaultdict(list)
25    types = {}
26    versions = {}
27
28    # Special case for the 'all' top-level fake package
29    deps['all'] = []
30    types['all'] = 'target'
31    versions['all'] = ''
32
33    cmd = ["make", "-s", "--no-print-directory", "show-info"]
34    with open(os.devnull, 'wb') as devnull:
35        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull,
36                             universal_newlines=True)
37        pkg_list = json.loads(p.communicate()[0])
38
39    for pkg in pkg_list:
40        deps['all'].append(pkg)
41        types[pkg] = pkg_list[pkg]["type"]
42        deps[pkg] = pkg_list[pkg].get("dependencies", [])
43        for p in deps[pkg]:
44            rdeps[p].append(pkg)
45        versions[pkg] = \
46            None if pkg_list[pkg]["type"] == "rootfs" \
47            else "virtual" if pkg_list[pkg]["virtual"] \
48            else pkg_list[pkg]["version"]
49
50    return (deps, rdeps, types, versions)
51