2
0
Fork 0
mirror of https://github.com/bazel-contrib/bazel-lib synced 2024-12-01 07:15:24 +00:00
bazel-lib/lib/private/jq.bzl
Mike Lundy dfcffca8f5
jq: add data file and location expansion support (#757)
This teaches the jq rule about a `data` attribute and adds conditional
support to do bazel location expansion. The expansion is disabled by
default because it likely would cause compat concerns (since jq can take
arbitrary text as input args).
2024-02-26 17:43:56 -08:00

102 lines
3.5 KiB
Python

"""Implementation for jq rule"""
load("//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp")
load(":expand_locations.bzl", "expand_locations")
_jq_attrs = dict({
"srcs": attr.label_list(
allow_files = True,
mandatory = True,
allow_empty = True,
),
"data": attr.label_list(
allow_files = True,
),
"filter": attr.string(),
"filter_file": attr.label(allow_single_file = True),
"args": attr.string_list(),
"expand_args": attr.bool(),
"out": attr.output(),
"_parse_status_file_filter": attr.label(
allow_single_file = True,
default = Label("//lib/private:parse_status_file.jq"),
),
}, **STAMP_ATTRS)
def _expand_locations(ctx, s):
# `.split(" ")` is a work-around https://github.com/bazelbuild/bazel/issues/10309
# TODO: If the string has intentional spaces or if one or more of the expanded file
# locations has a space in the name, we will incorrectly split it into multiple arguments
return expand_locations(ctx, s, targets = ctx.attr.data).split(" ")
def _jq_impl(ctx):
jq_bin = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"].jqinfo.bin
out = ctx.outputs.out or ctx.actions.declare_file(ctx.attr.name + ".json")
if ctx.attr.expand_args:
args = []
for a in ctx.attr.args:
args += _expand_locations(ctx, a)
else:
args = ctx.attr.args
inputs = ctx.files.srcs[:]
inputs += ctx.files.data
if not ctx.attr.filter and not ctx.attr.filter_file:
fail("Must provide a filter or a filter_file")
if ctx.attr.filter and ctx.attr.filter_file:
fail("Cannot provide both a filter and a filter_file")
# jq hangs when there are no input sources unless --null-input flag is passed
if len(ctx.attr.srcs) == 0 and "-n" not in args and "--null-input" not in args:
args = args + ["--null-input"]
if ctx.attr.filter_file:
args = args + ["--from-file '%s'" % ctx.file.filter_file.path]
inputs.append(ctx.file.filter_file)
stamp = maybe_stamp(ctx)
if stamp:
# create an action that gives a JSON representation of the stamp keys
stamp_json = ctx.actions.declare_file("_%s_stamp.json" % ctx.label.name)
ctx.actions.run_shell(
tools = [jq_bin],
inputs = [stamp.stable_status_file, stamp.volatile_status_file, ctx.file._parse_status_file_filter],
outputs = [stamp_json],
command = "{jq} -s -R -f {filter} {stable} {volatile} > {out}".format(
jq = jq_bin.path,
filter = ctx.file._parse_status_file_filter.path,
stable = stamp.stable_status_file.path,
volatile = stamp.volatile_status_file.path,
out = stamp_json.path,
),
mnemonic = "ConvertStatusToJson",
)
inputs.append(stamp_json)
args = args + ["--slurpfile", "STAMP", stamp_json.path]
cmd = "{jq} {args} {filter} {sources} > {out}".format(
jq = jq_bin.path,
args = " ".join(args),
filter = "'%s'" % ctx.attr.filter if ctx.attr.filter else "",
sources = " ".join(["'%s'" % file.path for file in ctx.files.srcs]),
out = out.path,
)
ctx.actions.run_shell(
tools = [jq_bin],
inputs = inputs,
outputs = [out],
command = cmd,
mnemonic = "Jq",
)
return DefaultInfo(files = depset([out]), runfiles = ctx.runfiles([out]))
jq_lib = struct(
attrs = _jq_attrs,
implementation = _jq_impl,
)