blob: 05f254690ae6ce0961d52b984e833904b64ed160 [file] [log] [blame]
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# 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.
# Rules for templating / files layout
def _expand_template_impl(ctx):
"""Simply spawn the template-engine in a rule."""
variables = [
"--variable=%s=%s" % (k, ctx.attr.substitutions[k])
for k in ctx.attr.substitutions
]
d = {str(ctx.attr.deps[i].label): ctx.files.deps[i].path
for i in range(0, len(ctx.attr.deps))}
imports = ["--imports=%s=%s" % (k, d[k]) for k in d]
imports += ["--imports=%s=%s" % (k, d[str(ctx.label.relative(ctx.attr.deps_aliases[k]))])
for k in ctx.attr.deps_aliases]
ctx.action(
executable = ctx.executable._engine,
arguments = [
"--executable" if ctx.attr.executable else "--noexecutable",
"--template=%s" % ctx.file.template.path,
"--output=%s" % ctx.outputs.out.path,
] + variables + imports,
inputs = [ctx.file.template] + ctx.files.deps,
outputs = [ctx.outputs.out],
)
expand_template = rule(
attrs = {
"template": attr.label(
mandatory = True,
allow_files = True,
single_file = True,
),
"deps": attr.label_list(default = [], allow_files = True),
"deps_aliases": attr.string_dict(default = {}),
"substitutions": attr.string_dict(mandatory = True),
"out": attr.output(mandatory = True),
"executable": attr.bool(default = True),
"_engine": attr.label(
default = Label("//templating:template_engine"),
executable = True,
cfg="host"),
},
implementation = _expand_template_impl,
)
"""Expand a jinja2 template file.
This rules expands the file given in template, into the file given by out.
Args:
template: The template file to expand.
deps: additional files to expand, they will be accessible as imports[label]
in the template environment. If a file ends with .tpl, it is considered
a template itself and will be expanded.
deps_aliases: a dictionary of name to label. Each label in that dictionary
should be present in the deps attribute, and will be make accessible as
imports[name] in the template environment.
substitutions: a dictionary of key => values that will appear as variables.key
in the template environment.
out: the name of the output file to generate.
executable: mark the result as excutable if set to True.
"""
def strip_prefix(path, prefixes):
for prefix in prefixes:
if path.startswith(prefix):
return path[len(prefix):]
return path
def strip_suffix(path, suffixes):
for suffix in suffixes:
if path.endswith(suffix):
return path[:-len(suffix)]
return path
def _dest_path(f, strip_prefixes, strip_suffixes):
"""Returns the short path of f, stripped of strip_prefixes and strip_suffixes."""
return strip_suffix(strip_prefix(f.short_path, strip_prefixes), strip_suffixes)
def _format_path(path_format, path):
dirsep = path.rfind("/")
dirname = path[:dirsep] if dirsep > 0 else ""
basename = path[dirsep+1:] if dirsep > 0 else path
extsep = basename.rfind(".")
extension = basename[extsep+1:] if extsep > 0 else ""
basename = basename[:extsep] if extsep > 0 else basename
return path_format.format(
path=path,
dirname=dirname,
basename=basename,
extension=extension
)
def _append_inputs(args, inputs, f, path, path_format):
args.append("--file=%s=%s" % (
f.path,
_format_path(path_format, path)
))
inputs.append(f)
def _merge_files_impl(ctx):
"""Merge a list of config files in a tar ball with the correct layout."""
output = ctx.outputs.out
build_tar = ctx.executable._build_tar
inputs = []
args = [
"--output=" + output.path,
"--directory=" + ctx.attr.directory,
"--mode=0644",
]
variables = [
"--variable=%s=%s" % (k, ctx.attr.substitutions[k])
for k in ctx.attr.substitutions
]
for f in ctx.files.srcs:
path = _dest_path(f, ctx.attr.strip_prefixes, ctx.attr.strip_suffixes)
if path.endswith(ctx.attr.template_extension):
path = path[:-4]
f2 = ctx.new_file(ctx.label.name + "/" + path)
ctx.action(
executable = ctx.executable._engine,
arguments = [
"--template=%s" % f.path,
"--output=%s" % f2.path,
"--noescape_xml",
] + variables,
inputs = [f],
outputs = [f2],
)
_append_inputs(args, inputs, f2, path, ctx.attr.path_format)
else:
_append_inputs(args, inputs, f, path, ctx.attr.path_format)
ctx.action(
executable = build_tar,
arguments = args,
inputs = inputs,
outputs = [output],
mnemonic="MergeFiles"
)
merge_files = rule(
attrs = {
"srcs": attr.label_list(allow_files=True),
"template_extension": attr.string(default=".tpl"),
"directory": attr.string(default="/"),
"strip_prefixes": attr.string_list(default=[]),
"strip_suffixes": attr.string_list(default=["-staging", "-test"]),
"substitutions": attr.string_dict(default={}),
"path_format": attr.string(default="{path}"),
"_build_tar": attr.label(
default=Label("@bazel_tools//tools/build_defs/pkg:build_tar"),
cfg="host",
executable=True,
allow_files=True),
"_engine": attr.label(
cfg="host",
default = Label("//templating:template_engine"),
executable = True),
},
outputs = {"out": "%{name}.tar"},
implementation = _merge_files_impl,
)
"""Merge a set of files in a single tarball.
This rule merge a set of files into one tarball, each file will appear in the
tarball as a file determined by path_format, strip_prefixes and directory.
Outputs:
<name>.tar: the tarball containing all the files in srcs.
Args:
srcs: The list of files to merge. If a file is ending with ".tpl" (see
template_extension), it will get expanded like a template passed to
expand_template.
template_extension: extension of files to be considered as template, ".tpl"
by default.
directory: base directory for all the files in the resulting tarball.
strip_prefixes: list of prefixes to strip from the path of the srcs to obtain
the final path (see path_format).
strip_suffixes: list of suffixes to strip from the path of the srcs to obtain
the final path (see path_format).
substitutions: map of substitutions to make available during template
expansion. Values of that map will be available as "variables.name" in
the template environment.
path_format: format of the final files. Each file will appear in the final
tarball under "{directory}/{path_format}" where the following string of
path_format are replaced:
{path}: path of the input file, removed from prefixes and suffixes,
{dirname}: directory name of path,
{basename}: base filename of path,
{extension}: extension of path
"""