2022-04-20 04:45:06 +00:00
""" Implementation for yq rule """
2023-06-14 14:21:55 +00:00
load ( " //lib:stamping.bzl " , " STAMP_ATTRS " , " maybe_stamp " )
_yq_attrs = dict ( {
2022-04-20 04:45:06 +00:00
" srcs " : attr . label_list (
2023-08-30 16:18:10 +00:00
allow_files = True ,
2022-04-20 04:45:06 +00:00
mandatory = True ,
allow_empty = True ,
) ,
" expression " : attr . string ( mandatory = False ) ,
" args " : attr . string_list ( ) ,
" outs " : attr . output_list ( mandatory = True ) ,
2023-06-14 14:21:55 +00:00
" _parse_status_file_expression " : attr . label (
allow_single_file = True ,
default = Label ( " //lib/private:parse_status_file.yq " ) ,
) ,
} , * * STAMP_ATTRS )
2022-04-20 04:45:06 +00:00
def is_split_operation ( args ) :
for arg in args :
if arg . startswith ( " -s " ) or arg . startswith ( " --split-exp " ) :
return True
return False
def _escape_path ( path ) :
return " / " . join ( [ " .. " for t in path . split ( " / " ) ] ) + " / "
def _yq_impl ( ctx ) :
yq_bin = ctx . toolchains [ " @aspect_bazel_lib//lib:yq_toolchain_type " ] . yqinfo . bin
outs = ctx . outputs . outs
args = ctx . attr . args [ : ]
inputs = ctx . files . srcs [ : ]
split_operation = is_split_operation ( args )
if " eval " in args or " eval-all " in args :
fail ( " Do not pass ' eval ' or ' eval-all ' into yq; this is already set based on the number of srcs " )
if not split_operation and len ( outs ) > 1 :
fail ( " Cannot specify multiple outputs when -s or --split-exp is not set " )
if " -i " in args or " --inplace " in args :
fail ( " Cannot use arg -i or --inplace as it is not bazel-idiomatic to update the input file; consider using write_source_files to write back to the source tree " )
if len ( ctx . attr . srcs ) == 0 and " -n " not in args and " --null-input " not in args :
args = args + [ " --null-input " ]
2023-06-14 14:21:55 +00:00
stamp = maybe_stamp ( ctx )
stamp_yaml = ctx . actions . declare_file ( " _ %s _stamp.yaml " % ctx . label . name )
if stamp :
# create an action that gives a YAML representation of the stamp keys
ctx . actions . run_shell (
tools = [ yq_bin ] ,
inputs = [ stamp . stable_status_file , stamp . volatile_status_file , ctx . file . _parse_status_file_expression ] ,
outputs = [ stamp_yaml ] ,
command = " {yq} --from-file {expression} {stable} {volatile} > {out} " . format (
yq = yq_bin . path ,
expression = ctx . file . _parse_status_file_expression . path ,
stable = stamp . stable_status_file . path ,
volatile = stamp . volatile_status_file . path ,
out = stamp_yaml . path ,
) ,
mnemonic = " ConvertStatusToYaml " ,
2024-10-15 17:16:11 +00:00
toolchain = " @aspect_bazel_lib//lib:yq_toolchain_type " ,
2023-06-14 14:21:55 +00:00
)
else :
# create an empty stamp file as placeholder
ctx . actions . write (
output = stamp_yaml ,
content = " {} " ,
)
inputs . append ( stamp_yaml )
2022-04-20 04:45:06 +00:00
# For split operations, yq outputs files in the same directory so we
# must cd to the correct output dir before executing it
2022-05-02 22:41:06 +00:00
bin_dir = " / " . join ( [ ctx . bin_dir . path , ctx . label . package ] ) if ctx . label . package else ctx . bin_dir . path
2022-04-20 04:45:06 +00:00
escape_bin_dir = _escape_path ( bin_dir )
cmd = " cd {bin_dir} && {yq} {args} {eval_cmd} {expression} {sources} {maybe_out} " . format (
bin_dir = ctx . bin_dir . path + " / " + ctx . label . package ,
yq = escape_bin_dir + yq_bin . path ,
eval_cmd = " eval " if len ( inputs ) < = 1 else " eval-all " ,
args = " " . join ( args ) ,
expression = " ' %s ' " % ctx . attr . expression if ctx . attr . expression else " " ,
sources = " " . join ( [ " ' %s %s ' " % ( escape_bin_dir , file . path ) for file in ctx . files . srcs ] ) ,
# In the -s/--split-exr case, the out file names are determined by the yq expression
maybe_out = ( " > %s %s " % ( escape_bin_dir , outs [ 0 ] . path ) ) if len ( outs ) == 1 else " " ,
)
ctx . actions . run_shell (
tools = [ yq_bin ] ,
inputs = inputs ,
outputs = outs ,
command = cmd ,
2023-06-14 14:21:55 +00:00
env = { " STAMP " : escape_bin_dir + stamp_yaml . path } ,
2022-05-06 18:01:27 +00:00
mnemonic = " Yq " ,
2024-10-15 17:16:11 +00:00
toolchain = " @aspect_bazel_lib//lib:yq_toolchain_type " ,
2022-04-20 04:45:06 +00:00
)
return DefaultInfo ( files = depset ( outs ) , runfiles = ctx . runfiles ( outs ) )
yq_lib = struct (
attrs = _yq_attrs ,
implementation = _yq_impl ,
)