Support patching of git repositories as well By simply sharing the utility function. In this way, we get feature parity between git_repository and http_archive. Fixes #4676. Change-Id: I99b300e42b2f267d8d04fd965f09c24f3ae54f10 PiperOrigin-RevId: 187450644
diff --git a/src/test/shell/bazel/external_patching_test.sh b/src/test/shell/bazel/external_patching_test.sh index fe5d4f2..820b859 100755 --- a/src/test/shell/bazel/external_patching_test.sh +++ b/src/test/shell/bazel/external_patching_test.sh
@@ -110,6 +110,92 @@ grep -q 'env' $foopath || fail "expected unpatched file" } +test_patch_git() { + EXTREPODIR=`pwd` + export GIT_CONFIG_NOSYSTEM=YES + + mkdir extgit + (cd extgit && git init \ + && git config user.email 'me@example.com' \ + && git config user.name 'E X Ample' ) + cat > extgit/foo.sh <<'EOF' +#!/usr/bin/env sh + +echo Here be dragons... +EOF + (cd extgit + git add . + git commit --author="A U Thor <author@example.com>" -m 'initial commit' + git tag mytag) + + # Test that the patches attribute of git_repository is honored + mkdir main + cd main + cat > patch_foo.sh <<'EOF' +--- foo.sh.orig 2018-01-15 10:39:20.183909147 +0100 ++++ foo.sh 2018-01-15 10:43:35.331566052 +0100 +@@ -1,3 +1,3 @@ + #!/usr/bin/env sh + +-echo Here be dragons... ++echo There are dragons... +EOF + cat > WORKSPACE <<EOF +load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository") +new_git_repository( + name="ext", + remote="file://${EXTREPODIR}/extgit/.git", + tag="mytag", + build_file_content="exports_files([\"foo.sh\"])", + patches = ["//:patch_foo.sh"], + patch_cmds = ["find . -name '*.sh' -exec sed -i.orig '1s|#!/usr/bin/env sh\$|/bin/sh\$|' {} +"], +) +EOF + cat > BUILD <<'EOF' +genrule( + name = "foo", + outs = ["foo.sh"], + srcs = ["@ext//:foo.sh"], + cmd = "cp $< $@; chmod u+x $@", + executable = True, +) +EOF + bazel build :foo.sh + foopath=`bazel info bazel-genfiles`/foo.sh + grep -q 'There are' $foopath || fail "expected patch to be applied" + grep env $foopath && fail "expected patch commands to be executed" || : + + # Verify that changes to the patch files trigger enough rebuilding + cat > patch_foo.sh <<'EOF' +--- foo.sh.orig 2018-01-15 10:39:20.183909147 +0100 ++++ foo.sh 2018-01-15 10:43:35.331566052 +0100 +@@ -1,3 +1,3 @@ + #!/usr/bin/env sh + +-echo Here be dragons... ++echo completely differently patched +EOF + bazel build :foo.sh + foopath=`bazel info bazel-genfiles`/foo.sh + grep -q 'differently patched' $foopath \ + || fail "expected the new patch to be applied" + + # Verify that changes to the patches attribute trigger enough rebuilding + cat > WORKSPACE <<EOF +load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository") +new_git_repository( + name="ext", + remote="file://${EXTREPODIR}/extgit/.git", + tag="mytag", + build_file_content="exports_files([\"foo.sh\"])", +) +EOF + bazel build :foo.sh + foopath=`bazel info bazel-genfiles`/foo.sh + grep -q 'Here be' $foopath || fail "expected unpatched file" + grep -q 'env' $foopath || fail "expected unpatched file" +} + test_override_buildfile() { ## Verify that the BUILD file of an external repository can be overriden ## via the http_archive rule.
diff --git a/tools/build_defs/repo/git.bzl b/tools/build_defs/repo/git.bzl index f146ef6..d9cf660 100644 --- a/tools/build_defs/repo/git.bzl +++ b/tools/build_defs/repo/git.bzl
@@ -13,7 +13,8 @@ # limitations under the License. """Rules for cloning external git repositories.""" -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile", "patch") + def _clone_or_update(ctx): if ((not ctx.attr.tag and not ctx.attr.commit) or @@ -86,9 +87,11 @@ fail('Exactly one of build_file and build_file_content must be provided.') _clone_or_update(ctx) workspace_and_buildfile(ctx) + patch(ctx) def _git_repository_implementation(ctx): _clone_or_update(ctx) + patch(ctx) _common_attrs = { @@ -98,7 +101,10 @@ 'tag': attr.string(default=''), 'init_submodules': attr.bool(default=False), 'verbose': attr.bool(default=False), - 'strip_prefix': attr.string(default='') + 'strip_prefix': attr.string(default=''), + 'patches': attr.label_list(default=[]), + 'patch_tool': attr.string(default="patch"), + 'patch_cmds': attr.string_list(default=[]), } @@ -144,6 +150,11 @@ remote: The URI of the remote Git repository. strip_prefix: A directory prefix to strip from the extracted files. + + patches: A list of files that are to be applied as patches after extracting + the archive. + patch_tool: the patch(1) utility to use. + patch_cmds: sequence of commands to be applied after patches are applied. """ git_repository = repository_rule( @@ -174,4 +185,9 @@ wall-clock time. strip_prefix: A directory prefix to strip from the extracted files. + + patches: A list of files that are to be applied as patches after extracting + the archive. + patch_tool: the patch(1) utility to use. + patch_cmds: sequence of commands to be applied after patches are applied. """
diff --git a/tools/build_defs/repo/http.bzl b/tools/build_defs/repo/http.bzl index 2247708..e396914 100644 --- a/tools/build_defs/repo/http.bzl +++ b/tools/build_defs/repo/http.bzl
@@ -29,23 +29,7 @@ replace the native rules. """ -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile") - -def _patch(ctx): - """Implementation of patching an already extracted repository""" - bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" - for patchfile in ctx.attr.patches: - command = "{patchtool} -p0 < {patchfile}".format( - patchtool=ctx.attr.patch_tool, - patchfile=ctx.path(patchfile)) - st = ctx.execute([bash_exe, "-c", command]) - if st.return_code: - fail("Error applying patch %s:\n%s" % (str(patchfile), st.stderr)) - for cmd in ctx.attr.patch_cmds: - st = ctx.execute([bash_exe, "-c", cmd]) - if st.return_code: - fail("Error applying patch command %s:\n%s%s" - % (cmd, st.stdout, st.stderr)) +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile", "patch") def _http_archive_impl(ctx): """Implementation of the http_archive rule.""" @@ -74,7 +58,7 @@ ctx.download_and_extract(all_urls, "", ctx.attr.sha256, ctx.attr.type, ctx.attr.strip_prefix) - _patch(ctx) + patch(ctx) workspace_and_buildfile(ctx) _HTTP_FILE_BUILD = """
diff --git a/tools/build_defs/repo/utils.bzl b/tools/build_defs/repo/utils.bzl index 5f72f64..b326a82 100644 --- a/tools/build_defs/repo/utils.bzl +++ b/tools/build_defs/repo/utils.bzl
@@ -50,4 +50,20 @@ ctx.execute([bash_exe, "-c", "rm -f BUILD.bazel"]) ctx.file("BUILD", ctx.attr.build_file_content) +def patch(ctx): + """Implementation of patching an already extracted repository""" + bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" + for patchfile in ctx.attr.patches: + command = "{patchtool} -p0 < {patchfile}".format( + patchtool=ctx.attr.patch_tool, + patchfile=ctx.path(patchfile)) + st = ctx.execute([bash_exe, "-c", command]) + if st.return_code: + fail("Error applying patch %s:\n%s" % (str(patchfile), st.stderr)) + for cmd in ctx.attr.patch_cmds: + st = ctx.execute([bash_exe, "-c", cmd]) + if st.return_code: + fail("Error applying patch command %s:\n%s%s" + % (cmd, st.stdout, st.stderr)) +