Squashed 'third_party/rules_rust/' content from commit bf59038ca

git-subtree-dir: third_party/rules_rust
git-subtree-split: bf59038cac11798cbaef9f3bf965bad8182b97fa
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I5a20e403203d670df467ea97dde9a4ac40339a8d
diff --git a/crate_universe/private/bootstrap_utils.bzl b/crate_universe/private/bootstrap_utils.bzl
new file mode 100644
index 0000000..9df387e
--- /dev/null
+++ b/crate_universe/private/bootstrap_utils.bzl
@@ -0,0 +1,106 @@
+"""Utilities directly related to bootstrapping `cargo-bazel`"""
+
+_SRCS_TEMPLATE = """\
+\"\"\"A generate file containing all source files used to produce `cargo-bazel`\"\"\"
+
+# Each source file is tracked as a target so the `cargo_bootstrap_repository`
+# rule will know to automatically rebuild if any of the sources changed.
+CARGO_BAZEL_SRCS = [
+    {srcs}
+]
+"""
+
+def _srcs_module_impl(ctx):
+    srcs = ["@rules_rust{}".format(src.owner) for src in ctx.files.srcs]
+    if not srcs:
+        fail("`srcs` cannot be empty")
+    output = ctx.actions.declare_file(ctx.label.name)
+
+    ctx.actions.write(
+        output = output,
+        content = _SRCS_TEMPLATE.format(
+            srcs = "\n    ".join(["\"{}\",".format(src) for src in srcs]),
+        ),
+    )
+
+    return DefaultInfo(
+        files = depset([output]),
+    )
+
+_srcs_module = rule(
+    doc = "A rule for writing a list of sources to a templated file",
+    implementation = _srcs_module_impl,
+    attrs = {
+        "srcs": attr.label(
+            doc = "A filegroup of source files",
+            allow_files = True,
+        ),
+    },
+)
+
+_INSTALLER_TEMPLATE = """\
+#!/bin/bash
+set -euo pipefail
+cp -f "{path}" "${{BUILD_WORKSPACE_DIRECTORY}}/{dest}"
+"""
+
+def _srcs_installer_impl(ctx):
+    output = ctx.actions.declare_file(ctx.label.name + ".sh")
+    target_file = ctx.file.input
+    dest = ctx.file.dest.short_path
+
+    ctx.actions.write(
+        output = output,
+        content = _INSTALLER_TEMPLATE.format(
+            path = target_file.short_path,
+            dest = dest,
+        ),
+        is_executable = True,
+    )
+
+    return DefaultInfo(
+        files = depset([output]),
+        runfiles = ctx.runfiles(files = [target_file]),
+        executable = output,
+    )
+
+_srcs_installer = rule(
+    doc = "A rule for writing a file back to the repository",
+    implementation = _srcs_installer_impl,
+    attrs = {
+        "dest": attr.label(
+            doc = "the file name to use for installation",
+            allow_single_file = True,
+            mandatory = True,
+        ),
+        "input": attr.label(
+            doc = "The file to write back to the repository",
+            allow_single_file = True,
+            mandatory = True,
+        ),
+    },
+    executable = True,
+)
+
+def srcs_module(name, dest, **kwargs):
+    """A helper rule to ensure the bootstrapping functionality of `cargo-bazel` is always up to date
+
+    Args:
+        name (str): The name of the sources module
+        dest (str): The filename the module should be written as in the current package.
+        **kwargs (dict): Additional keyword arguments
+    """
+    tags = kwargs.pop("tags", [])
+
+    _srcs_module(
+        name = name,
+        tags = tags,
+        **kwargs
+    )
+
+    _srcs_installer(
+        name = name + ".install",
+        input = name,
+        dest = dest,
+        tags = tags,
+    )