feat: add repo_utils with fork of @bazel_tools patch function that takes a working_directory argument

This commit is contained in:
Greg Magolan 2022-04-11 18:08:30 -07:00 committed by Greg Magolan
parent 1421a1d6f4
commit 322bbc92df
8 changed files with 307 additions and 9 deletions

View File

@ -73,4 +73,9 @@ stardoc_with_diff_test(
bzl_library_target = "//lib:transitions",
)
stardoc_with_diff_test(
name = "repo_utils",
bzl_library_target = "//lib:repo_utils",
)
update_docs()

89
docs/repo_utils.md Executable file
View File

@ -0,0 +1,89 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
Public API
<a id="#is_darwin_os"></a>
## is_darwin_os
<pre>
is_darwin_os(<a href="#is_darwin_os-rctx">rctx</a>)
</pre>
Returns true if the host operating system is Darwin
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="is_darwin_os-rctx"></a>rctx | <p align="center"> - </p> | none |
<a id="#is_linux_os"></a>
## is_linux_os
<pre>
is_linux_os(<a href="#is_linux_os-rctx">rctx</a>)
</pre>
Returns true if the host operating system is Linux
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="is_linux_os-rctx"></a>rctx | <p align="center"> - </p> | none |
<a id="#is_windows_os"></a>
## is_windows_os
<pre>
is_windows_os(<a href="#is_windows_os-rctx">rctx</a>)
</pre>
Returns true if the host operating system is Windows
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="is_windows_os-rctx"></a>rctx | <p align="center"> - </p> | none |
<a id="#patch"></a>
## patch
<pre>
patch(<a href="#patch-ctx">ctx</a>, <a href="#patch-patches">patches</a>, <a href="#patch-patch_cmds">patch_cmds</a>, <a href="#patch-patch_cmds_win">patch_cmds_win</a>, <a href="#patch-patch_tool">patch_tool</a>, <a href="#patch-patch_args">patch_args</a>, <a href="#patch-auth">auth</a>, <a href="#patch-patch_directory">patch_directory</a>)
</pre>
Implementation of patching an already extracted repository.
This rule is intended to be used in the implementation function of
a repository rule. If the parameters `patches`, `patch_tool`,
`patch_args`, `patch_cmds` and `patch_cmds_win` are not specified
then they are taken from `ctx.attr`.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="patch-ctx"></a>ctx | The repository context of the repository rule calling this utility function. | none |
| <a id="patch-patches"></a>patches | The patch files to apply. List of strings, Labels, or paths. | <code>None</code> |
| <a id="patch-patch_cmds"></a>patch_cmds | Bash commands to run for patching, passed one at a time to bash -c. List of strings | <code>None</code> |
| <a id="patch-patch_cmds_win"></a>patch_cmds_win | Powershell commands to run for patching, passed one at a time to powershell /c. List of strings. If the boolean value of this parameter is false, patch_cmds will be used and this parameter will be ignored. | <code>None</code> |
| <a id="patch-patch_tool"></a>patch_tool | Path of the patch tool to execute for applying patches. String. | <code>None</code> |
| <a id="patch-patch_args"></a>patch_args | Arguments to pass to the patch tool. List of strings. | <code>None</code> |
| <a id="patch-auth"></a>auth | An optional dict specifying authentication information for some of the URLs. | <code>None</code> |
| <a id="patch-patch_directory"></a>patch_directory | Directory to apply the patches in | <code>None</code> |

View File

@ -127,3 +127,13 @@ bzl_library(
srcs = ["windows_utils.bzl"],
visibility = ["//visibility:public"],
)
bzl_library(
name = "repo_utils",
srcs = ["repo_utils.bzl"],
visibility = ["//visibility:public"],
deps = [
"//lib/private:patch",
"//lib/private:repo_utils",
],
)

View File

@ -120,3 +120,16 @@ bzl_library(
"@bazel_skylib//lib:dicts",
],
)
bzl_library(
name = "repo_utils",
srcs = ["repo_utils.bzl"],
visibility = ["//lib:__subpackages__"],
)
bzl_library(
name = "patch",
srcs = ["patch.bzl"],
visibility = ["//lib:__subpackages__"],
deps = [":repo_utils"],
)

151
lib/private/patch copy.bzl Normal file
View File

