/etc/python/armarx/armarx_version.py
Python | 283 lines | 239 code | 18 blank | 26 comment | 13 complexity | 140f182184d54cac89e76e54cbd083c7 MD5 | raw file
- #!/usr/bin/env python2
- from __future__ import with_statement, print_function, division
- import os
- import logging
- from argparse import ArgumentParser
- from collections import namedtuple
- import re
- import subprocess
- logger = logging.getLogger(__name__)
- Version = namedtuple('Version', ['major', 'minor', 'patch'])
- armarx_pkgs = {"ArmarXCore", "ArmarXGui", "RobotAPI", "MemoryX", "VisionX",
- "RobotComponents", "ArmarXSimulation",
- "RobotSkillTemplates", "ArmarXDB"}
- armarx_version_file = "etc/cmake/ArmarXPackageVersion.cmake"
- def get_version(pkg_name):
- pkg_dir = get_armarx_pkg_dir(pkg_name)
- version = read_armarx_version(pkg_dir)
- return format_version(version)
- def read_armarx_version(pkg_dir):
- """
- get the current armarx version for a package
- :param pkg_dir: path to the top level package directory
- :returns: the armarx version
- :rtype: dict with major minor patch version
- """
- version = {}
- path = os.path.join(pkg_dir, armarx_version_file)
- with open(path) as f:
- lines = f.readlines()
- for l in lines:
- match = re.search('.*ARMARX_PACKAGE_LIBRARY_VERSION_([A-Z]*) "(\d+)".*', l)
- if match:
- x, v = match.groups()
- if x.lower() not in Version._fields:
- logger.error("error while parsing version file {}".format(path))
- raise ValueError('unable to parse version file')
- version[x.lower()] = int(v)
- return Version(**version)
- def get_armarx_pkg_dir(pkg_name):
- """
- finds the package path for an armarx package
- :param pkg_name: name of the package
- :returns: the path to the package if found
- :rtype: str
- """
- path = os.path.expanduser("~/.cmake/packages/{}/".format(pkg_name))
- l = list(os.listdir(path))
- if len(l) != 1:
- logger.error("unable to find path for package {}. path is not unique".format(pkg_name))
- raise ValueError("unable to find cmake package path")
- with open(os.path.join(path, l[0])) as f:
- lines = f.readlines()
- if len(lines) != 1:
- logger.error("unable to find path for package {}".format(pkg_name))
- raise ValueError("unable to find cmake package path")
- else:
- for line in open(os.path.join(lines[0][:-1], 'CMakeCache.txt')):
- if line.startswith('Project_SOURCE_DIR'):
- return line.split('=')[-1][:-1]
- def print_armarx_version(pkg_names):
- """
- convenience function for printing version number
- :param pkg_name: list of package names
- """
- for p in pkg_names:
- pkg_dir = get_armarx_pkg_dir(p)
- version = read_armarx_version(pkg_dir)
- print("{} {} - {}".format(p, format_version(version), pkg_dir))
- def write_armarx_version(pkg_dir, new_version):
- """
- sets the version in ArmarXPackageVersion.cmake
- :param pkg_dir: path to the package
- :param new_version: the new version
- """
- version_file = '''# armarx version file
- set(ARMARX_PACKAGE_LIBRARY_VERSION_MAJOR "{}")
- set(ARMARX_PACKAGE_LIBRARY_VERSION_MINOR "{}")
- set(ARMARX_PACKAGE_LIBRARY_VERSION_PATCH "{}")
- '''.format(new_version.major, new_version.minor, new_version.patch)
- version_file_footer = '''
- set(ARMARX_PACKAGE_LIBRARY_VERSION "${ARMARX_PACKAGE_LIBRARY_VERSION_MAJOR}.${ARMARX_PACKAGE_LIBRARY_VERSION_MINOR}.${ARMARX_PACKAGE_LIBRARY_VERSION_PATCH}")
- set(ARMARX_PACKAGE_LIBRARY_SOVERSION "0")
- '''
- path = os.path.join(pkg_dir, armarx_version_file)
- with open(path, 'w') as f:
- f.write(version_file)
- f.write(version_file_footer)
- def update_armarx_python(new_version):
- """
- sets the version for python utils
- .. todo:: python utils should extract the version from the cmake version file
- :param new_version: the new version to set
- """
- version_str = format_version(new_version)[1:]
- version_file_content = 'armarx_version = "{}"'.format(version_str)
- path = os.path.join(get_armarx_pkg_dir('ArmarXCore'), 'etc/python/__version__.py')
- with open(path, 'w') as f:
- f.write(version_file_content)
- def format_version(version):
- """
- converts the version dict to a string with the format vx.y.z
- where x is the major, y the minor and z the patch
- :param version: the version to format
- :type version: dict
- :rtype: str
- """
- return 'v{}.{}.{}'.format(version.major, version.minor, version.patch)
- def commit_version(pkg_name, pkg_dir, new_version):
- """
- creates a git commit and tag for the new version
- :param pkg_name: name of the package
- :param pkg_dir: path to the pacakge
- :param new_version: the new version to set
- """
- os.chdir(pkg_dir)
- cmd = 'git checkout stable'
- subprocess.check_call([cmd], shell=True)
- str_version = format_version(new_version)
- subprocess.check_call(['pwd'], shell=True)
- cmd = 'git commit -m "version bump to {}" -- "{}"'.format(str_version, armarx_version_file)
- if pkg_name == "ArmarXCore":
- cmd = cmd + ' etc/python/__version__.py'
- subprocess.check_call([cmd], shell=True)
- cmd = 'git tag -a {} -m "{} {}"'.format(str_version, pkg_name, str_version)
- subprocess.check_call([cmd], shell=True)
- def parse_version(v_str):
- """
- :param v_str: the version string to parse
- :returns: the parsed version
- :rtype: dict
- """
- if v_str.startswith("v"):
- v_str = v_str[1:]
- version = map(int, v_str.split('.'))
- version = Version(*version)
- if version > Version(0, 0, 0):
- return version
- def push_version(pkg_dir):
- """
- convenience function for pushing the git repository
- :param pkg_dir: path to the package
- """
- cmd = 'git push --tags -u origin'
- subprocess.check_call([cmd], shell=True)
- def increase_version(current_version, bump):
- """
- increase the version
- :param current_version: the current version
- :type current_version: dict
- :param bump: specifies the version increase
- :type bump: str
- :return: the increased version
- :rtype: dict
- """
- new_version = list(current_version)
- found = False
- for i, k in enumerate(Version._fields):
- if found:
- new_version[i] = 0
- elif k == bump:
- new_version[i] = current_version[i] + 1
- found = True
- return Version(*new_version)
- def bump_version(bump, pkg_names):
- """
- convenience function to increase the version
- """
- new_version = {}
- for p in pkg_names:
- pkg_dir = get_armarx_pkg_dir(p)
- current_version = read_armarx_version(pkg_dir)
- bumped_version = increase_version(current_version, bump)
- logger.info("new version is {}".format(format_version(bumped_version)))
- if not new_version:
- new_version = bumped_version
- elif new_version != bumped_version:
- logger.error("unable to bump version for package {}".format(p))
- logger.error("new version is {}. expected {}".format(format_version(bumped_version), format_version(new_version)))
- return
- set_version(new_version, pkg_names)
- def set_version(new_version, pkg_names):
- """
- set the version
- """
- logger.info("setting version to {}".format(format_version(new_version)))
- pkg_dirs = map(get_armarx_pkg_dir, pkg_names)
- for p in pkg_dirs:
- current_version = read_armarx_version(p)
- logger.debug("{}: {} -> {}".format(p, format_version(current_version), format_version(new_version)))
- if not new_version > current_version:
- logger.error("invalid version increase from {} to {} in {}".format(current_version, new_version, p))
- return
- for p in pkg_dirs:
- write_armarx_version(p, new_version)
- update_armarx_python(new_version)
- for pkg_name, pkg_path in zip(pkg_names, pkg_dirs):
- commit_version(pkg_name, pkg_path, new_version)
- logger.info("push to origin: repo forall -c 'git push'")
- logger.info("done.")
- def main():
- parser = ArgumentParser(description="armarx version script")
- verbose_group = parser.add_mutually_exclusive_group()
- verbose_group.add_argument('-v', '--verbose', action='store_true', help='be verbose')
- verbose_group.add_argument('-q', '--quiet', action='store_true', help='be quiet')
- group = parser.add_mutually_exclusive_group()
- group.add_argument('-b', '--bump-version', choices=['major', 'minor', 'patch'], help='version bump')
- group.add_argument('-s', '--set-version', help='set the version')
- group.add_argument('-p', '--print-package', nargs='+', help='print the version for a package name')
- # parser.add_argument('-p', '--package', help='limit command to packages')
- args = parser.parse_args()
- if args.verbose:
- logging.basicConfig(level=logging.DEBUG)
- elif args.quiet:
- logging.basicConfig(level=logging.ERROR)
- else:
- logging.basicConfig()
- if args.print_package:
- print_armarx_version(args.print_package)
- elif args.bump_version:
- bump_version(args.bump_version, armarx_pkgs)
- elif args.set_version:
- new_version = parse_version(args.set_version)
- set_version(new_version, armarx_pkgs)
- else:
- print_armarx_version(armarx_pkgs)
- if __name__ == "__main__":
- main()