feat: Relax single file limit of run_in rule (#71)
This change makes `run_in` rule accept multi-file executable target by
using `ctx.executable.tool`. With this change, it will be possible to
wrap e.g. a `py_console_script_binary` target where there is an
executable file together with a bunch of other files.
As a concrete example:
```starlark
load("@pip_deps//:requirements.bzl", "requirement")
load("@rules_multitool//multitool:cwd.bzl", "cwd")
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary")
py_console_script_binary(
name = "pre-commit",
pkg = requirement("pre-commit"),
script = "pre-commit",
)
cwd(
name = "cwd",
tool = ":pre-commit",
)
```
Then we can do `bazel run //tools/pre-commit:cwd -- autoupdate`,
otherwise we will need to have workaround like `bazel run
--run_under="cd $PWD && " //tools/pre-commit -- autoupdate`diff --git a/examples/module/.bazelrc b/examples/module/.bazelrc
index fe93ecc..c7becee 100644
--- a/examples/module/.bazelrc
+++ b/examples/module/.bazelrc
@@ -10,3 +10,7 @@
# off by default on windows, required for this module
common --enable_runfiles
+
+# Don't rely on test logs being easily accessible from the test runner,
+# though it makes the log noisier.
+test --test_output=errors
diff --git a/examples/module/BUILD.bazel b/examples/module/BUILD.bazel
index e143f37..d738393 100644
--- a/examples/module/BUILD.bazel
+++ b/examples/module/BUILD.bazel
@@ -1,3 +1,6 @@
+load("@rules_multitool//multitool:cwd.bzl", "cwd")
+load("//:add_dummy_file.bzl", "add_dummy_file")
+
sh_test(
name = "integration_test",
srcs = ["integration_test.sh"],
@@ -24,3 +27,22 @@
],
data = ["@multitool//tools/target-determinator:workspace_root"],
)
+
+add_dummy_file(
+ name = "add_dummy_file",
+ tool = "@multitool//tools/target-determinator",
+)
+
+cwd(
+ name = "add_dummy_file_cwd",
+ tool = ":add_dummy_file",
+)
+
+sh_test(
+ name = "integration_test_add_dummy_file_cwd",
+ srcs = ["integration_test.sh"],
+ args = [
+ "$(location :add_dummy_file_cwd)",
+ ],
+ data = [":add_dummy_file_cwd"],
+)
diff --git a/examples/module/add_dummy_file.bzl b/examples/module/add_dummy_file.bzl
new file mode 100644
index 0000000..7a90bc3
--- /dev/null
+++ b/examples/module/add_dummy_file.bzl
@@ -0,0 +1,27 @@
+"rule adding a dummy file to output, for test purpose"
+
+def _add_dummy_file(ctx):
+ if ctx.executable.tool.extension == "exe":
+ content = "@%s %%*" % ctx.executable.tool.short_path.replace("/", "\\")
+ script = ctx.actions.declare_file(ctx.label.name + ".bat")
+ else:
+ content = '#!/usr/bin/env bash\nexec "%s" "$@"' % ctx.executable.tool.short_path
+ script = ctx.actions.declare_file(ctx.label.name)
+ ctx.actions.write(script, content, is_executable = True)
+
+ dummy_output_file = ctx.actions.declare_file(ctx.label.name + ".dummy")
+ ctx.actions.write(dummy_output_file, "")
+
+ return [DefaultInfo(
+ executable = script,
+ files = depset([script, dummy_output_file]),
+ runfiles = ctx.attr.tool[DefaultInfo].default_runfiles,
+ )]
+
+add_dummy_file = rule(
+ implementation = _add_dummy_file,
+ executable = True,
+ attrs = {
+ "tool": attr.label(mandatory = True, executable = True, cfg = "exec"),
+ },
+)
diff --git a/multitool/private/run_in.bzl b/multitool/private/run_in.bzl
index 619c523..c8bbd73 100644
--- a/multitool/private/run_in.bzl
+++ b/multitool/private/run_in.bzl
@@ -1,7 +1,7 @@
"run_in provides a shared implementation for cwd and workspace_root execution"
run_in_attrs = {
- "tool": attr.label(mandatory = True, allow_single_file = True, executable = True, cfg = "exec"),
+ "tool": attr.label(mandatory = True, executable = True, cfg = "exec"),
"_template_sh": attr.label(default = "//multitool/private:run_in.template.sh", allow_single_file = True),
"_template_bat": attr.label(default = "//multitool/private:run_in.template.bat", allow_single_file = True),
}
@@ -22,8 +22,8 @@
# This algorithm requires --enable_runfiles (enabled by default on non-windows)
template = ctx.file._template_sh
wrapper_name = ctx.label.name
- tool_short_path = ctx.file.tool.short_path
- if ctx.file.tool.extension == "exe":
+ tool_short_path = ctx.executable.tool.short_path
+ if ctx.executable.tool.extension == "exe":
template = ctx.file._template_bat
wrapper_name = wrapper_name + ".bat"
tool_short_path = tool_short_path.replace("/", "\\")
@@ -36,4 +36,4 @@
"{{env_var}}": env_var,
},
)
- return [DefaultInfo(executable = output, runfiles = ctx.runfiles(files = [ctx.file.tool]))]
+ return [DefaultInfo(executable = output, runfiles = ctx.attr.tool[DefaultInfo].default_runfiles)]