Update pkg_war.bzl to match the version in Gerrit core In addition to the adaptations done, the support for the old package structure, i.e. directory structures started with `gerrit-` and not `java/`, has been removed. Change-Id: I229760ea46acab33dd97148f1bb2a9040322436b
diff --git a/tools/pkg_war.bzl b/tools/pkg_war.bzl index eaffc9b..0691ec2 100644 --- a/tools/pkg_war.bzl +++ b/tools/pkg_war.bzl
@@ -1,4 +1,4 @@ -# Copyright (C) 2017 The Android Open Source Project +# Copyright (C) 2016 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,27 +13,81 @@ # limitations under the License. # War packaging. + load("@rules_java//java:defs.bzl", "JavaInfo") +jar_filetype = [".jar"] + +# Special prefix added by rules_jvm_external.jvm_import() to stamped jars +# https://github.com/bazel-contrib/rules_jvm_external/blob/6.9/private/rules/jvm_import.bzl#L32 +PROCESSED_PREFIX = "processed_" + +def war_jar_name(f): + """Return the jar file name as it will appear inside the WAR.""" + raw = f.basename + if raw.startswith(PROCESSED_PREFIX): + raw = raw[len(PROCESSED_PREFIX):] + + sp = f.short_path + + # Rename ONLY caffeine's "guava" artifact (not Google Guava) + # Matches: .../com/github/ben-manes/caffeine/guava/<ver>/processed_guava-<ver>.jar + if "/com/github/ben-manes/caffeine/guava/" in sp and raw.startswith("guava-") and raw.endswith(".jar"): + raw = "caffeine-" + raw # -> caffeine-guava-<ver>.jar + + # Keep existing Gerrit naming rules + if sp.startswith("gerrit-"): + raw = sp.split("/")[0] + "-" + raw + elif sp.startswith("java/"): + raw = sp[5:].replace("/", "_") + + return raw + +def normalize_jar_id(jar_name): + """Version-agnostic jar identity used for allowlists/inventories.""" + n = jar_name + if n.endswith(".jar"): + n = n[:-4] + i = n.rfind("-") + + # Strip trailing "-<version-ish>" where the suffix begins with a digit. + if i > 0 and n[i + 1:i + 2].isdigit(): + n = n[:i] + return n + +def should_skip_packaged_jar(ctx, jar_name): + """jar_name must be the post-processed name (war_jar_name output).""" + for pfx in ctx.attr.exclude_jar_prefixes: + if jar_name.startswith(pfx): + return True + return False + +def is_third_party_jar_id(ctx, jar_id): + """Return True if jar_id should be tracked in third-party allowlists.""" + if jar_id in ctx.attr.exclude_third_party_jar: + return False + for pfx in ctx.attr.exclude_third_party_jar_prefix: + if jar_id.startswith(pfx): + return False + return True + def _add_context(in_file, output): - input_path = in_file.path return [ - "unzip -qd %s %s" % (output, input_path), + "unzip -qd %s %s" % (output, in_file.path), ] -def _add_file(name, in_file, output): - output_path = output - input_path = in_file.path - short_path = in_file.short_path - n = in_file.basename +def _add_jar_file(in_file, output): + raw = war_jar_name(in_file) + output_path = output + raw - if n != "web.xml" and short_path.startswith("%s-" % name): - n = short_path.split("/")[0] + "-" + n + return _add_file(in_file.path, output_path) - output_path = output_path + n +def _add_web_xml_file(in_file, output): + return _add_file(in_file.path, output + in_file.basename) +def _add_file(in_file, output): return [ - "test -L %s || ln -s $(pwd)/%s %s" % (output_path, input_path, output_path), + "test -L %s || ln -s $(pwd)/%s %s" % (output, in_file, output), ] def _make_war(input_dir, output): @@ -41,7 +95,7 @@ "root=$(pwd)", "cd %s" % input_dir, "find . -exec touch -t 198001010000 '{}' ';' 2> /dev/null", - "zip -9qr ${root}/%s ." % (output.path), + "zip -X -9qr ${root}/%s ." % (output.path), ]) def _war_impl(ctx): @@ -49,12 +103,25 @@ build_output = war.path + ".build_output" inputs = [] + # Metadata we expose for checks/tools. + jar_entries = [] + jar_ids = [] + + # Create war layout cmd = [ "set -e;rm -rf " + build_output, "mkdir -p " + build_output, "mkdir -p %s/WEB-INF/lib" % build_output, + "mkdir -p %s/WEB-INF/pgm-lib" % build_output, ] + # Add web.xml files + if ctx.attr.web_xml: + for web_xml in ctx.attr.web_xml.files.to_list(): + inputs.append(web_xml) + cmd = cmd + _add_web_xml_file(web_xml, build_output + "/WEB-INF/") + + # Add runtime libs transitive_libs = [] for l in ctx.attr.libs: if JavaInfo in l: @@ -62,16 +129,41 @@ elif hasattr(l, "files"): transitive_libs.append(l.files) - transitive_lib_deps = depset(transitive = transitive_libs) - for dep in transitive_lib_deps.to_list(): - cmd = cmd + _add_file(ctx.attr.name, dep, build_output + "/WEB-INF/lib/") + for dep in depset(transitive = transitive_libs).to_list(): + packaged = war_jar_name(dep) + if should_skip_packaged_jar(ctx, packaged): + continue + + cmd += _add_jar_file(dep, build_output + "/WEB-INF/lib/") inputs.append(dep) - if ctx.attr.web_xml: - for web_xml in ctx.attr.web_xml.files.to_list(): - inputs.append(web_xml) - cmd = cmd + _add_file(ctx.attr.name, web_xml, build_output + "/WEB-INF/") + jar_entries.append("WEB-INF/lib/" + packaged) + jid = normalize_jar_id(packaged) + if is_third_party_jar_id(ctx,jid): + jar_ids.append(jid) + + # Add pgm libs + transitive_pgmlibs = [] + for l in ctx.attr.pgmlibs: + transitive_pgmlibs.append(l[JavaInfo].transitive_runtime_jars) + + for dep in depset(transitive = transitive_pgmlibs).to_list(): + packaged = war_jar_name(dep) + if should_skip_packaged_jar(ctx, packaged): + continue + + if dep not in inputs: + cmd += _add_jar_file(dep, build_output + "/WEB-INF/pgm-lib/") + inputs.append(dep) + + jar_entries.append("WEB-INF/pgm-lib/" + packaged) + + jid = normalize_jar_id(packaged) + if is_third_party_jar_id(ctx, jid): + jar_ids.append(jid) + + # Add context transitive_context_libs = [] if ctx.attr.context: for jar in ctx.attr.context: @@ -79,11 +171,25 @@ transitive_context_libs.append(jar[JavaInfo].transitive_runtime_jars) elif hasattr(jar, "files"): transitive_context_libs.append(jar.files) - transitive_context_deps = depset(transitive = transitive_context_libs) - for dep in transitive_context_deps.to_list(): - cmd = cmd + _add_context(dep, build_output) + + for dep in depset(transitive = transitive_context_libs).to_list(): + cmd += _add_context(dep, build_output) inputs.append(dep) + # Write deterministic manifests for checks. + # + # NOTE: The manifests are produced as independent actions. + # Bazel will only execute the actions needed for the requested output, + # so building *.war.entries.txt does not materialize the WAR. + ctx.actions.write( + output = ctx.outputs.jars, + content = "\n".join(sorted(depset(jar_ids).to_list())) + "\n", + ) + ctx.actions.write( + output = ctx.outputs.entries, + content = "\n".join(sorted(jar_entries)) + "\n", + ) + # Add zip war cmd.append(_make_war(build_output, war)) @@ -95,16 +201,29 @@ use_default_shell_env = True, ) + return [ + DefaultInfo(files = depset([war, ctx.outputs.jars, ctx.outputs.entries])), + ] + # context: go to the root directory # libs: go to the WEB-INF/lib directory +# pgmlibs: go to the WEB-INF/pgm-lib directory # web_xml: go to the WEB-INF directory _pkg_war = rule( attrs = { "context": attr.label_list(allow_files = True), - "libs": attr.label_list(allow_files = [".jar"]), + "libs": attr.label_list(allow_files = jar_filetype), + "pgmlibs": attr.label_list(allow_files = False), "web_xml": attr.label(allow_files = True), + "exclude_jar_prefixes": attr.string_list(), + "exclude_third_party_jar": attr.string_list(), + "exclude_third_party_jar_prefix": attr.string_list(), }, - outputs = {"war": "%{name}.war"}, + outputs = { + "war": "%{name}.war", + "jars": "%{name}.war.jars.txt", + "entries": "%{name}.war.entries.txt", + }, implementation = _war_impl, )