@ -0,0 +1,151 @@
# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Fork of @bazel_tools//tools/build_defs/repo:utils.bzl patch function with
working_directory argument added.
"""
load(":repo_utils.bzl", "repo_utils")
# Temporary directory for downloading remote patch files.
_REMOTE_PATCH_DIR = ".tmp_remote_patches"
def _use_native_patch(patch_args):
"""If patch_args only contains -p<NUM> options, we can use the native patch implementation."""
for arg in patch_args:
if not arg.startswith("-p"):
return False
return True
def _download_patch(ctx, patch_url, integrity, auth):
name = patch_url.split("/")[-1]
patch_path = ctx.path(_REMOTE_PATCH_DIR).get_child(name)
ctx.download(
patch_url,
patch_path,
canonical_id = ctx.attr.canonical_id,
auth = auth,
integrity = integrity,
)
return patch_path
def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_tool = None, patch_args = None, auth = None, working_directory = None):
"""Implementation of patching an already extracted repository.
This rule is intended to be used in the implementation function of
a repository rule. If the parameters `patches`, `patch_tool`,
`patch_args`, `patch_cmds` and `patch_cmds_win` are not specified
then they are taken from `ctx.attr`.
Args:
ctx: The repository context of the repository rule calling this utility
function.
patches: The patch files to apply. List of strings, Labels, or paths.
patch_cmds: Bash commands to run for patching, passed one at a
time to bash -c. List of strings
patch_cmds_win: Powershell commands to run for patching, passed
one at a time to powershell /c. List of strings. If the
boolean value of this parameter is false, patch_cmds will be
used and this parameter will be ignored.
patch_tool: Path of the patch tool to execute for applying
patches. String.
patch_args: Arguments to pass to the patch tool. List of strings.
auth: An optional dict specifying authentication information for some of the URLs.
working_directory: Working directory to apply the patches in
"""
bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash"
powershell_exe = ctx.os.environ["BAZEL_POWERSHELL"] if "BAZEL_POWERSHELL" in ctx.os.environ else "powershell.exe"
if patches == None:
patches = []
if hasattr(ctx.attr, "patches") and ctx.attr.patches:
patches += ctx.attr.patches
remote_patches = {}
remote_patch_strip = 0
if hasattr(ctx.attr, "remote_patches") and ctx.attr.remote_patches:
if hasattr(ctx.attr, "remote_patch_strip"):
remote_patch_strip = ctx.attr.remote_patch_strip
remote_patches = ctx.attr.remote_patches
if patch_cmds == None and hasattr(ctx.attr, "patch_cmds"):
patch_cmds = ctx.attr.patch_cmds
if patch_cmds == None:
patch_cmds = []
if patch_cmds_win == None and hasattr(ctx.attr, "patch_cmds_win"):
patch_cmds_win = ctx.attr.patch_cmds_win
if patch_cmds_win == None:
patch_cmds_win = []
if patch_tool == None and hasattr(ctx.attr, "patch_tool"):
patch_tool = ctx.attr.patch_tool
if not patch_tool:
patch_tool = "patch"
native_patch = True
else:
native_patch = False
if patch_args == None and hasattr(ctx.attr, "patch_args"):
patch_args = ctx.attr.patch_args
if patch_args == None:
patch_args = []
if len(remote_patches) > 0 or len(patches) > 0 or len(patch_cmds) > 0:
ctx.report_progress("Patching repository")
# Apply remote patches
for patch_url in remote_patches:
integrity = remote_patches[patch_url]
patchfile = _download_patch(ctx, patch_url, integrity, auth)
ctx.patch(patchfile, remote_patch_strip)
ctx.delete(patchfile)
ctx.delete(ctx.path(_REMOTE_PATCH_DIR))
# Apply local patches
if native_patch and _use_native_patch(patch_args) and not working_directory:
if patch_args:
strip = int(patch_args[-1][2:])
else:
strip = 0
for patchfile in patches:
ctx.patch(patchfile, strip)
else:
for patchfile in patches:
command = "{patchtool} {patch_args} < {patchfile}".format(
patchtool = patch_tool,
patchfile = ctx.path(patchfile),
patch_args = " ".join([
"'%s'" % arg
for arg in patch_args
]),
)
st = ctx.execute([bash_exe, "-c", command], working_directory = working_directory)
if st.return_code:
fail("Error applying patch %s:\n%s%s" %
(str(patchfile), st.stderr, st.stdout))
if repo_utils.is_windows_os(ctx) and patch_cmds_win:
for cmd in patch_cmds_win:
st = ctx.execute([powershell_exe, "/c", cmd], working_directory = working_directory)
if st.return_code:
fail("Error applying patch command %s:\n%s%s" %
(cmd, st.stdout, st.stderr))
else:
for cmd in patch_cmds:
st = ctx.execute([bash_exe, "-c", cmd], working_directory = working_directory)
if st.return_code:
fail("Error applying patch command %s:\n%s%s" %
(cmd, st.stdout, st.stderr))

View File

@ -19,12 +19,11 @@ Upstream code is at
https://github.com/bazelbuild/bazel/blob/f4214746fcd15f0ef8c4e747ef8e3edca9f112a5/tools/build_defs/repo/utils.bzl#L87
"""
load(":repo_utils.bzl", "repo_utils")
# Temporary directory for downloading remote patch files.
_REMOTE_PATCH_DIR = ".tmp_remote_patches"
def _is_windows(ctx):
return ctx.os.name.lower().find("windows") != -1
def _use_native_patch(patch_args):
"""If patch_args only contains -p<NUM> options, we can use the native patch implementation."""
for arg in patch_args:
@ -44,13 +43,14 @@ def _download_patch(ctx, patch_url, integrity, auth):
)
return patch_path
def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_tool = None, patch_args = None, auth = None):
def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_tool = None, patch_args = None, auth = None, patch_directory = None):
"""Implementation of patching an already extracted repository.
This rule is intended to be used in the implementation function of
a repository rule. If the parameters `patches`, `patch_tool`,
`patch_args`, `patch_cmds` and `patch_cmds_win` are not specified
then they are taken from `ctx.attr`.
Args:
ctx: The repository context of the repository rule calling this utility
function.
@ -65,6 +65,8 @@ def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_t
patches. String.
patch_args: Arguments to pass to the patch tool. List of strings.
auth: An optional dict specifying authentication information for some of the URLs.
patch_directory: Directory to apply the patches in
"""
bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash"
powershell_exe = ctx.os.environ["BAZEL_POWERSHELL"] if "BAZEL_POWERSHELL" in ctx.os.environ else "powershell.exe"
@ -116,7 +118,7 @@ def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_t
ctx.delete(ctx.path(_REMOTE_PATCH_DIR))
# Apply local patches
if native_patch and _use_native_patch(patch_args):
if native_patch and _use_native_patch(patch_args) and not patch_directory:
if patch_args:
strip = int(patch_args[-1][2:])
else:
@ -133,20 +135,20 @@ def patch(ctx, patches = None, patch_cmds = None, patch_cmds_win = None, patch_t
for arg in patch_args
]),
)
st = ctx.execute([bash_exe, "-c", command])
st = ctx.execute([bash_exe, "-c", command], working_directory = patch_directory)
if st.return_code:
fail("Error applying patch %s:\n%s%s" %
(str(patchfile), st.stderr, st.stdout))
if _is_windows(ctx) and patch_cmds_win:
if repo_utils.is_windows_os(ctx) and patch_cmds_win:
for cmd in patch_cmds_win:
st = ctx.execute([powershell_exe, "/c", cmd])
st = ctx.execute([powershell_exe, "/c", cmd], working_directory = patch_directory)
if st.return_code:
fail("Error applying patch command %s:\n%s%s" %
(cmd, st.stdout, st.stderr))
else:
for cmd in patch_cmds:
st = ctx.execute([bash_exe, "-c", cmd])
st = ctx.execute([bash_exe, "-c", cmd], working_directory = patch_directory)
if st.return_code:
fail("Error applying patch command %s:\n%s%s" %
(cmd, st.stdout, st.stderr))

View File

@ -0,0 +1,19 @@
"""Utility functions for repository rules"""
def _is_windows_os(rctx):
"""Returns true if the host operating system is Windows"""
return rctx.os.name.lower().find("windows") != -1
def _is_darwin_os(rctx):
"""Returns true if the host operating system is Darwin"""
return rctx.os.name.lower().os_name.startswith("mac os")
def _is_linux_os(rctx):
"""Returns true if the host operating system is Linux"""
return rctx.os.name.lower().startswith("linux")
repo_utils = struct(
is_windows_os = _is_windows_os,
is_darwin_os = _is_darwin_os,
is_linux_os = _is_linux_os,
)

9
lib/repo_utils.bzl Normal file
View File

@ -0,0 +1,9 @@
"Public API"
load("//lib/private:repo_utils.bzl", "repo_utils")
load("//lib/private:patch.bzl", _patch = "patch")
is_windows_os = repo_utils.is_windows_os
is_darwin_os = repo_utils.is_darwin_os
is_linux_os = repo_utils.is_linux_os
patch = _patch