# SPDX-License-Identifier: GPL-2.0-or-later # Copyright 2018 sysmocom - s.f.m.c. GmbH import collections import os import subprocess import sys # Same folder import parse def git_clone(workdir, prefix, cache_git_fetch, repository, version): """ Clone a missing git repository and checkout a specific version tag. :param workdir: path to where all data (git, build, install) is stored :param prefix: git url prefix (e.g. "git://git.osmocom.org/") :param cache_git_fetch: list of repositories that have already been fetched in this run of osmo-depcheck :param repository: Osmocom git repository name (e.g. "libosmo-abis") :param version: "master" or a version tag like "0.11.0" """ repodir = workdir + "/git/" + repository if repository not in cache_git_fetch: if os.path.exists(repodir): # Fetch tags for existing source print("Fetching tags...") subprocess.run(["git", "-C", repodir, "fetch", "--tags", "-q"], check=True) else: # Clone the source url = prefix + repository print("Cloning git repo: " + url) try: subprocess.run(["git", "-C", workdir + "/git", "clone", "-q", url], check=True) except subprocess.CalledProcessError: print("NOTE: if '" + repository + "' is part of a git" " repository with a different name, please add it to the" " mapping in 'config.py' and try again.") sys.exit(1) # Only fetch the same repository once per session cache_git_fetch.append(repository) # Checkout the version tag try: subprocess.run(["git", "-C", repodir, "checkout", version, "-q"], check=True) except subprocess.CalledProcessError: print("ERROR: git checkout failed! Invalid version specified?") sys.exit(1) def generate(workdir, prefix, cache_git_fetch, initial, rev): """ Generate the dependency graph of an Osmocom program by cloning the git repository, parsing the "configure.ac" file, and recursing. :param workdir: path to where all data (git, build, install) is stored :param prefix: git url prefix (e.g. "git://git.osmocom.org/") :param cache_git_fetch: list of repositories that have already been fetched in this run of osmo-depcheck :param initial: the first program to look at (e.g. "osmo-bts") :param rev: the git revision to check out ("master", "0.1.0", ...) :returns: a dictionary like the following: {"osmo-bts": {"version": "master", "depends": {"libosmocore": "0.11.0", "libosmo-abis": "0.5.0"}}, "libosmocore": {"version": "0.11.0", "depends": {}}, "libosmo-abis": {"version": "0.5.0", "depends": {"libosmocore": "0.11.0"}} """ # Iterate over stack stack = collections.OrderedDict({initial: rev}) ret = collections.OrderedDict() while len(stack): # Pop program from stack program, version = next(iter(stack.items())) del stack[program] # Skip when already parsed if program in ret: continue # Add the programs dependencies to the stack print("Looking at " + program + ":" + version) git_clone(workdir, prefix, cache_git_fetch, program, version) depends = parse.configure_ac(workdir, program) stack.update(depends) # Add the program to the ret ret[program] = {"version": version, "depends": depends} return ret def print_dict(depends): """ Print the whole dependency graph. :param depends: return value from generate() above """ print("Dependency graph:") for program, data in depends.items(): version = data["version"] depends = data["depends"] print(" * " + program + ":" + version + " depends: " + str(depends)) def git_latest_tag(workdir, repository): """ Get the last release string by asking git for the latest tag. :param workdir: path to where all data (git, build, install) is stored :param repository: Osmocom git repository name (e.g. "libosmo-abis") :returns: the latest git tag (e.g. "1.0.2") """ dir = workdir + "/git/" + repository complete = subprocess.run(["git", "-C", dir, "describe", "--abbrev=0", "master"], check=True, stdout=subprocess.PIPE) return complete.stdout.decode().rstrip() def print_old(workdir, depends): """ Print dependencies tied to an old release tag :param workdir: path to where all data (git, build, install) is stored :param depends: return value from generate() above """ print("Dependencies on old releases:") for program, data in depends.items(): for depend, version in data["depends"].items(): latest = git_latest_tag(workdir, depend) if latest == version: continue print(" * " + program + ":" + data["version"] + " -> " + depend + ":" + version + " (latest: " + latest + ")")