mirror of https://github.com/v2ray/v2ray-core
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.4 KiB
162 lines
5.4 KiB
# Copied from google/nomulus project as we don't want to import the whole repository.
|
|
|
|
ZIPPER = "@bazel_tools//tools/zip:zipper"
|
|
|
|
def long_path(ctx, file_):
|
|
"""Constructs canonical runfile path relative to TEST_SRCDIR.
|
|
Args:
|
|
ctx: A Skylark rule context.
|
|
file_: A File object that should appear in the runfiles for the test.
|
|
Returns:
|
|
A string path relative to TEST_SRCDIR suitable for use in tests and
|
|
testing infrastructure.
|
|
"""
|
|
if file_.short_path.startswith("../"):
|
|
return file_.short_path[3:]
|
|
if file_.owner and file_.owner.workspace_root:
|
|
return file_.owner.workspace_root + "/" + file_.short_path
|
|
return ctx.workspace_name + "/" + file_.short_path
|
|
|
|
def collect_runfiles(targets):
|
|
"""Aggregates runfiles from targets.
|
|
Args:
|
|
targets: A list of Bazel targets.
|
|
Returns:
|
|
A list of Bazel files.
|
|
"""
|
|
data = depset()
|
|
for target in targets:
|
|
if hasattr(target, "runfiles"):
|
|
data += target.runfiles.files
|
|
continue
|
|
if hasattr(target, "data_runfiles"):
|
|
data += target.data_runfiles.files
|
|
if hasattr(target, "default_runfiles"):
|
|
data += target.default_runfiles.files
|
|
return data
|
|
|
|
def _get_runfiles(target, attribute):
|
|
runfiles = getattr(target, attribute, None)
|
|
if runfiles:
|
|
return runfiles.files
|
|
return []
|
|
|
|
def _zip_file(ctx):
|
|
"""Implementation of zip_file() rule."""
|
|
for s, d in ctx.attr.mappings.items():
|
|
if (s.startswith("/") or s.endswith("/") or
|
|
d.startswith("/") or d.endswith("/")):
|
|
fail("mappings should not begin or end with slash")
|
|
srcs = depset(transitive = [depset(ctx.files.srcs),depset(ctx.files.data),depset(collect_runfiles(ctx.attr.data))])
|
|
mapped = _map_sources(ctx, srcs, ctx.attr.mappings)
|
|
cmd = [
|
|
"#!/bin/sh",
|
|
"set -e",
|
|
'repo="$(pwd)"',
|
|
'zipper="${repo}/%s"' % ctx.file._zipper.path,
|
|
'archive="${repo}/%s"' % ctx.outputs.out.path,
|
|
'tmp="$(mktemp -d "${TMPDIR:-/tmp}/zip_file.XXXXXXXXXX")"',
|
|
'cd "${tmp}"',
|
|
]
|
|
cmd += [
|
|
'"${zipper}" x "${repo}/%s"' % dep.zip_file.path
|
|
for dep in ctx.attr.deps
|
|
]
|
|
cmd += ["rm %s" % filename for filename in ctx.attr.exclude]
|
|
cmd += [
|
|
'mkdir -p "${tmp}/%s"' % zip_path
|
|
for zip_path in depset(
|
|
[
|
|
zip_path[:zip_path.rindex("/")]
|
|
for _, zip_path in mapped
|
|
if "/" in zip_path
|
|
],
|
|
).to_list()
|
|
]
|
|
cmd += [
|
|
'ln -sf "${repo}/%s" "${tmp}/%s"' % (path, zip_path)
|
|
for path, zip_path in mapped
|
|
]
|
|
cmd += [
|
|
("find . | sed 1d | cut -c 3- | LC_ALL=C sort" +
|
|
' | xargs "${zipper}" cC "${archive}"'),
|
|
'cd "${repo}"',
|
|
'rm -rf "${tmp}"',
|
|
]
|
|
script = ctx.actions.declare_file("%s/%s.sh" % (ctx.bin_dir, ctx.label.name))
|
|
ctx.actions.write(output = script, content = "\n".join(cmd), is_executable = True)
|
|
inputs = [ctx.file._zipper]
|
|
inputs += [dep.zip_file for dep in ctx.attr.deps]
|
|
inputs += list(srcs.to_list())
|
|
ctx.actions.run(
|
|
inputs = inputs,
|
|
outputs = [ctx.outputs.out],
|
|
executable = script,
|
|
mnemonic = "zip",
|
|
progress_message = "Creating zip with %d inputs %s" % (
|
|
len(inputs),
|
|
ctx.label,
|
|
),
|
|
)
|
|
return struct(files = depset([ctx.outputs.out]), zip_file = ctx.outputs.out)
|
|
|
|
def _map_sources(ctx, srcs, mappings):
|
|
"""Calculates paths in zip file for srcs."""
|
|
|
|
# order mappings with more path components first
|
|
mappings = sorted([
|
|
(-len(source.split("/")), source, dest)
|
|
for source, dest in mappings.items()
|
|
])
|
|
|
|
# get rid of the integer part of tuple used for sorting
|
|
mappings = [(source, dest) for _, source, dest in mappings]
|
|
mappings_indexes = range(len(mappings))
|
|
used = {i: False for i in mappings_indexes}
|
|
mapped = []
|
|
for file_ in srcs.to_list():
|
|
run_path = long_path(ctx, file_)
|
|
zip_path = None
|
|
for i in mappings_indexes:
|
|
source = mappings[i][0]
|
|
dest = mappings[i][1]
|
|
if not source:
|
|
if dest:
|
|
zip_path = dest + "/" + run_path
|
|
else:
|
|
zip_path = run_path
|
|
elif source == run_path:
|
|
if dest:
|
|
zip_path = dest
|
|
else:
|
|
zip_path = run_path
|
|
elif run_path.startswith(source + "/"):
|
|
if dest:
|
|
zip_path = dest + run_path[len(source):]
|
|
else:
|
|
zip_path = run_path[len(source) + 1:]
|
|
else:
|
|
continue
|
|
used[i] = True
|
|
break
|
|
if not zip_path:
|
|
fail("no mapping matched: " + run_path)
|
|
mapped += [(file_.path, zip_path)]
|
|
for i in mappings_indexes:
|
|
if not used[i]:
|
|
fail('superfluous mapping: "%s" -> "%s"' % mappings[i])
|
|
return mapped
|
|
|
|
pkg_zip = rule(
|
|
implementation = _zip_file,
|
|
attrs = {
|
|
"out": attr.output(mandatory = True),
|
|
"srcs": attr.label_list(allow_files = True),
|
|
"data": attr.label_list(allow_files = True),
|
|
"deps": attr.label_list(providers = ["zip_file"]),
|
|
"exclude": attr.string_list(),
|
|
"mappings": attr.string_dict(),
|
|
"_zipper": attr.label(default = Label(ZIPPER), allow_single_file = True),
|
|
},
|
|
)
|