2
0
Fork 0
mirror of https://github.com/bazel-contrib/bazel-lib synced 2024-11-25 11:32:33 +00:00
bazel-lib/lib/private/tar.bzl
David Zbarsky 8fe4f6f8d5
Avoid expanding mtree spec during analysis phase (#576)
* Avoid expanding mtree spec during analysis phase

* Update tar.bzl

remove comment and unused code

---------

Co-authored-by: Alex Eagle <alex@aspect.dev>
2023-10-05 12:36:55 -07:00

138 lines
4.7 KiB
Python

"Implementation of tar rule"
_tar_attrs = {
"args": attr.string_list(
doc = "Additional flags permitted by BSD tar; see the man page.",
),
"srcs": attr.label_list(
doc = "Files and directories that are placed into the tar",
mandatory = True,
allow_files = True,
),
"mode": attr.string(
doc = """A mode indicator from the following list, copied from the tar manpage:
- create: Create a new archive containing the specified items.
- append: Like `create`, but new entries are appended to the archive.
Note that this only works on uncompressed archives stored in regular files.
The -f option is required.
- list: List archive contents to stdout.
- update: Like `append`, but new entries are added only if they have a
modification date newer than the corresponding entry in the archive.
Note that this only works on uncompressed archives stored in
regular files. The -f option is required.
- extract: Extract to disk from the archive. If a file with the same name
appears more than once in the archive, each copy will be extracted,
with later copies overwriting (replacing) earlier copies.
""",
values = ["create"], # TODO: support other modes: ["append", "list", "update", "extract"]
default = "create",
),
"mtree": attr.label(
doc = "An mtree specification file",
allow_single_file = True,
# Mandatory since it's the only way to set constant timestamps
mandatory = True,
),
"out": attr.output(
doc = "Resulting tar file to write. If absent, `[name].tar` is written.",
),
"compress": attr.string(
doc = "Compress the archive file with a supported algorithm.",
values = ["bzip2", "compress", "gzip", "lrzip", "lz4", "lzma", "lzop", "xz", "zstd"],
),
}
_mtree_attrs = {
"srcs": attr.label_list(doc = "Files that are placed into the tar", mandatory = True, allow_files = True),
"out": attr.output(doc = "Resulting specification file to write"),
}
def _add_compress_options(compress, args):
if compress == "bzip2":
args.add("--bzip2")
if compress == "compress":
args.add("--compress")
if compress == "gzip":
args.add("--gzip")
if compress == "lrzip":
args.add("--lrzip")
if compress == "lzma":
args.add("--lzma")
if compress == "lz4":
args.add("--lz4")
if compress == "lzop":
args.add("--lzop")
if compress == "xz":
args.add("--xz")
if compress == "zstd":
args.add("--zstd")
def _tar_impl(ctx):
bsdtar = ctx.toolchains["@aspect_bazel_lib//lib:tar_toolchain_type"]
inputs = ctx.files.srcs[:]
args = ctx.actions.args()
# Set mode
args.add(ctx.attr.mode, format = "--%s")
# User-provided args first
args.add_all(ctx.attr.args)
# Compression args
_add_compress_options(ctx.attr.compress, args)
out = ctx.outputs.out or ctx.actions.declare_file(ctx.attr.name + ".tar")
args.add("--file", out)
args.add(ctx.file.mtree, format = "@%s")
inputs.append(ctx.file.mtree)
ctx.actions.run(
executable = bsdtar.tarinfo.binary,
inputs = depset(direct = inputs, transitive = [bsdtar.default.files]),
outputs = [out],
arguments = [args],
mnemonic = "Tar",
)
return DefaultInfo(files = depset([out]), runfiles = ctx.runfiles([out]))
def _default_mtree_line(file):
# Functions passed to map_each cannot take optional arguments.
return _mtree_line(file)
def _mtree_line(file, uid = "0", gid = "0", time = "1672560000", mode = "0755"):
return " ".join([
file.short_path,
"uid=" + uid,
"gid=" + gid,
"time=" + time,
"mode=" + mode,
"type=" + ("dir" if file.is_directory else "file"),
"content=" + file.path,
])
def _mtree_impl(ctx):
out = ctx.outputs.out or ctx.actions.declare_file(ctx.attr.name + ".spec")
content = ctx.actions.args()
content.set_param_file_format("multiline")
content.add_all(ctx.files.srcs, map_each = _default_mtree_line)
ctx.actions.write(out, content = content)
return DefaultInfo(files = depset([out]), runfiles = ctx.runfiles([out]))
tar_lib = struct(
attrs = _tar_attrs,
implementation = _tar_impl,
mtree_attrs = _mtree_attrs,
mtree_implementation = _mtree_impl,
)
tar = rule(
doc = "Rule that executes BSD `tar`. Most users should use the [`tar`](#tar) macro, rather than load this directly.",
implementation = tar_lib.implementation,
attrs = tar_lib.attrs,
toolchains = ["@aspect_bazel_lib//lib:tar_toolchain_type"],
)