mirror of
https://github.com/bazel-contrib/bazel-lib
synced 2024-12-01 07:15:24 +00:00
dfcffca8f5
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).
102 lines
3.5 KiB
Python
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,
|
|
)
|