1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
5 # This file runs in one of three modes:
7 # 1. If the ARVADOS_BUILDING_VERSION environment variable is set, it writes
8 # _version.py and generates dependencies based on that value.
9 # 2. If running from an arvados Git checkout, it writes _version.py
10 # and generates dependencies from Git.
11 # 3. Otherwise, we expect this is source previously generated from Git, and
12 # it reads _version.py and generates dependencies from it.
19 from pathlib import Path
21 # These maps explain the relationships between different Python modules in
22 # the arvados repository. We use these to help generate setup.py.
23 PACKAGE_DEPENDENCY_MAP = {
24 'arvados-cwl-runner': ['arvados-python-client', 'crunchstat_summary'],
25 'arvados-user-activity': ['arvados-python-client'],
26 'arvados_fuse': ['arvados-python-client'],
27 'crunchstat_summary': ['arvados-python-client'],
29 PACKAGE_MODULE_MAP = {
30 'arvados-cwl-runner': 'arvados_cwl',
31 'arvados-docker-cleaner': 'arvados_docker',
32 'arvados-python-client': 'arvados',
33 'arvados-user-activity': 'arvados_user_activity',
34 'arvados_fuse': 'arvados_fuse',
35 'crunchstat_summary': 'crunchstat_summary',
37 PACKAGE_SRCPATH_MAP = {
38 'arvados-cwl-runner': Path('sdk', 'cwl'),
39 'arvados-docker-cleaner': Path('services', 'dockercleaner'),
40 'arvados-python-client': Path('sdk', 'python'),
41 'arvados-user-activity': Path('tools', 'user-activity'),
42 'arvados_fuse': Path('services', 'fuse'),
43 'crunchstat_summary': Path('tools', 'crunchstat-summary'),
46 ENV_VERSION = os.environ.get("ARVADOS_BUILDING_VERSION")
47 SETUP_DIR = Path(__file__).absolute().parent
49 REPO_PATH = Path(subprocess.check_output(
50 ['git', '-C', str(SETUP_DIR), 'rev-parse', '--show-toplevel'],
51 stderr=subprocess.DEVNULL,
54 except (subprocess.CalledProcessError, OSError):
57 # Verify this is the arvados monorepo
58 if all((REPO_PATH / path).exists() for path in PACKAGE_SRCPATH_MAP.values()):
60 pkg_name for pkg_name, path in PACKAGE_SRCPATH_MAP.items()
61 if (REPO_PATH / path) == SETUP_DIR
63 MODULE_NAME = PACKAGE_MODULE_MAP[PACKAGE_NAME]
64 VERSION_SCRIPT_PATH = Path(REPO_PATH, 'build', 'version-at-commit.sh')
68 (PACKAGE_NAME, MODULE_NAME), = (
70 for pkg_name, mod_name in PACKAGE_MODULE_MAP.items()
71 if (SETUP_DIR / mod_name).is_dir()
74 def short_tests_only(arglist=sys.argv):
76 arglist.remove('--short-tests-only')
82 def git_log_output(path, *args):
83 return subprocess.check_output(
84 ['git', '-C', str(REPO_PATH),
85 'log', '--first-parent', '--max-count=1',
90 def choose_version_from():
91 ver_paths = [SETUP_DIR, VERSION_SCRIPT_PATH, *(
92 PACKAGE_SRCPATH_MAP[pkg]
93 for pkg in PACKAGE_DEPENDENCY_MAP.get(PACKAGE_NAME, ())
95 getver = max(ver_paths, key=lambda path: git_log_output(path, '--format=format:%ct'))
96 print(f"Using {getver} for version number calculation of {SETUP_DIR}", file=sys.stderr)
99 def git_version_at_commit():
100 curdir = choose_version_from()
101 myhash = git_log_output(curdir, '--format=%H')
102 return subprocess.check_output(
103 [str(VERSION_SCRIPT_PATH), myhash],
107 def save_version(setup_dir, module, v):
108 with Path(setup_dir, module, '_version.py').open('w') as fp:
109 print(f"__version__ = {v!r}", file=fp)
111 def read_version(setup_dir, module):
112 file_vars = runpy.run_path(Path(setup_dir, module, '_version.py'))
113 return file_vars['__version__']
115 def get_version(setup_dir=SETUP_DIR, module=MODULE_NAME):
117 version = ENV_VERSION
118 elif REPO_PATH is None:
119 return read_version(setup_dir, module)
121 version = git_version_at_commit()
122 version = version.replace("~dev", ".dev").replace("~rc", "rc")
123 save_version(setup_dir, module, version)
126 # Called from calculate_python_sdk_cwl_package_versions() in run-library.sh
127 if __name__ == '__main__':