Auto merge of #8824 - Ms2ger:tidy-lock, r=Wafflespeanut

Rewrite the Cargo.lock tidy check.

Fixes #8691.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8824)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-12-08 10:21:55 +05:30
commit cad77d5f1c

View file

@ -159,45 +159,52 @@ def check_flake8(file_name, contents):
def check_lock(file_name, contents):
def find_reverse_dependencies(dependency, version, content):
dependency_prefix = "{} {}".format(dependency, version)
for package in itertools.chain([content["root"]], content["package"]):
for dependency in package.get("dependencies", []):
if dependency.startswith(dependency_prefix):
yield package["name"]
if not file_name.endswith(".lock"):
raise StopIteration
contents = contents.splitlines(True)
idx = 1
packages = {}
# package names to be neglected (as named by cargo)
exceptions = ["libc"]
exceptions = ["libc", "byteorder", "cocoa"]
while idx < len(contents):
content = contents[idx].strip()
if 'name' in content:
base_name = content.split('"')[1]
# we need the base package because some other package might demand a new version in the following lines
packages[base_name] = contents[idx + 1].split('"')[1], idx + 2, base_name
if 'dependencies' in content:
idx += 1
while contents[idx].strip() != ']':
package = contents[idx].strip().strip('",').split()
name, version = package[0], package[1]
if name not in packages: # store the line number & base package name for future comparison
packages[name] = (version, idx + 1, base_name)
elif all([packages[name][0] != version, name not in exceptions, base_name not in exceptions]):
line = idx + 1
version_1 = tuple(map(maybe_int, packages[name][0].split('.')))
version_2 = tuple(map(maybe_int, version.split('.')))
if version_1 < version_2: # get the line & base package containing the older version
packages[name], (version, line, base_name) = (version, line, base_name), packages[name]
import toml
content = toml.loads(contents)
message = 'duplicate versions for package "%s"' % name
error = '\n\t\033[93mexpected maximum version "{}"\033[0m'.format(packages[name][0]) + \
'\n\t\033[91mbut, "{}" demands "{}"\033[0m' \
.format(base_name, version)
suggest = "\n\t\033[93mtry upgrading with\033[0m " + \
"\033[96m./mach cargo-update -p {}:{}\033[0m" \
.format(name, version)
yield (line, message + error + suggest)
idx += 1
idx += 1
packages = {}
for package in content.get("package", []):
packages.setdefault(package["name"], []).append(package["version"])
for (name, versions) in packages.iteritems():
if name in exceptions or len(versions) <= 1:
continue
highest = max(versions)
for version in versions:
if version != highest:
reverse_dependencies = "\n".join(
"\t\t{}".format(n)
for n in find_reverse_dependencies(name, version, content)
)
substitutions = {
"package": name,
"old_version": version,
"new_version": highest,
"reverse_dependencies": reverse_dependencies
}
message = """
duplicate versions for package "{package}"
\t\033[93mfound dependency on version {old_version}\033[0m
\t\033[91mbut highest version is {new_version}\033[0m
\t\033[93mtry upgrading with\033[0m \033[96m./mach cargo-update -p {package}:{old_version}\033[0m
\tThe following packages depend on version {old_version}:
{reverse_dependencies}
""".format(**substitutions).strip()
yield (1, message)
def maybe_int(value):