github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/bazel/zip.bzl (about)

     1  # Copied from google/nomulus project as we don't want to import the whole repository.
     2  
     3  ZIPPER = "@bazel_tools//tools/zip:zipper"
     4  
     5  def long_path(ctx, file_):
     6      """Constructs canonical runfile path relative to TEST_SRCDIR.
     7      Args:
     8        ctx: A Skylark rule context.
     9        file_: A File object that should appear in the runfiles for the test.
    10      Returns:
    11        A string path relative to TEST_SRCDIR suitable for use in tests and
    12        testing infrastructure.
    13      """
    14      if file_.short_path.startswith("../"):
    15          return file_.short_path[3:]
    16      if file_.owner and file_.owner.workspace_root:
    17          return file_.owner.workspace_root + "/" + file_.short_path
    18      return ctx.workspace_name + "/" + file_.short_path
    19  
    20  def collect_runfiles(targets):
    21      """Aggregates runfiles from targets.
    22      Args:
    23        targets: A list of Bazel targets.
    24      Returns:
    25        A list of Bazel files.
    26      """
    27      data = depset()
    28      for target in targets:
    29          if hasattr(target, "runfiles"):
    30              data += target.runfiles.files
    31              continue
    32          if hasattr(target, "data_runfiles"):
    33              data += target.data_runfiles.files
    34          if hasattr(target, "default_runfiles"):
    35              data += target.default_runfiles.files
    36      return data
    37  
    38  def _get_runfiles(target, attribute):
    39      runfiles = getattr(target, attribute, None)
    40      if runfiles:
    41          return runfiles.files
    42      return []
    43  
    44  def _zip_file(ctx):
    45      """Implementation of zip_file() rule."""
    46      for s, d in ctx.attr.mappings.items():
    47          if (s.startswith("/") or s.endswith("/") or
    48              d.startswith("/") or d.endswith("/")):
    49              fail("mappings should not begin or end with slash")
    50      srcs = depset(transitive = [depset(ctx.files.srcs),depset(ctx.files.data),depset(collect_runfiles(ctx.attr.data))])
    51      mapped = _map_sources(ctx, srcs, ctx.attr.mappings)
    52      cmd = [
    53          "#!/bin/sh",
    54          "set -e",
    55          'repo="$(pwd)"',
    56          'zipper="${repo}/%s"' % ctx.file._zipper.path,
    57          'archive="${repo}/%s"' % ctx.outputs.out.path,
    58          'tmp="$(mktemp -d "${TMPDIR:-/tmp}/zip_file.XXXXXXXXXX")"',
    59          'cd "${tmp}"',
    60      ]
    61      cmd += [
    62          '"${zipper}" x "${repo}/%s"' % dep.zip_file.path
    63          for dep in ctx.attr.deps
    64      ]
    65      cmd += ["rm %s" % filename for filename in ctx.attr.exclude]
    66      cmd += [
    67          'mkdir -p "${tmp}/%s"' % zip_path
    68          for zip_path in depset(
    69              [
    70                  zip_path[:zip_path.rindex("/")]
    71                  for _, zip_path in mapped
    72                  if "/" in zip_path
    73              ],
    74          ).to_list()
    75      ]
    76      cmd += [
    77          'ln -sf "${repo}/%s" "${tmp}/%s"' % (path, zip_path)
    78          for path, zip_path in mapped
    79      ]
    80      cmd += [
    81          ("find . | sed 1d | cut -c 3- | LC_ALL=C sort" +
    82           ' | xargs "${zipper}" cC "${archive}"'),
    83          'cd "${repo}"',
    84          'rm -rf "${tmp}"',
    85      ]
    86      script = ctx.actions.declare_file("%s/%s.sh" % (ctx.bin_dir, ctx.label.name))
    87      ctx.actions.write(output = script, content = "\n".join(cmd), is_executable = True)
    88      inputs = [ctx.file._zipper]
    89      inputs += [dep.zip_file for dep in ctx.attr.deps]
    90      inputs += list(srcs.to_list())
    91      ctx.actions.run(
    92          inputs = inputs,
    93          outputs = [ctx.outputs.out],
    94          executable = script,
    95          mnemonic = "zip",
    96          progress_message = "Creating zip with %d inputs %s" % (
    97              len(inputs),
    98              ctx.label,
    99          ),
   100      )
   101      return struct(files = depset([ctx.outputs.out]), zip_file = ctx.outputs.out)
   102  
   103  def _map_sources(ctx, srcs, mappings):
   104      """Calculates paths in zip file for srcs."""
   105  
   106      # order mappings with more path components first
   107      mappings = sorted([
   108          (-len(source.split("/")), source, dest)
   109          for source, dest in mappings.items()
   110      ])
   111  
   112      # get rid of the integer part of tuple used for sorting
   113      mappings = [(source, dest) for _, source, dest in mappings]
   114      mappings_indexes = range(len(mappings))
   115      used = {i: False for i in mappings_indexes}
   116      mapped = []
   117      for file_ in srcs.to_list():
   118          run_path = long_path(ctx, file_)
   119          zip_path = None
   120          for i in mappings_indexes:
   121              source = mappings[i][0]
   122              dest = mappings[i][1]
   123              if not source:
   124                  if dest:
   125                      zip_path = dest + "/" + run_path
   126                  else:
   127                      zip_path = run_path
   128              elif source == run_path:
   129                  if dest:
   130                      zip_path = dest
   131                  else:
   132                      zip_path = run_path
   133              elif run_path.startswith(source + "/"):
   134                  if dest:
   135                      zip_path = dest + run_path[len(source):]
   136                  else:
   137                      zip_path = run_path[len(source) + 1:]
   138              else:
   139                  continue
   140              used[i] = True
   141              break
   142          if not zip_path:
   143              fail("no mapping matched: " + run_path)
   144          mapped += [(file_.path, zip_path)]
   145      for i in mappings_indexes:
   146          if not used[i]:
   147              fail('superfluous mapping: "%s" -> "%s"' % mappings[i])
   148      return mapped
   149  
   150  pkg_zip = rule(
   151      implementation = _zip_file,
   152      attrs = {
   153          "out": attr.output(mandatory = True),
   154          "srcs": attr.label_list(allow_files = True),
   155          "data": attr.label_list(allow_files = True),
   156          "deps": attr.label_list(providers = ["zip_file"]),
   157          "exclude": attr.string_list(),
   158          "mappings": attr.string_dict(),
   159          "_zipper": attr.label(default = Label(ZIPPER), allow_single_file = True),
   160      },
   161  )