Skip to content

Commit 50b2011

Browse files
authored
Added non-conflicting hash for install files (#1454)
1 parent 2509468 commit 50b2011

21 files changed

Lines changed: 1107 additions & 111 deletions

BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ exports_files([
66
"defs.bzl",
77
"extensions.bzl",
88
"specs.bzl",
9+
"maven_install.json",
910
])
1011

1112
licenses(["notice"]) # Apache 2.0

maven_install.json

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,36 @@
11
{
22
"__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
3-
"__INPUT_ARTIFACTS_HASH": 1827703030,
4-
"__RESOLVED_ARTIFACTS_HASH": -1607032127,
3+
"__INPUT_ARTIFACTS_HASH": {
4+
"com.google.code.gson:gson": -1146526807,
5+
"com.google.errorprone:error_prone_annotations": -571311395,
6+
"com.google.guava:guava": -1756621521,
7+
"com.google.protobuf:protobuf-java": -154599721,
8+
"com.google.protobuf:protobuf-java-util": -1033086717,
9+
"io.netty:netty-tcnative-boringssl-static": -1979050407,
10+
"org.hamcrest:hamcrest-core": 466791695,
11+
"repositories": -1949687017
12+
},
13+
"__RESOLVED_ARTIFACTS_HASH": {
14+
"com.google.code.findbugs:jsr305": 870839855,
15+
"com.google.code.gson:gson": 50257904,
16+
"com.google.errorprone:error_prone_annotations": 1527418394,
17+
"com.google.guava:failureaccess": 1715931538,
18+
"com.google.guava:guava": -1587873388,
19+
"com.google.guava:listenablefuture": 1079558157,
20+
"com.google.j2objc:j2objc-annotations": -1008747351,
21+
"com.google.protobuf:protobuf-java": 657144169,
22+
"com.google.protobuf:protobuf-java-util": 291568724,
23+
"io.netty:netty-tcnative-boringssl-static": 786460467,
24+
"io.netty:netty-tcnative-boringssl-static:jar:linux-aarch_64": -151974322,
25+
"io.netty:netty-tcnative-boringssl-static:jar:linux-x86_64": -1831640381,
26+
"io.netty:netty-tcnative-boringssl-static:jar:osx-aarch_64": -1661340718,
27+
"io.netty:netty-tcnative-boringssl-static:jar:osx-x86_64": 2101324017,
28+
"io.netty:netty-tcnative-boringssl-static:jar:windows-x86_64": 889950966,
29+
"io.netty:netty-tcnative-classes": 1239547355,
30+
"org.hamcrest:hamcrest": -533823501,
31+
"org.hamcrest:hamcrest-core": 511008887,
32+
"org.jspecify:jspecify": 117231129
33+
},
534
"conflict_resolution": {
635
"com.google.errorprone:error_prone_annotations:2.23.0": "com.google.errorprone:error_prone_annotations:2.41.0"
736
},
@@ -260,5 +289,5 @@
260289
]
261290
},
262291
"services": {},
263-
"version": "2"
292+
"version": "3"
264293
}

