arti/maint/check_toposort

104 lines
2.5 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env python3
#
# Helper script: makes sure that the crates as listed in Cargo.toml are
# topologically sorted from lowest-level to highest level.
import toml.decoder
2022-08-16 18:15:35 +01:00
import sys
import os.path
import os
TOPDIR = os.path.split(os.path.dirname(sys.argv[0]))[0]
CRATEDIR = os.path.join(TOPDIR, "crates")
WORKSPACE_TOML = os.path.join(TOPDIR, "Cargo.toml")
2022-08-16 18:15:35 +01:00
def crate_dirs():
return set(name for name in os.listdir(CRATEDIR) if not name.startswith("."))
2022-08-16 18:15:35 +01:00
def strip_prefix(s, prefix):
if s.startswith(prefix):
return s[len(prefix):]
else:
return s
2022-08-16 18:15:35 +01:00
def crate_list():
t = toml.decoder.load(WORKSPACE_TOML)
return list(strip_prefix(name, "crates/") for name in t['workspace']['members'])
2022-08-16 18:15:35 +01:00
CRATE_LIST = crate_list()
CRATE_DIRS = crate_dirs()
def check_disjoint():
listed_crates = set(crate_list())
if listed_crates != CRATE_DIRS:
print("The crates in the crates/ directory do not match the ones in Cargo.toml!")
print("Problem crates", listed_crates ^ CRATE_DIRS)
return True
else:
return False
def get_path(dep):
try:
return dep['path']
2022-08-16 18:15:35 +01:00
except (KeyError, TypeError):
return None
2022-08-16 18:15:35 +01:00
def get_dependencies(cratename):
fname = os.path.join(CRATEDIR, cratename, "Cargo.toml")
t = toml.decoder.load(fname)
deps = set()
for secname in ['dependencies', 'dev-dependencies']:
sec = t.get(secname)
if not sec:
continue
2022-08-16 18:15:35 +01:00
for (key, val) in sec.items():
path = get_path(val)
if path:
2022-08-16 18:15:35 +01:00
d, p = os.path.split(val['path'])
if d == "..":
assert(p in CRATE_DIRS)
deps.add(p)
return deps
2022-08-16 18:15:35 +01:00
def get_dependency_graph():
all_deps = {}
for crate in CRATE_DIRS:
all_deps[crate] = get_dependencies(crate)
return all_deps
2022-08-16 18:15:35 +01:00
GRAPH = get_dependency_graph()
2022-08-16 18:15:35 +01:00
def check_consistency(order, graph):
"""Make sure that `order` is topologically sorted from bottom to
top, according to `graph`.
"""
seen_so_far = set()
problems = False
for crate in order:
for dependent in graph[crate]:
if dependent not in seen_so_far:
2022-08-16 18:15:35 +01:00
print(
f"{crate} dependency on {dependent} is not reflected in Cargo.toml")
problems = True
seen_so_far.add(crate)
return problems
2022-08-16 18:15:35 +01:00
if __name__ == '__main__':
if check_disjoint():
sys.exit(1)
if check_consistency(CRATE_LIST, GRAPH):
sys.exit(1)
print("Everything seems okay")