2019-05-30 11:53:41 -07:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# This script figures the order in which workspace crates must be published to
|
|
|
|
# crates.io. Along the way it also ensures there are no circular dependencies
|
|
|
|
# that would cause a |cargo publish| to fail.
|
|
|
|
#
|
|
|
|
# On success an ordered list of Cargo.toml files is written to stdout
|
|
|
|
#
|
|
|
|
|
|
|
|
import os
|
|
|
|
import json
|
|
|
|
import subprocess
|
|
|
|
import sys;
|
|
|
|
|
|
|
|
def load_metadata():
|
|
|
|
return json.loads(subprocess.Popen(
|
|
|
|
'cargo metadata --no-deps --format-version=1',
|
|
|
|
shell=True, stdout=subprocess.PIPE).communicate()[0])
|
|
|
|
|
|
|
|
def get_packages():
|
|
|
|
metadata = load_metadata()
|
|
|
|
|
|
|
|
manifest_path = dict()
|
|
|
|
|
|
|
|
# Build dictionary of packages and their immediate solana-only dependencies
|
|
|
|
dependency_graph = dict()
|
|
|
|
for pkg in metadata['packages']:
|
|
|
|
manifest_path[pkg['name']] = pkg['manifest_path'];
|
2019-05-30 13:44:27 -07:00
|
|
|
dependency_graph[pkg['name']] = [x['name'] for x in pkg['dependencies'] if x['name'].startswith('solana')];
|
2019-05-30 11:53:41 -07:00
|
|
|
|
|
|
|
# Check for direct circular dependencies
|
|
|
|
circular_dependencies = set()
|
|
|
|
for package, dependencies in dependency_graph.items():
|
|
|
|
for dependency in dependencies:
|
|
|
|
if dependency in dependency_graph and package in dependency_graph[dependency]:
|
|
|
|
circular_dependencies.add(' <--> '.join(sorted([package, dependency])))
|
|
|
|
|
|
|
|
for dependency in circular_dependencies:
|
|
|
|
sys.stderr.write('Error: Circular dependency: {}\n'.format(dependency))
|
|
|
|
|
|
|
|
if len(circular_dependencies) != 0:
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# Order dependencies
|
|
|
|
sorted_dependency_graph = []
|
|
|
|
max_iterations = pow(len(dependency_graph),2)
|
|
|
|
while dependency_graph:
|
|
|
|
if max_iterations == 0:
|
2019-10-21 22:25:06 -07:00
|
|
|
# One day be more helpful and find the actual cycle for the user...
|
2019-05-30 11:53:41 -07:00
|
|
|
sys.exit('Error: Circular dependency suspected between these packages: {}\n'.format(' '.join(dependency_graph.keys())))
|
|
|
|
|
|
|
|
max_iterations -= 1
|
|
|
|
for package, dependencies in dependency_graph.items():
|
|
|
|
for dependency in dependencies:
|
|
|
|
if dependency in dependency_graph:
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
del dependency_graph[package]
|
|
|
|
sorted_dependency_graph.append((package, manifest_path[package]))
|
|
|
|
|
|
|
|
|
|
|
|
return sorted_dependency_graph
|
|
|
|
|
|
|
|
for package, manifest in get_packages():
|
|
|
|
print os.path.relpath(manifest)
|