diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD index 3c10ffc1b82f3a..ea2b8226b2a7f8 100644 --- a/src/test/shell/bazel/BUILD +++ b/src/test/shell/bazel/BUILD @@ -246,6 +246,7 @@ sh_test( size = "medium", srcs = ["external_patching_test.sh"], data = [":test-deps"], + shard_count = 3, ) sh_test( diff --git a/src/test/shell/bazel/external_patching_test.sh b/src/test/shell/bazel/external_patching_test.sh index 1458b2d886498f..5f13d536264d16 100755 --- a/src/test/shell/bazel/external_patching_test.sh +++ b/src/test/shell/bazel/external_patching_test.sh @@ -223,6 +223,129 @@ EOF expect_not_log "BAD" } +test_override_buildfile_git() { + ## Verify that the BUILD file of an external repository can be overriden + ## via the git_repository rule. + EXTREPODIR=`pwd` + export GIT_CONFIG_NOSYSTEM=YES + + mkdir withbuild + (cd withbuild && git init) + cat > withbuild/BUILD.bazel <<'EOF' +genrule( + name="target", + srcs=["file.txt"], + outs=["target.txt"], + cmd="cp $< $@ && echo BAD >> $@", + visibility=["//visibility:public"], +) +EOF + cat > withbuild/file.txt <<'EOF' +from external repo +EOF + (cd withbuild + git add . + git commit --author="A U Thor " -m 'initial commit' + git tag mytag) + + mkdir main + cd main + cat > WORKSPACE < BUILD <<'EOF' +genrule( + name = "local", + outs = ["local.txt"], + srcs = ["@withbuild//:target"], + cmd = "cp $< $@", +) +EOF + cat > ext.BUILD <<'EOF' +genrule( + name="target", + srcs=["file.txt"], + outs=["target.txt"], + cmd="cp $< $@ && echo GOOD >> $@", + visibility=["//visibility:public"], +) +EOF + + bazel build //:local || fail "Expected success" + + cat `bazel info bazel-genfiles`/local.txt > "${TEST_log}" + expect_log "from external repo" + expect_log "GOOD" + expect_not_log "BAD" +} + +test_override_buildfilecontents_git() { + ## Verify that the BUILD file of an external repository can be overriden + ## via specified content in the git_repository rule. + EXTREPODIR=`pwd` + export GIT_CONFIG_NOSYSTEM=YES + + mkdir withbuild + (cd withbuild && git init) + cat > withbuild/BUILD.bazel <<'EOF' +genrule( + name="target", + srcs=["file.txt"], + outs=["target.txt"], + cmd="cp $< $@ && echo BAD >> $@", + visibility=["//visibility:public"], +) +EOF + cat > withbuild/file.txt <<'EOF' +from external repo +EOF + (cd withbuild + git add . + git commit --author="A U Thor " -m 'initial commit' + git tag mytag) + + mkdir main + cd main + cat > WORKSPACE < BUILD <<'EOF' +genrule( + name = "local", + outs = ["local.txt"], + srcs = ["@withbuild//:target"], + cmd = "cp $< $@", +) +EOF + + bazel build //:local || fail "Expected success" + + cat `bazel info bazel-genfiles`/local.txt > "${TEST_log}" + expect_log "from external repo" + expect_log "GOOD" + expect_not_log "BAD" +} + test_build_file_build_bazel() { ## 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 d85a9d6e7e06ed..f146ef69b4288b 100644 --- a/tools/build_defs/repo/git.bzl +++ b/tools/build_defs/repo/git.bzl @@ -13,6 +13,8 @@ # limitations under the License. """Rules for cloning external git repositories.""" +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile") + def _clone_or_update(ctx): if ((not ctx.attr.tag and not ctx.attr.commit) or (ctx.attr.tag and ctx.attr.commit)): @@ -83,11 +85,7 @@ def _new_git_repository_implementation(ctx): (ctx.attr.build_file and ctx.attr.build_file_content)): fail('Exactly one of build_file and build_file_content must be provided.') _clone_or_update(ctx) - ctx.file('WORKSPACE', 'workspace(name = \'{name}\')\n'.format(name=ctx.name)) - if ctx.attr.build_file: - ctx.symlink(ctx.attr.build_file, 'BUILD.bazel') - else: - ctx.file('BUILD.bazel', ctx.attr.build_file_content) + workspace_and_buildfile(ctx) def _git_repository_implementation(ctx): _clone_or_update(ctx) diff --git a/tools/build_defs/repo/http.bzl b/tools/build_defs/repo/http.bzl index 9e5b7e137509cb..2247708f2cc2a8 100644 --- a/tools/build_defs/repo/http.bzl +++ b/tools/build_defs/repo/http.bzl @@ -29,6 +29,8 @@ These rules are improved versions of the native http rules and will eventually 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" @@ -73,16 +75,7 @@ def _http_archive_impl(ctx): ctx.download_and_extract(all_urls, "", ctx.attr.sha256, ctx.attr.type, ctx.attr.strip_prefix) _patch(ctx) - ctx.file("WORKSPACE", "workspace(name = \"{name}\")\n".format(name=ctx.name)) - if ctx.attr.build_file: - bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" - ctx.execute([bash_exe, "-c", "rm -f BUILD BUILD.bazel"]) - ctx.symlink(ctx.attr.build_file, "BUILD") - elif ctx.attr.build_file_content: - bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" - ctx.execute([bash_exe, "-c", "rm -f BUILD.bazel"]) - ctx.file("BUILD", ctx.attr.build_file_content) - + workspace_and_buildfile(ctx) _HTTP_FILE_BUILD = """ package(default_visibility = ["//visibility:public"]) diff --git a/tools/build_defs/repo/utils.bzl b/tools/build_defs/repo/utils.bzl new file mode 100644 index 00000000000000..5f72f6489e264e --- /dev/null +++ b/tools/build_defs/repo/utils.bzl @@ -0,0 +1,53 @@ +# 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. +"""Utils for manipulating external repositories, once fetched. + +### Setup + +These utility are intended to be used by other repository rules. They +can be loaded as follows. + +```python +load( + "@bazel_tools//tools/build_defs/repo:utils.bzl", + "workspace_and_buildfile", +) +``` +""" + +def workspace_and_buildfile(ctx): + """Utility function for writing WORKSPACE and, if requested, a BUILD file. + + It assumes the paramters name, build_file, and build_file_contents to be + present in ctx.attr, the latter two possibly with value None. + + Args: + ctx: The repository context of the repository rule calling this utility + function. + """ + if ctx.attr.build_file and ctx.attr.build_file_content: + ctx.fail("Only one of build_file and build_file_content can be provided.") + + ctx.file("WORKSPACE", "workspace(name = \"{name}\")\n".format(name=ctx.name)) + + if ctx.attr.build_file: + bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" + ctx.execute([bash_exe, "-c", "rm -f BUILD BUILD.bazel"]) + ctx.symlink(ctx.attr.build_file, "BUILD") + elif ctx.attr.build_file_content: + bash_exe = ctx.os.environ["BAZEL_SH"] if "BAZEL_SH" in ctx.os.environ else "bash" + ctx.execute([bash_exe, "-c", "rm -f BUILD.bazel"]) + ctx.file("BUILD", ctx.attr.build_file_content) + +