From 5a27b74ee6ab07e68064c40d4823682929d7c523 Mon Sep 17 00:00:00 2001 From: salma-samy Date: Thu, 29 Feb 2024 06:53:24 -0800 Subject: [PATCH] Fix fetch target (fixes #13847) Context: - Traditional query relies on the initial loading phase of the build, this lacks the context of build configurations (flags, select() logic), leading to potentially inaccurate or over-inclusive dependency listings. - cquery executes after the analysis phase, where Bazel has resolved configurations and determined how options influence target definitions. This allows cquery to provide the dependencies truly needed for a build under the current settings. Considering these differences, I'm updating fetch target logic to rely on cquery instead. This ensures that all necessary repositories are fetched for an offline build while avoiding potential over-fetching PiperOrigin-RevId: 611455579 Change-Id: I2a954476c06182fd9eb78ad86def7bd72f04074a --- .../devtools/build/lib/bazel/commands/BUILD | 5 +- .../lib/bazel/commands/FetchCommand.java | 20 +- .../lib/bazel/commands/TargetFetcher.java | 151 ++++++++++----- .../build/lib/buildtool/CqueryProcessor.java | 20 +- .../ConfiguredTargetQueryEnvironment.java | 181 +++++++++++------- src/test/py/bazel/BUILD | 4 + src/test/py/bazel/bzlmod/bazel_fetch_test.py | 38 ++++ .../bzlmod/external_repo_completion_test.py | 4 +- 8 files changed, 291 insertions(+), 132 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/commands/BUILD index 0ace636128ad20..5c074c83ccabbc 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/commands/BUILD +++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/BUILD @@ -45,11 +45,10 @@ java_library( "//src/main/java/com/google/devtools/build/lib/cmdline", "//src/main/java/com/google/devtools/build/lib/events", "//src/main/java/com/google/devtools/build/lib/packages", - "//src/main/java/com/google/devtools/build/lib/packages:label_printer", "//src/main/java/com/google/devtools/build/lib/packages/semantics", "//src/main/java/com/google/devtools/build/lib/pkgcache", - "//src/main/java/com/google/devtools/build/lib/query2/common:abstract-blaze-query-env", - "//src/main/java/com/google/devtools/build/lib/query2/common:universe-scope", + "//src/main/java/com/google/devtools/build/lib/query2", + "//src/main/java/com/google/devtools/build/lib/query2/common:cquery-node", "//src/main/java/com/google/devtools/build/lib/query2/engine", "//src/main/java/com/google/devtools/build/lib/rules:repository/repository_directory_value", "//src/main/java/com/google/devtools/build/lib/rules:repository/repository_function", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java index f1cd8511a2adb2..d9d64471dc2a22 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.events.Reporter; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; import com.google.devtools.build.lib.pkgcache.PackageOptions; +import com.google.devtools.build.lib.query2.cquery.CqueryOptions; import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction; import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue; import com.google.devtools.build.lib.runtime.BlazeCommand; @@ -38,17 +39,18 @@ import com.google.devtools.build.lib.runtime.CommandEnvironment; import com.google.devtools.build.lib.runtime.KeepGoingOption; import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption; +import com.google.devtools.build.lib.runtime.commands.TestCommand; import com.google.devtools.build.lib.server.FailureDetails; import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; import com.google.devtools.build.lib.server.FailureDetails.FetchCommand.Code; import com.google.devtools.build.lib.skyframe.PrecomputedValue; import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException; -import com.google.devtools.build.lib.util.AbruptExitException; import com.google.devtools.build.lib.util.DetailedExitCode; import com.google.devtools.build.lib.util.InterruptedFailureDetails; import com.google.devtools.build.skyframe.EvaluationContext; import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.SkyValue; +import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsParsingResult; import java.util.List; import javax.annotation.Nullable; @@ -56,12 +58,16 @@ /** Fetches external repositories. Which is so fetch. */ @Command( name = FetchCommand.NAME, + builds = true, + inherits = {TestCommand.class}, options = { FetchOptions.class, + CqueryOptions.class, PackageOptions.class, KeepGoingOption.class, LoadingPhaseThreadsOption.class }, + usesConfigurationOptions = true, help = "resource:fetch.txt", shortDescription = "Fetches external repositories that are prerequisites to the targets.", allowResidue = true, @@ -70,6 +76,14 @@ public final class FetchCommand implements BlazeCommand { public static final String NAME = "fetch"; + @Override + public void editOptions(OptionsParser optionsParser) { + // We only need to inject these options with fetch target (when there is a residue) + if (!optionsParser.getResidue().isEmpty()) { + TargetFetcher.injectOptionsToFetchTarget(optionsParser); + } + } + @Override public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) { BlazeCommandResult invalidResult = validateOptions(env, options); @@ -100,7 +114,6 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti BlazeCommandResult result; LoadingPhaseThreadsOption threadsOption = options.getOptions(LoadingPhaseThreadsOption.class); try { - env.syncPackageLoading(options); if (!options.getResidue().isEmpty()) { result = fetchTarget(env, options, options.getResidue()); } else if (!fetchOptions.repos.isEmpty()) { @@ -108,9 +121,6 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti } else { // --all, --configure, or just 'fetch' result = fetchAll(env, threadsOption, fetchOptions.configure); } - } catch (AbruptExitException e) { - return createFailedBlazeCommandResult( - env.getReporter(), e.getMessage(), e.getDetailedExitCode()); } catch (InterruptedException e) { return createFailedBlazeCommandResult( env.getReporter(), "Fetch interrupted: " + e.getMessage()); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/TargetFetcher.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/TargetFetcher.java index 94de6ab029f779..71df720e849966 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/commands/TargetFetcher.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/TargetFetcher.java @@ -14,30 +14,39 @@ package com.google.devtools.build.lib.bazel.commands; +import static com.google.common.collect.ImmutableMap.toImmutableMap; + import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.buildtool.BuildRequest; +import com.google.devtools.build.lib.buildtool.BuildResult; +import com.google.devtools.build.lib.buildtool.BuildTool; +import com.google.devtools.build.lib.buildtool.CqueryProcessor; import com.google.devtools.build.lib.cmdline.RepositoryMapping; import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.cmdline.TargetPattern; import com.google.devtools.build.lib.cmdline.TargetPattern.Parser; -import com.google.devtools.build.lib.packages.LabelPrinter; -import com.google.devtools.build.lib.packages.Target; -import com.google.devtools.build.lib.query2.common.AbstractBlazeQueryEnvironment; -import com.google.devtools.build.lib.query2.common.UniverseScope; -import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting; -import com.google.devtools.build.lib.query2.engine.QueryEvalResult; -import com.google.devtools.build.lib.query2.engine.QueryException; +import com.google.devtools.build.lib.query2.NamedThreadSafeOutputFormatterCallback; +import com.google.devtools.build.lib.query2.common.CqueryNode; +import com.google.devtools.build.lib.query2.cquery.ConfiguredTargetQueryEnvironment; +import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction; import com.google.devtools.build.lib.query2.engine.QueryExpression; +import com.google.devtools.build.lib.query2.engine.QueryParser; import com.google.devtools.build.lib.query2.engine.QuerySyntaxException; -import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback; import com.google.devtools.build.lib.runtime.CommandEnvironment; import com.google.devtools.build.lib.runtime.KeepGoingOption; import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption; -import com.google.devtools.build.lib.runtime.commands.QueryCommand; import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException; +import com.google.devtools.common.options.OptionPriority.PriorityCategory; +import com.google.devtools.common.options.OptionsParser; +import com.google.devtools.common.options.OptionsParsingException; import com.google.devtools.common.options.OptionsParsingResult; -import java.io.IOException; -import java.util.EnumSet; +import java.util.Collection; import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; /** Fetches all repos needed for building a given set of targets. */ public class TargetFetcher { @@ -47,7 +56,7 @@ private TargetFetcher(CommandEnvironment env) { this.env = env; } - /** Uses `deps` query to find and fetch all repos needed for these targets */ + /** Uses cquery to find and fetch all repos needed to build these targets */ public static void fetchTargets( CommandEnvironment env, OptionsParsingResult options, List targets) throws RepositoryMappingResolutionException, InterruptedException, TargetFetcherException { @@ -56,28 +65,17 @@ public static void fetchTargets( private void fetchTargets(OptionsParsingResult options, List targets) throws InterruptedException, TargetFetcherException, RepositoryMappingResolutionException { - AbstractBlazeQueryEnvironment queryEnv = getQueryEnv(options); - QueryExpression expr = createQueryExpression(targets, queryEnv); - QueryEvalResult queryEvalResult; - try { - queryEvalResult = - queryEnv.evaluateQuery( - expr, - new ThreadSafeOutputFormatterCallback<>() { - @Override - public void processOutput(Iterable partialResult) {} - }); - } catch (IOException e) { - // Should be impossible since our OutputFormatterCallback doesn't throw IOException. - throw new IllegalStateException(e); - } catch (QueryException e) { - throw new TargetFetcherException( - String.format( - "Fetching target dependencies for %s encountered an error: %s", - expr, e.getMessage())); - } + QueryExpression expr = createQueryExpression(targets); + BuildRequest request = createBuildRequest(env, options, targets); + TargetPattern.Parser mainRepoTargetParser = getMainRepoMappingParser(env); - if (!queryEvalResult.getSuccess()) { + BuildResult result = + new BuildTool( + env, + new CqueryProcessor( + expr, mainRepoTargetParser, Optional.of(createNoOutputFormatter()))) + .processRequest(request, /* validator= */ null); + if (!result.getSuccess()) { throw new TargetFetcherException( String.format( "Fetching some target dependencies for %s failed, but --keep_going specified. " @@ -86,33 +84,59 @@ public void processOutput(Iterable partialResult) {} } } - AbstractBlazeQueryEnvironment getQueryEnv(OptionsParsingResult options) + /** Creates special output formatter for fetch that doesn't print anything */ + private NamedThreadSafeOutputFormatterCallback createNoOutputFormatter() { + return new NamedThreadSafeOutputFormatterCallback() { + @Override + public String getName() { + return "no_output"; + } + + @Override + public void processOutput(Iterable partialResult) { + // Just do nothing! + // This will be later used to collect repos for vendoring + } + }; + } + + private BuildRequest createBuildRequest( + CommandEnvironment env, OptionsParsingResult options, List targets) { + return BuildRequest.builder() + .setCommandName(env.getCommandName()) + .setId(env.getCommandId()) + .setOptions(options) + .setStartupOptions(env.getRuntime().getStartupOptionsProvider()) + .setOutErr(env.getReporter().getOutErr()) + .setTargets(targets) + .setStartTimeMillis(env.getCommandStartTime()) + .setCheckforActionConflicts(false) + .setReportIncompatibleTargets(false) + .build(); + } + + private Parser getMainRepoMappingParser(CommandEnvironment env) throws RepositoryMappingResolutionException, InterruptedException { - boolean keepGoing = options.getOptions(KeepGoingOption.class).keepGoing; - LoadingPhaseThreadsOption threadsOption = options.getOptions(LoadingPhaseThreadsOption.class); RepositoryMapping repoMapping = env.getSkyframeExecutor() - .getMainRepoMapping(keepGoing, threadsOption.threads, env.getReporter()); - TargetPattern.Parser targetParser = - new Parser(env.getRelativeWorkingDirectory(), RepositoryName.MAIN, repoMapping); - return QueryCommand.newQueryEnvironment( - env, - keepGoing, - false, - UniverseScope.EMPTY, - threadsOption.threads, - EnumSet.noneOf(Setting.class), - /* useGraphlessQuery= */ true, - targetParser, - LabelPrinter.legacy()); + .getMainRepoMapping( + env.getOptions().getOptions(KeepGoingOption.class).keepGoing, + env.getOptions().getOptions(LoadingPhaseThreadsOption.class).threads, + env.getReporter()); + return new Parser(env.getRelativeWorkingDirectory(), RepositoryName.MAIN, repoMapping); } - private QueryExpression createQueryExpression( - List targets, AbstractBlazeQueryEnvironment queryEnv) + private QueryExpression createQueryExpression(List targets) throws TargetFetcherException { String query = "deps(" + Joiner.on(" union ").join(targets) + ")"; + + ImmutableMap functions = + Stream.of(ConfiguredTargetQueryEnvironment.FUNCTIONS, env.getRuntime().getQueryFunctions()) + .flatMap(Collection::stream) + .collect(toImmutableMap(QueryFunction::getName, Function.identity())); + try { - return QueryExpression.parse(query, queryEnv); + return QueryParser.parse(query, functions); } catch (QuerySyntaxException e) { throw new TargetFetcherException( String.format( @@ -121,6 +145,29 @@ private QueryExpression createQueryExpression( } } + static void injectOptionsToFetchTarget(OptionsParser optionsParser) { + try { + optionsParser.parse( + PriorityCategory.COMPUTED_DEFAULT, + "Options required to fetch target", + ImmutableList.of("--nobuild")); + optionsParser.parse( + PriorityCategory.COMPUTED_DEFAULT, + "Fetch target should include 'tags = [\"manual\"]' targets by default", + ImmutableList.of("--build_manual_tests")); + optionsParser.parse( + PriorityCategory.SOFTWARE_REQUIREMENT, + "Fetch target should not exclude test_suite rules", + ImmutableList.of("--noexpand_test_suites")); + optionsParser.parse( + PriorityCategory.SOFTWARE_REQUIREMENT, + "Fetch target should not exclude tests", + ImmutableList.of("--nobuild_tests_only")); + } catch (OptionsParsingException e) { + throw new IllegalStateException("Fetch target needed options failed to parse", e); + } + } + static class TargetFetcherException extends Exception { public TargetFetcherException(String message) { super(message); diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/CqueryProcessor.java b/src/main/java/com/google/devtools/build/lib/buildtool/CqueryProcessor.java index fa0ab52e861629..64fac989abd332 100644 --- a/src/main/java/com/google/devtools/build/lib/buildtool/CqueryProcessor.java +++ b/src/main/java/com/google/devtools/build/lib/buildtool/CqueryProcessor.java @@ -16,6 +16,7 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.TargetPattern; import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions; +import com.google.devtools.build.lib.query2.NamedThreadSafeOutputFormatterCallback; import com.google.devtools.build.lib.query2.PostAnalysisQueryEnvironment.TopLevelConfigurations; import com.google.devtools.build.lib.query2.common.CqueryNode; import com.google.devtools.build.lib.query2.cquery.ConfiguredTargetQueryEnvironment; @@ -26,14 +27,30 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.WalkableGraph; import java.util.Collection; +import java.util.Optional; import net.starlark.java.eval.StarlarkSemantics; /** Performs {@code cquery} processing. */ public final class CqueryProcessor extends PostAnalysisQueryProcessor { + /** + * Only passed when this is a call from a non query command like Fetch or Vendor, where we don't + * need the output printed + */ + private Optional> noOutputFormatter; + public CqueryProcessor( QueryExpression queryExpression, TargetPattern.Parser mainRepoTargetParser) { super(queryExpression, mainRepoTargetParser); + this.noOutputFormatter = Optional.empty(); + } + + public CqueryProcessor( + QueryExpression queryExpression, + TargetPattern.Parser mainRepoTargetParser, + Optional> noOutputFormatter) { + this(queryExpression, mainRepoTargetParser); + this.noOutputFormatter = noOutputFormatter; } @Override @@ -66,6 +83,7 @@ protected ConfiguredTargetQueryEnvironment getQueryEnvironment( request.getTopLevelArtifactContext(), request .getOptions(CqueryOptions.class) - .getLabelPrinter(starlarkSemantics, mainRepoTargetParser.getRepoMapping())); + .getLabelPrinter(starlarkSemantics, mainRepoTargetParser.getRepoMapping()), + noOutputFormatter); } } diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java index b14ebb2ef8c0e9..1ec7f14c4b9791 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java @@ -66,6 +66,7 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; @@ -94,6 +95,12 @@ public class ConfiguredTargetQueryEnvironment extends PostAnalysisQueryEnvironme private final ConfiguredTargetAccessor accessor; + /** + * Only passed when this is a call from a non query command like Fetch or Vendor, where we don't + * need the output printed + */ + private Optional> noOutputFormatter; + /** * F Stores every configuration in the transitive closure of the build graph as a map from its * user-friendly hash to the configuration itself. @@ -157,7 +164,8 @@ public ConfiguredTargetQueryEnvironment( Supplier walkableGraphSupplier, CqueryOptions cqueryOptions, TopLevelArtifactContext topLevelArtifactContext, - LabelPrinter labelPrinter) + LabelPrinter labelPrinter, + Optional> noOutputFormatter) throws InterruptedException { this( keepGoing, @@ -172,6 +180,7 @@ public ConfiguredTargetQueryEnvironment( topLevelArtifactContext, labelPrinter); this.cqueryOptions = cqueryOptions; + this.noOutputFormatter = noOutputFormatter; } private static ImmutableList populateFunctions() { @@ -209,78 +218,112 @@ private static ImmutableMap getTransitiveConfig throws QueryException, InterruptedException { AspectResolver aspectResolver = cqueryOptions.aspectDeps.createResolver(packageManager, eventHandler); - return ImmutableList.of( - new LabelAndConfigurationOutputFormatterCallback( - eventHandler, cqueryOptions, out, skyframeExecutor, accessor, true, getLabelPrinter()), - new LabelAndConfigurationOutputFormatterCallback( - eventHandler, cqueryOptions, out, skyframeExecutor, accessor, false, getLabelPrinter()), - new TransitionsOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - ruleClassProvider, - getLabelPrinter()), - new ProtoOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - aspectResolver, - OutputType.BINARY, - ruleClassProvider, - getLabelPrinter()), - new ProtoOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - aspectResolver, - OutputType.DELIMITED_BINARY, - ruleClassProvider, - labelPrinter), - new ProtoOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - aspectResolver, - OutputType.TEXT, - ruleClassProvider, - getLabelPrinter()), - new ProtoOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - aspectResolver, - OutputType.JSON, - ruleClassProvider, - getLabelPrinter()), - new BuildOutputFormatterCallback( - eventHandler, cqueryOptions, out, skyframeExecutor, accessor, getLabelPrinter()), - new GraphOutputFormatterCallback( - eventHandler, - cqueryOptions, - out, - skyframeExecutor, - accessor, - kct -> getFwdDeps(ImmutableList.of(kct)), - getLabelPrinter()), - new StarlarkOutputFormatterCallback( - eventHandler, cqueryOptions, out, skyframeExecutor, accessor, starlarkSemantics), - new FilesOutputFormatterCallback( - eventHandler, cqueryOptions, out, skyframeExecutor, accessor, topLevelArtifactContext)); + ImmutableList.Builder> formatters = + ImmutableList.>builder() + .add( + new LabelAndConfigurationOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + true, + getLabelPrinter()), + new LabelAndConfigurationOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + false, + getLabelPrinter()), + new TransitionsOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + ruleClassProvider, + getLabelPrinter()), + new ProtoOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + aspectResolver, + OutputType.BINARY, + ruleClassProvider, + getLabelPrinter()), + new ProtoOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + aspectResolver, + OutputType.DELIMITED_BINARY, + ruleClassProvider, + labelPrinter), + new ProtoOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + aspectResolver, + OutputType.TEXT, + ruleClassProvider, + getLabelPrinter()), + new ProtoOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + aspectResolver, + OutputType.JSON, + ruleClassProvider, + getLabelPrinter()), + new BuildOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + getLabelPrinter()), + new GraphOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + kct -> getFwdDeps(ImmutableList.of(kct)), + getLabelPrinter()), + new StarlarkOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + starlarkSemantics), + new FilesOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + topLevelArtifactContext)); + + if (noOutputFormatter.isPresent()) { + formatters.add(noOutputFormatter.get()); + } + return formatters.build(); } @Override public String getOutputFormat() { - return cqueryOptions.outputFormat; + return noOutputFormatter.isPresent() ? "no_output" : cqueryOptions.outputFormat; } @Override diff --git a/src/test/py/bazel/BUILD b/src/test/py/bazel/BUILD index ea335ac97760ab..40c922817adcf2 100644 --- a/src/test/py/bazel/BUILD +++ b/src/test/py/bazel/BUILD @@ -305,6 +305,10 @@ py_test( size = "medium", srcs = ["bzlmod/bazel_fetch_test.py"], data = ["//tools/build_defs/repo:http_src"], + shard_count = 5, + tags = [ + "requires-network", + ], deps = [ ":bzlmod_test_utils", ":test_base", diff --git a/src/test/py/bazel/bzlmod/bazel_fetch_test.py b/src/test/py/bazel/bzlmod/bazel_fetch_test.py index 072caedba197e0..cec2f7dc10f05c 100644 --- a/src/test/py/bazel/bzlmod/bazel_fetch_test.py +++ b/src/test/py/bazel/bzlmod/bazel_fetch_test.py @@ -37,6 +37,7 @@ def setUp(self): 'common --noenable_workspace', 'common --experimental_isolated_extension_usages', 'common --registry=' + self.main_registry.getURL(), + 'common --registry=https://bcr.bazel.build', 'common --verbose_failures', # Set an explicit Java language version 'common --java_language_version=8', @@ -261,6 +262,43 @@ def testForceFetch(self): _, _, stderr = self.RunBazel(['fetch', '--repo=@hello', '--force']) self.assertIn('No more Orange Juice!', ''.join(stderr)) + def testFetchTarget(self): + self.main_registry.createCcModule('aaa', '1.0').createCcModule( + 'bbb', '1.0', {'aaa': '1.0'} + ) + self.ScratchFile( + 'MODULE.bazel', + [ + 'bazel_dep(name = "bbb", version = "1.0")', + ], + ) + self.ScratchFile( + 'BUILD', + [ + 'cc_binary(', + ' name = "main",', + ' srcs = ["main.cc"],', + ' deps = [', + ' "@bbb//:lib_bbb",', + ' ],', + ')', + ], + ) + self.ScratchFile( + 'main.cc', + [ + '#include "aaa.h"', + 'int main() {', + ' hello_aaa("Hello there!");', + '}', + ], + ) + self.RunBazel(['fetch', '//:main']) + # If we can run the target with --nofetch, this means we successfully + # fetched all its needed repos + _, stdout, _ = self.RunBazel(['run', '//:main', '--nofetch']) + self.assertIn('Hello there! => aaa@1.0', stdout) + if __name__ == '__main__': absltest.main() diff --git a/src/test/py/bazel/bzlmod/external_repo_completion_test.py b/src/test/py/bazel/bzlmod/external_repo_completion_test.py index ac5f6991bd53f7..95bceed06ae9c9 100644 --- a/src/test/py/bazel/bzlmod/external_repo_completion_test.py +++ b/src/test/py/bazel/bzlmod/external_repo_completion_test.py @@ -139,7 +139,7 @@ def setUp(self): self.main_registry.createLocalPathModule('ext', '1.0', 'ext') scratchFile( self.projects_dir.joinpath('ext', 'BUILD'), - ['cc_library(name="lib_ext")'], + ['cc_library(name="lib_ext", visibility = ["//visibility:public"])'], ) scratchFile( self.projects_dir.joinpath('ext', 'tools', 'BUILD'), @@ -153,7 +153,7 @@ def setUp(self): self.main_registry.createLocalPathModule('ext2', '1.0', 'ext2') scratchFile( self.projects_dir.joinpath('ext2', 'BUILD'), - ['cc_library(name="lib_ext2")'], + ['cc_library(name="lib_ext2", visibility = ["//visibility:public"])'], ) scratchFile(self.projects_dir.joinpath('ext2', 'ext.bzl'), ext_src)