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
This commit is contained in:
Monty Taylor 2018-03-19 12:20:38 -05:00 committed by Andreas Jaeger
parent d28c326b36
commit a99a73dca6

View File

@ -200,29 +200,41 @@ 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)
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)
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()