From a99a73dca619d48f2e896932d87b4c18d59f94e0 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Mon, 19 Mar 2018 12:20:38 -0500 Subject: [PATCH] Uninstall and reinstall siblings one at a time The current logic uninstalls all detected siblings first, then it executes a single install with all of the detected sibling git repos. If one sibling (A) depends on another sibling (B), then the commands: pip uninstall A pip uninstall B pip install ../A ../B Will result in pip finding B in the requirements list for ../A and re-installing the released version, then considering the requirement satisfied when it gets to ../B and not installing it. To solve that, do the uninstall and reinstall in a single-project loop for each sibling. This results in: pip uninstall A pip install ../A pip will find B in ../A's requirements, but B will already be installed because it hasn't been uninstalled yet, so nothing will happen. Then: pip uninstall B pip install ../B Which will result in both ../A and ../B being installed. As if that wasn't enough, if A and B happen to appear in the opposite order, doing: pip uninstall B pip install ../B pip uninstall A pip install ../A Will wind up with pip uninstalling ../B and installing B if the version requested for B is greater than the version reported by ../B (which is the case for openstack projects operating from master after a release but before the first release of the next cycle) In order to combat that, do a second installation pass with --no-deps. This way the first pass will be sure to get any transitive dependency changes, but the second pass will ensure all the siblings are installed instead of their non-git versions. pip uninstall B pip install ../B pip uninstall A pip install ../A pip install --no-deps ../B pip install --no-deps ../A Change-Id: I060e188313391de7847adf851566468c4b032342 --- .../library/tox_install_sibling_packages.py | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/roles/tox/library/tox_install_sibling_packages.py b/roles/tox/library/tox_install_sibling_packages.py index 9851d5cfc..259c0a20d 100644 --- a/roles/tox/library/tox_install_sibling_packages.py +++ b/roles/tox/library/tox_install_sibling_packages.py @@ -200,30 +200,42 @@ def main(): root=sibling_python_packages[package.name])) changed = True - log.append("Uninstalling {name}".format(name=package.name)) - uninstall_output = subprocess.check_output( - [tox_python, '-m', 'pip', 'uninstall', '-y', package.name], - stderr=subprocess.STDOUT) - log.extend(uninstall_output.decode('utf-8').split('\n')) found_sibling_packages.append(package.name) - args = [tox_python, '-m', 'pip', 'install'] - if constraints: constraints_file = write_new_constraints_file( constraints, found_sibling_packages) - args.extend(['-c', constraints_file]) + + for sibling_package in found_sibling_packages: + log.append("Uninstalling {name}".format(name=sibling_package)) + uninstall_output = subprocess.check_output( + [tox_python, '-m', + 'pip', 'uninstall', '-y', sibling_package], + stderr=subprocess.STDOUT) + log.extend(uninstall_output.decode('utf-8').split('\n')) + + args = [tox_python, '-m', 'pip', 'install'] + if constraints: + args.extend(['-c', constraints_file]) + log.append( + "Installing {name} from {root} for deps".format( + name=sibling_package, + root=sibling_python_packages[sibling_package])) + args.append(sibling_python_packages[sibling_package]) + + install_output = subprocess.check_output(args) + log.extend(install_output.decode('utf-8').split('\n')) for sibling_package in found_sibling_packages: log.append( "Installing {name} from {root}".format( name=sibling_package, root=sibling_python_packages[sibling_package])) - args.append('-e') - args.append(sibling_python_packages[sibling_package]) - install_output = subprocess.check_output(args) - log.extend(install_output.decode('utf-8').split('\n')) + install_output = subprocess.check_output( + [tox_python, '-m', 'pip', 'install', '--no-deps', + sibling_python_packages[sibling_package]]) + log.extend(install_output.decode('utf-8').split('\n')) except Exception as e: tb = traceback.format_exc() log.append(str(e))