private/extensions/maven.bzl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ load("//private/rules:coursier.bzl", "DEFAULT_AAR_IMPORT_LABEL", "coursier_fetch
1414
load("//private/rules:maven_version.bzl", "compare_maven_versions")
1515
load("//private/rules:unpinned_maven_pin_command_alias.bzl", "unpinned_maven_pin_command_alias")
1616
load("//private/rules:v1_lock_file.bzl", "v1_lock_file")
17-
load("//private/rules:v2_lock_file.bzl", "v2_lock_file")
17+
load("//private/rules:v3_lock_file.bzl", "v2_lock_file", "v3_lock_file")
1818
load(":download_pinned_deps.bzl", "download_pinned_deps")
1919

2020
DEFAULT_REPOSITORIES = [
@@ -755,12 +755,15 @@ def maven_impl(mctx):
755755
"artifacts": {},
756756
"dependencies": {},
757757
"repositories": {},
758-
"version": "2",
758+
"version": "3",
759759
}
760760
else:
761761
lock_file = json.decode(lock_file_content)
762762

763-
if v2_lock_file.is_valid_lock_file(lock_file):
763+
if v3_lock_file.is_valid_lock_file(lock_file):
764+
artifacts = v3_lock_file.get_artifacts(lock_file)
765+
importer = v3_lock_file
766+
elif v2_lock_file.is_valid_lock_file(lock_file):
764767
artifacts = v2_lock_file.get_artifacts(lock_file)
765768
importer = v2_lock_file
766769
elif v1_lock_file.is_valid_lock_file(lock_file):

private/rules/coursier.bzl

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ load(
3333
load("//private/lib:coordinates.bzl", "to_key", "unpack_coordinates")
3434
load("//private/lib:urls.bzl", "remove_auth_from_url")
3535
load("//private/rules:v1_lock_file.bzl", "v1_lock_file")
36-
load("//private/rules:v2_lock_file.bzl", "v2_lock_file")
36+
load("//private/rules:v3_lock_file.bzl", "v2_lock_file", "v3_lock_file")
3737

3838
_BUILD = """
3939
# package(default_visibility = [{visibilities}]) # https://github.com/bazelbuild/bazel/issues/13681
@@ -341,6 +341,13 @@ def _stable_artifact(artifact):
341341
keys = sorted(parsed.keys())
342342
return ":".join(["%s=%s" % (key, parsed[key]) for key in keys])
343343

344+
def _add_to_hash_dictionary(dictionary, artifact, salt):
345+
artifact_dict = json.decode(artifact)
346+
key = artifact_dict["group"] + ":" + artifact_dict["artifact"]
347+
value = dictionary.get(key, [])
348+
value.append(hash(_stable_artifact(artifact) + salt))
349+
dictionary[key] = value
350+
344351
# Compute a signature of the list of artifacts that will be used to build
345352
# the dependency tree. This is used as a check to see whether the dependency
346353
# tree needs to be repinned.
@@ -359,24 +366,37 @@ def compute_dependency_inputs_signature(boms = [], artifacts = [], repositories
359366
artifact_inputs = []
360367
excluded_artifact_inputs = []
361368

369+
all_hashes = dict()
370+
362371
if boms and len(boms):
363372
for bom in sorted(boms):
364373
artifact_inputs.append(_stable_artifact(bom))
374+
_add_to_hash_dictionary(all_hashes, bom, "bom")
365375

366376
for artifact in sorted(artifacts):
367377
artifact_inputs.append(_stable_artifact(artifact))
378+
_add_to_hash_dictionary(all_hashes, artifact, "artifact")
368379

369380
for artifact in sorted(excluded_artifacts):
370381
excluded_artifact_inputs.append(_stable_artifact(artifact))
382+
_add_to_hash_dictionary(all_hashes, artifact, "excluded_artifact")
371383

372384
v1_sig = hash(repr(sorted(artifact_inputs))) ^ hash(repr(sorted(repositories)))
373385

374386
hash_parts = [sorted(artifact_inputs), sorted(repositories), sorted(excluded_artifact_inputs)]
375-
current_version_sig = 0
387+
v2_sig = 0
376388
for part in hash_parts:
377-
current_version_sig ^= hash(repr(part))
389+
v2_sig ^= hash(repr(part))
390+
391+
for k, v in all_hashes.items():
392+
if len(v) == 1:
393+
all_hashes[k] = v[0]
394+
else:
395+
all_hashes[k] = hash(repr(sorted(v)))
378396

379-
return (current_version_sig, [v1_sig])
397+
all_hashes["repositories"] = hash(repr(sorted(repositories)))
398+
399+
return (all_hashes, [v1_sig, v2_sig])
380400

381401
def get_netrc_lines_from_entries(netrc_entries):
382402
netrc_lines = []
@@ -540,21 +560,26 @@ def _pinned_coursier_fetch_impl(repository_ctx):
540560
"artifacts": {},
541561
"dependencies": {},
542562
"repositories": {},
543-
"version": "2",
563+
"version": "3",
544564
}
545565
else:
546566
maven_install_json_content = json.decode(lock_file_content)
547567

548-
if v1_lock_file.is_valid_lock_file(maven_install_json_content):
568+
if v3_lock_file.is_valid_lock_file(maven_install_json_content):
569+
importer = v3_lock_file
570+
elif v2_lock_file.is_valid_lock_file(maven_install_json_content):
571+
importer = v2_lock_file
572+
elif v1_lock_file.is_valid_lock_file(maven_install_json_content):
549573
importer = v1_lock_file
574+
else:
575+
fail("Unable to read lock file: %s" % repository_ctx.attr.maven_install_json)
576+
577+
# Check if using the most recent lock file format.
578+
if importer != v3_lock_file:
550579
print_if_not_repinning(
551580
repository_ctx,
552581
"Lock file should be updated. Please run `REPIN=1 bazel run @unpinned_%s//:pin`" % repository_ctx.name,
553582
)
554-
elif v2_lock_file.is_valid_lock_file(maven_install_json_content):
555-
importer = v2_lock_file
556-
else:
557-
fail("Unable to read lock file: %s" % repository_ctx.attr.maven_install_json)
558583

559584
# Validation steps for maven_install.json.
560585

@@ -612,10 +637,10 @@ def _pinned_coursier_fetch_impl(repository_ctx):
612637
)
613638
elif computed_artifacts_hash != input_artifacts_hash:
614639
if _get_fail_if_repin_required(repository_ctx):
615-
fail("%s_install.json contains an invalid input signature (expected %s and got %s) and must be regenerated. " % (
640+
to_print = importer.print_friendly_hash_difference(input_artifacts_hash, computed_artifacts_hash)
641+
fail("%s_install.json contains an invalid input signature (%s) and must be regenerated. " % (
616642
user_provided_name,
617-
input_artifacts_hash,
618-
computed_artifacts_hash,
643+
to_print,
619644
) +
620645
"This typically happens when the maven_install artifacts have been changed but not repinned. " +
621646
"PLEASE DO NOT MODIFY THIS FILE DIRECTLY! To generate a new " +
@@ -641,11 +666,12 @@ def _pinned_coursier_fetch_impl(repository_ctx):
641666
# Then, validate that the signature provided matches the contents of the dependency_tree.
642667
# This is to stop users from manually modifying maven_install.json.
643668
if _get_fail_if_repin_required(repository_ctx):
669+
computed_hash = importer.compute_lock_file_hash(maven_install_json_content)
670+
to_print = importer.print_friendly_hash_difference(dep_tree_signature, computed_hash)
644671
fail(
645-
"%s_install.json contains an invalid signature (expected %s and got %s) and may be corrupted. " % (
672+
"%s_install.json contains an invalid signature (%s) and may be corrupted. " % (
646673
user_provided_name,
647-
dep_tree_signature,
648-
importer.compute_lock_file_hash(maven_install_json_content),
674+
to_print,
649675
) +
650676
"PLEASE DO NOT MODIFY THIS FILE DIRECTLY! To generate a new " +
651677
"%s_install.json and re-pin the artifacts, follow these steps: \n\n" % user_provided_name +
@@ -1415,7 +1441,7 @@ def _coursier_fetch_impl(repository_ctx):
14151441

14161442
repository_ctx.file(
14171443
"unsorted_deps.json",
1418-
content = v2_lock_file.render_lock_file(
1444+
content = v3_lock_file.render_lock_file(
14191445
lock_file_contents,
14201446
inputs_hash,
14211447
),
@@ -1424,7 +1450,7 @@ def _coursier_fetch_impl(repository_ctx):
14241450
repository_ctx.report_progress("Generating BUILD targets..")
14251451
(generated_imports, jar_versionless_target_labels) = parser.generate_imports(
14261452
repository_ctx = repository_ctx,
1427-
dependencies = v2_lock_file.get_artifacts(lock_file_contents),
1453+
dependencies = v3_lock_file.get_artifacts(lock_file_contents),
14281454
explicit_artifacts = {
14291455
a["group"] + ":" + a["artifact"] + (":" + a["classifier"] if "classifier" in a else ""): True
14301456
for a in artifacts

private/rules/pin_dependencies.bzl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ load("//private/rules:coursier.bzl", "compute_dependency_inputs_signature")
1515

1616
_TEMPLATE = """#!/usr/bin/env bash
1717
18-
{resolver_cmd} --jvm_flags={jvm_flags} --argsfile {config} --input_hash '{input_hash}' --output {output}{dependency_index_output}
18+
{resolver_cmd} --jvm_flags={jvm_flags} --argsfile {config} --input-hash-path '{input_hash_path}' --output {output}{dependency_index_output}
1919
"""
2020

2121
def _stringify_exclusions(exclusions):
@@ -63,13 +63,19 @@ def _pin_dependencies_impl(ctx):
6363
content = json.encode_indent(config, indent = " "),
6464
)
6565

66-
input_hash = compute_dependency_inputs_signature(
66+
input_hash, _ = compute_dependency_inputs_signature(
6767
boms = ctx.attr.boms,
6868
artifacts = ctx.attr.artifacts,
6969
repositories = ctx.attr.repositories,
7070
excluded_artifacts = ctx.attr.excluded_artifacts,
7171
)
7272

73+
hash_file = ctx.actions.declare_file("%s-input-hash.json" % ctx.label.name)
74+
ctx.actions.write(
75+
hash_file,
76+
content = json.encode_indent(input_hash, indent = " "),
77+
)
78+
7379
dependency_index_output = ""
7480
if ctx.attr.dependency_index:
7581
dependency_index_output = " --dependency-index-output $BUILD_WORKSPACE_DIRECTORY/" + ctx.attr.dependency_index
@@ -79,7 +85,7 @@ def _pin_dependencies_impl(ctx):
7985
script,
8086
_TEMPLATE.format(
8187
config = config_file.short_path,
82-
input_hash = input_hash[0],
88+
input_hash_path = hash_file.short_path,
8389
resolver_cmd = ctx.executable.resolver.short_path,
8490
output = "$BUILD_WORKSPACE_DIRECTORY/" + ctx.attr.lock_file,
8591
dependency_index_output = dependency_index_output,
@@ -92,7 +98,7 @@ def _pin_dependencies_impl(ctx):
9298
DefaultInfo(
9399
executable = script,
94100
files = depset([script, config_file]),
95-
runfiles = ctx.runfiles(files = [script, config_file]).merge(ctx.attr.resolver[DefaultInfo].default_runfiles),
101+
runfiles = ctx.runfiles(files = [script, config_file, hash_file]).merge(ctx.attr.resolver[DefaultInfo].default_runfiles),
96102
),
97103
]
98104

private/rules/v1_lock_file.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def _get_lock_file_hash(lock_file_contents):
4242
dep_tree = lock_file_contents.get("dependency_tree", {})
4343
return dep_tree.get("__RESOLVED_ARTIFACTS_HASH")
4444

45+
def _print_friendly_hash_difference(old_hash, new_hash):
46+
if old_hash == new_hash:
47+
return ""
48+
return "expected %s and got %s" % (old_hash, new_hash)
49+
4550
# The representation of a Windows path when read from the parsed Coursier JSON
4651
# is delimited by 4 back slashes. Replace them with 1 forward slash.
4752
def _normalize_to_unix_path(path):
@@ -138,6 +143,7 @@ v1_lock_file = struct(
138143
is_valid_lock_file = _is_valid_lock_file,
139144
get_input_artifacts_hash = _get_input_artifacts_hash,
140145
get_lock_file_hash = _get_lock_file_hash,
146+
print_friendly_hash_difference = _print_friendly_hash_difference,
141147
compute_lock_file_hash = _compute_lock_file_hash,
142148
get_artifacts = _get_artifacts,
143149
get_netrc_entries = _get_netrc_entries,

0 commit comments

Comments
 (0)