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).
This commit is contained in:
parent
8906db5ced
commit
dfcffca8f5
|
@ -7,7 +7,7 @@ Public API for jq
|
|||
## jq
|
||||
|
||||
<pre>
|
||||
jq(<a href="#jq-name">name</a>, <a href="#jq-srcs">srcs</a>, <a href="#jq-filter">filter</a>, <a href="#jq-filter_file">filter_file</a>, <a href="#jq-args">args</a>, <a href="#jq-out">out</a>, <a href="#jq-kwargs">kwargs</a>)
|
||||
jq(<a href="#jq-name">name</a>, <a href="#jq-srcs">srcs</a>, <a href="#jq-filter">filter</a>, <a href="#jq-filter_file">filter_file</a>, <a href="#jq-args">args</a>, <a href="#jq-out">out</a>, <a href="#jq-data">data</a>, <a href="#jq-expand_args">expand_args</a>, <a href="#jq-kwargs">kwargs</a>)
|
||||
</pre>
|
||||
|
||||
Invoke jq with a filter on a set of json input files.
|
||||
|
@ -127,6 +127,8 @@ genrule(
|
|||
| <a id="jq-filter_file"></a>filter_file | File containing filter expression (alternative to <code>filter</code>) | <code>None</code> |
|
||||
| <a id="jq-args"></a>args | Additional args to pass to jq | <code>[]</code> |
|
||||
| <a id="jq-out"></a>out | Name of the output json file; defaults to the rule name plus ".json" | <code>None</code> |
|
||||
| <a id="jq-data"></a>data | List of additional files. May be empty. | <code>[]</code> |
|
||||
| <a id="jq-expand_args"></a>expand_args | Run bazel's location-expansion on the args. | <code>False</code> |
|
||||
| <a id="jq-kwargs"></a>kwargs | Other common named parameters such as <code>tags</code> or <code>visibility</code> | none |
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ _jq_rule = rule(
|
|||
toolchains = ["@aspect_bazel_lib//lib:jq_toolchain_type"],
|
||||
)
|
||||
|
||||
def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, **kwargs):
|
||||
def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, data = [], expand_args = False, **kwargs):
|
||||
"""Invoke jq with a filter on a set of json input files.
|
||||
|
||||
For jq documentation, see https://stedolan.github.io/jq/.
|
||||
|
@ -117,6 +117,7 @@ def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, **k
|
|||
Args:
|
||||
name: Name of the rule
|
||||
srcs: List of input files. May be empty.
|
||||
data: List of additional files. May be empty.
|
||||
filter: Filter expression (https://stedolan.github.io/jq/manual/#Basicfilters).
|
||||
Subject to stamp variable replacements, see [Stamping](./stamping.md).
|
||||
When stamping is enabled, a variable named "STAMP" will be available in the filter.
|
||||
|
@ -125,6 +126,7 @@ def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, **k
|
|||
|
||||
filter_file: File containing filter expression (alternative to `filter`)
|
||||
args: Additional args to pass to jq
|
||||
expand_args: Run bazel's location-expansion on the args.
|
||||
out: Name of the output json file; defaults to the rule name plus ".json"
|
||||
**kwargs: Other common named parameters such as `tags` or `visibility`
|
||||
"""
|
||||
|
@ -139,5 +141,7 @@ def jq(name, srcs, filter = None, filter_file = None, args = [], out = None, **k
|
|||
filter_file = filter_file,
|
||||
args = args,
|
||||
out = out,
|
||||
expand_args = expand_args,
|
||||
data = data,
|
||||
**kwargs
|
||||
)
|
||||
|
|
|
@ -159,7 +159,10 @@ bzl_library(
|
|||
name = "jq",
|
||||
srcs = ["jq.bzl"],
|
||||
visibility = ["//lib:__subpackages__"],
|
||||
deps = ["//lib:stamping"],
|
||||
deps = [
|
||||
":expand_locations",
|
||||
"//lib:stamping",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""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(
|
||||
|
@ -8,9 +9,13 @@ _jq_attrs = dict({
|
|||
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,
|
||||
|
@ -18,12 +23,25 @@ _jq_attrs = dict({
|
|||
),
|
||||
}, **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")
|
||||
args = ctx.attr.args
|
||||
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")
|
||||
|
|
|
@ -79,6 +79,26 @@ diff_test(
|
|||
file2 = "null.json",
|
||||
)
|
||||
|
||||
# Data files are passed in correctly
|
||||
jq(
|
||||
name = "case_data_input_flag",
|
||||
srcs = [],
|
||||
args = [
|
||||
"--slurpfile",
|
||||
"a",
|
||||
"$(location a_pretty.json)",
|
||||
],
|
||||
data = ["a_pretty.json"],
|
||||
expand_args = True,
|
||||
filter = "$a[0]",
|
||||
)
|
||||
|
||||
diff_test(
|
||||
name = "case_data_input_flag_test",
|
||||
file1 = ":case_data_input_flag",
|
||||
file2 = "a_pretty.json",
|
||||
)
|
||||
|
||||
# Load filter from file
|
||||
jq(
|
||||
name = "case_filter_file",
|
||||
|
|
Loading…
Reference in New Issue