X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/1efba8f3b728a3b8aa3c64c5aa09f441318ff2a8..a683ec930d6658145b2e96131288f4ef3000a7d5:/tools/user-activity/arvados_version.py diff --git a/tools/user-activity/arvados_version.py b/tools/user-activity/arvados_version.py index d8eec3d9ee..b594f88a7c 100644 --- a/tools/user-activity/arvados_version.py +++ b/tools/user-activity/arvados_version.py @@ -1,58 +1,128 @@ # Copyright (C) The Arvados Authors. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 +# +# This file runs in one of three modes: +# +# 1. If the ARVADOS_BUILDING_VERSION environment variable is set, it writes +# _version.py and generates dependencies based on that value. +# 2. If running from an arvados Git checkout, it writes _version.py +# and generates dependencies from Git. +# 3. Otherwise, we expect this is source previously generated from Git, and +# it reads _version.py and generates dependencies from it. -import subprocess -import time import os -import re +import runpy +import subprocess import sys -SETUP_DIR = os.path.dirname(os.path.abspath(__file__)) -VERSION_PATHS = { - SETUP_DIR, - os.path.abspath(os.path.join(SETUP_DIR, "../../sdk/python")), - os.path.abspath(os.path.join(SETUP_DIR, "../../build/version-at-commit.sh")) - } +from pathlib import Path + +# These maps explain the relationships between different Python modules in +# the arvados repository. We use these to help generate setup.py. +PACKAGE_DEPENDENCY_MAP = { + 'arvados-cwl-runner': ['arvados-python-client', 'crunchstat_summary'], + 'arvados-user-activity': ['arvados-python-client'], + 'arvados_fuse': ['arvados-python-client'], + 'crunchstat_summary': ['arvados-python-client'], +} +PACKAGE_MODULE_MAP = { + 'arvados-cwl-runner': 'arvados_cwl', + 'arvados-docker-cleaner': 'arvados_docker', + 'arvados-python-client': 'arvados', + 'arvados-user-activity': 'arvados_user_activity', + 'arvados_fuse': 'arvados_fuse', + 'crunchstat_summary': 'crunchstat_summary', +} +PACKAGE_SRCPATH_MAP = { + 'arvados-cwl-runner': Path('sdk', 'cwl'), + 'arvados-docker-cleaner': Path('services', 'dockercleaner'), + 'arvados-python-client': Path('sdk', 'python'), + 'arvados-user-activity': Path('tools', 'user-activity'), + 'arvados_fuse': Path('services', 'fuse'), + 'crunchstat_summary': Path('tools', 'crunchstat-summary'), +} + +ENV_VERSION = os.environ.get("ARVADOS_BUILDING_VERSION") +SETUP_DIR = Path(__file__).absolute().parent +try: + REPO_PATH = Path(subprocess.check_output( + ['git', '-C', str(SETUP_DIR), 'rev-parse', '--show-toplevel'], + stderr=subprocess.DEVNULL, + text=True, + ).rstrip('\n')) +except (subprocess.CalledProcessError, OSError): + REPO_PATH = None +else: + # Verify this is the arvados monorepo + if all((REPO_PATH / path).exists() for path in PACKAGE_SRCPATH_MAP.values()): + PACKAGE_NAME, = ( + pkg_name for pkg_name, path in PACKAGE_SRCPATH_MAP.items() + if (REPO_PATH / path) == SETUP_DIR + ) + MODULE_NAME = PACKAGE_MODULE_MAP[PACKAGE_NAME] + VERSION_SCRIPT_PATH = Path(REPO_PATH, 'build', 'version-at-commit.sh') + else: + REPO_PATH = None +if REPO_PATH is None: + (PACKAGE_NAME, MODULE_NAME), = ( + (pkg_name, mod_name) + for pkg_name, mod_name in PACKAGE_MODULE_MAP.items() + if (SETUP_DIR / mod_name).is_dir() + ) + +def short_tests_only(arglist=sys.argv): + try: + arglist.remove('--short-tests-only') + except ValueError: + return False + else: + return True + +def git_log_output(path, *args): + return subprocess.check_output( + ['git', '-C', str(REPO_PATH), + 'log', '--first-parent', '--max-count=1', + *args, str(path)], + text=True, + ).rstrip('\n') def choose_version_from(): - ts = {} - for path in VERSION_PATHS: - ts[subprocess.check_output( - ['git', 'log', '--first-parent', '--max-count=1', - '--format=format:%ct', path]).strip()] = path - - sorted_ts = sorted(ts.items()) - getver = sorted_ts[-1][1] - print("Using "+getver+" for version number calculation of "+SETUP_DIR, file=sys.stderr) + ver_paths = [SETUP_DIR, VERSION_SCRIPT_PATH, *( + PACKAGE_SRCPATH_MAP[pkg] + for pkg in PACKAGE_DEPENDENCY_MAP.get(PACKAGE_NAME, ()) + )] + getver = max(ver_paths, key=lambda path: git_log_output(path, '--format=format:%ct')) + print(f"Using {getver} for version number calculation of {SETUP_DIR}", file=sys.stderr) return getver def git_version_at_commit(): curdir = choose_version_from() - myhash = subprocess.check_output(['git', 'log', '-n1', '--first-parent', - '--format=%H', curdir]).strip() - myversion = subprocess.check_output([SETUP_DIR+'/../../build/version-at-commit.sh', myhash]).strip().decode() - return myversion + myhash = git_log_output(curdir, '--format=%H') + return subprocess.check_output( + [str(VERSION_SCRIPT_PATH), myhash], + text=True, + ).rstrip('\n') def save_version(setup_dir, module, v): - v = v.replace("~dev", ".dev").replace("~rc", "rc") - with open(os.path.join(setup_dir, module, "_version.py"), 'wt') as fp: - return fp.write("__version__ = '%s'\n" % v) + with Path(setup_dir, module, '_version.py').open('w') as fp: + print(f"__version__ = {v!r}", file=fp) def read_version(setup_dir, module): - with open(os.path.join(setup_dir, module, "_version.py"), 'rt') as fp: - return re.match("__version__ = '(.*)'$", fp.read()).groups()[0] - -def get_version(setup_dir, module): - env_version = os.environ.get("ARVADOS_BUILDING_VERSION") + file_vars = runpy.run_path(Path(setup_dir, module, '_version.py')) + return file_vars['__version__'] - if env_version: - save_version(setup_dir, module, env_version) +def get_version(setup_dir=SETUP_DIR, module=MODULE_NAME): + if ENV_VERSION: + version = ENV_VERSION + elif REPO_PATH is None: + return read_version(setup_dir, module) else: - try: - save_version(setup_dir, module, git_version_at_commit()) - except (subprocess.CalledProcessError, OSError) as err: - print("ERROR: {0}".format(err), file=sys.stderr) - pass + version = git_version_at_commit() + version = version.replace("~dev", ".dev").replace("~rc", "rc") + save_version(setup_dir, module, version) + return version - return read_version(setup_dir, module) +# Called from calculate_python_sdk_cwl_package_versions() in run-library.sh +if __name__ == '__main__': + print(get_version())