# Copyright (C) 2024 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. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Action that verifies all EFI protocols used by GBL are explicitly listed in README.md """ load("@rules_rust//rust/private:providers.bzl", "CrateInfo") def _readme_test_rule_impl(ctx): shell_script = """ while [[ $# -gt 0 ]]; do case $1 in --in) INPUT=$2 shift shift ;; --out) OUTPUT=$2 shift shift ;; --readme) README=$2 shift shift ;; *) echo "Unexpected argument: $1" exit 1 ;; esac done if [ ! -f $README ]; then echo "README file doesn't exist: ${README}" exit 1 fi ALL_INPUTS=$(echo ${INPUT} | sed 's/,/ /g') # Look for protocols in the source code that do not exist in the documentation. # The protocol name we match on here is the Rust struct name. DOCLESS_PROTOCOLS="" PROTOCOLS=($(grep -hE 'impl ProtocolInfo for .* \\{' ${ALL_INPUTS} | awk '{print $4}' | sort)) for P in ${PROTOCOLS[@]} do grep -Lq $P ${README} || DOCLESS_PROTOCOLS+="\n\t$P" done if [ ! -z "${DOCLESS_PROTOCOLS}" ]; then echo -e "Missing documentation for protocol(s):$DOCLESS_PROTOCOLS" exit 1 fi # Look for protocols in the documentation that are not in the source, to try to # prevent stale docs referring to protocols we are no longer using. # Here we're matching on words ending in "Protocol", except "Protocol" itself. UNUSED_PROTOCOLS="" README_PROTOCOLS=($(grep -P " ?[^ ]+Protocol$" ${README} | awk '{print $NF}' | sort | uniq)) for P in ${README_PROTOCOLS[@]} do grep -qhE "impl ProtocolInfo for $P" ${ALL_INPUTS} || UNUSED_PROTOCOLS+="\n\t$P" done if [ ! -z "${UNUSED_PROTOCOLS}" ]; then echo -e "Unused protocol(s) found in documentation:$UNUSED_PROTOCOLS" exit 1 fi touch $OUTPUT """ out_file = ctx.actions.declare_file("%s.script" % ctx.attr.name) in_files = [s for d in ctx.attr.deps for s in d[CrateInfo].srcs.to_list()] readme = ctx.attr.readme args = ctx.actions.args() args.add_joined( "--in", in_files, join_with = ",", ) args.add( "--out", out_file, ) args.add( "--readme", readme[DefaultInfo].files.to_list()[0], ) ctx.actions.run_shell( inputs = in_files + readme[DefaultInfo].files.to_list(), outputs = [out_file], arguments = [args], command = shell_script, ) return [DefaultInfo(executable = out_file)] readme_test = rule( implementation = _readme_test_rule_impl, attrs = { "deps": attr.label_list( providers = [CrateInfo], ), "readme": attr.label( allow_single_file = [".md"], ), }, test = True, )