diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index 223bdbd4b32de0..dd76cd90e7d6ab 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -2741,7 +2741,7 @@
"general": {
"bzlTransitiveDigest": "aazFN6GuLhvfkNKMuclv+T1HxL1E8g176trDl638NAs=",
"accumulatedFileDigests": {
- "@@//src/test/tools/bzlmod:MODULE.bazel.lock": "0a80fbbd4241dc7ccd3f7665029acd69a64c8d79fa49108c1c46ef778c857685",
+ "@@//src/test/tools/bzlmod:MODULE.bazel.lock": "07869ead2b4de601bf66b73683f003d2eb7308d5ab2467329c70283cb73d5614",
"@@//:MODULE.bazel": "15825821d543809fdc03e543f9c92a0ebfb3a53629e60c864f83566e1c41710d"
},
"envVariables": {},
@@ -2767,6 +2767,7 @@
"rules_license~0.0.7",
"rules_proto~5.3.0-21.7",
"rules_python~0.22.1",
+ "buildozer~6.4.0.2",
"platforms",
"protobuf~21.7",
"zlib~1.3",
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtensionContext.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtensionContext.java
index 0318ab1a55ca87..491427a6d3263a 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtensionContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleExtensionContext.java
@@ -160,7 +160,7 @@ public boolean rootModuleHasNonDevDependency() {
+ " dependencies of the root module. If the root module imports additional"
+ " repositories or does not import all of these repositories via use_repo
, Bazel"
- + " will print a warning when the extension is evaluated, instructing the user"
+ + " will print a warning when the extension is evaluated, instructing the user"
+ " to run bazel mod tidy
to fix the use_repo
calls"
+ " automatically.
If one of root_module_direct_deps
and"
+ " will print a warning and a fixup command when the extension is"
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/ModCommand.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/ModCommand.java
index 7a683bdb23b6a2..141603e41363b6 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/commands/ModCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/ModCommand.java
@@ -119,9 +119,6 @@ public final class ModCommand implements BlazeCommand {
public static final String NAME = "mod";
- private final ArrayList fixupEvents = new ArrayList<>();
- @Nullable private BazelModuleResolutionEvent bazelModuleResolutionEvent = null;
-
@Override
public void editOptions(OptionsParser optionsParser) {
try {
@@ -137,7 +134,6 @@ public void editOptions(OptionsParser optionsParser) {
@Override
public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
- env.getEventBus().register(this);
env.getEventBus()
.post(
new NoBuildEvent(
@@ -146,13 +142,7 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
/* separateFinishedEvent= */ true,
/* showProgress= */ true,
/* id= */ null));
- BlazeCommandResult result;
- try {
- result = execInternal(env, options);
- } finally {
- fixupEvents.clear();
- bazelModuleResolutionEvent = null;
- }
+ BlazeCommandResult result = execInternal(env, options);
env.getEventBus()
.post(
new NoBuildRequestFinishedEvent(
@@ -207,6 +197,7 @@ private BlazeCommandResult execInternal(CommandEnvironment env, OptionsParsingRe
@Nullable BazelModuleInspectorValue moduleInspector;
@Nullable BazelModTidyValue modTidyValue;
ImmutableList repoMappingValues;
+ TidyEventRecorder tidyEventRecorder = new TidyEventRecorder();
SkyframeExecutor skyframeExecutor = env.getSkyframeExecutor();
LoadingPhaseThreadsOption threadsOption = options.getOptions(LoadingPhaseThreadsOption.class);
@@ -225,6 +216,7 @@ private BlazeCommandResult execInternal(CommandEnvironment env, OptionsParsingRe
keys.addAll(repoMappingKeys);
} else if (subcommand.equals(ModSubcommand.TIDY)) {
keys.add(BazelModTidyValue.KEY);
+ env.getEventBus().register(tidyEventRecorder);
} else {
keys.add(BazelDepGraphValue.KEY, BazelModuleInspectorValue.KEY);
}
@@ -289,9 +281,9 @@ private BlazeCommandResult execInternal(CommandEnvironment env, OptionsParsingRe
// tidy doesn't take extra arguments.
if (!args.isEmpty()) {
return reportAndCreateFailureResult(
- env, "the 'fix' command doesn't take extra arguments", Code.TOO_MANY_ARGUMENTS);
+ env, "the 'tidy' command doesn't take extra arguments", Code.TOO_MANY_ARGUMENTS);
}
- return runTidy(env, modTidyValue);
+ return runTidy(env, modTidyValue, tidyEventRecorder);
}
// Extract and check the --base_module argument first to use it when parsing the other args.
@@ -563,14 +555,30 @@ private BlazeCommandResult execInternal(CommandEnvironment env, OptionsParsingRe
return BlazeCommandResult.success();
}
- private BlazeCommandResult runTidy(CommandEnvironment env, BazelModTidyValue modTidyValue) {
+ private static class TidyEventRecorder {
+ final List fixupEvents = new ArrayList<>();
+ @Nullable BazelModuleResolutionEvent bazelModuleResolutionEvent;
+
+ @Subscribe
+ public void fixupGenerated(RootModuleFileFixupEvent event) {
+ fixupEvents.add(event);
+ }
+
+ @Subscribe
+ public void bazelModuleResolved(BazelModuleResolutionEvent event) {
+ bazelModuleResolutionEvent = event;
+ }
+ }
+
+ private BlazeCommandResult runTidy(
+ CommandEnvironment env, BazelModTidyValue modTidyValue, TidyEventRecorder eventRecorder) {
CommandBuilder buildozerCommand =
new CommandBuilder()
.setWorkingDir(env.getWorkspace())
.addArg(modTidyValue.buildozer().getPathString())
.addArgs(
Stream.concat(
- fixupEvents.stream()
+ eventRecorder.fixupEvents.stream()
.map(RootModuleFileFixupEvent::getBuildozerCommands)
.flatMap(Collection::stream),
Stream.of("format"))
@@ -590,7 +598,7 @@ private BlazeCommandResult runTidy(CommandEnvironment env, BazelModTidyValue mod
Code.BUILDOZER_FAILED);
}
- for (RootModuleFileFixupEvent fixupEvent : fixupEvents) {
+ for (RootModuleFileFixupEvent fixupEvent : eventRecorder.fixupEvents) {
env.getReporter().handle(Event.info(fixupEvent.getSuccessMessage()));
}
@@ -628,13 +636,15 @@ private BlazeCommandResult runTidy(CommandEnvironment env, BazelModTidyValue mod
"Unexpected error parsing module file after running buildozer: " + e.getMessage(),
Code.BUILDOZER_FAILED);
}
+ // BazelModuleResolutionEvent is cached by Skyframe and thus always emitted.
BazelModuleResolutionEvent updatedModuleResolutionEvent =
BazelModuleResolutionEvent.create(
- bazelModuleResolutionEvent.getOnDiskLockfileValue(),
- bazelModuleResolutionEvent
+ eventRecorder.bazelModuleResolutionEvent.getOnDiskLockfileValue(),
+ eventRecorder
+ .bazelModuleResolutionEvent
.getResolutionOnlyLockfileValue()
.withShallowlyReplacedRootModule(newRootModuleFileValue),
- bazelModuleResolutionEvent.getExtensionUsagesById());
+ eventRecorder.bazelModuleResolutionEvent.getExtensionUsagesById());
env.getReporter().post(updatedModuleResolutionEvent);
}
@@ -710,14 +720,4 @@ public static void dumpRepoMappings(List repoMappings, W
}
writer.flush();
}
-
- @Subscribe
- public void fixupGenerated(RootModuleFileFixupEvent event) {
- fixupEvents.add(event);
- }
-
- @Subscribe
- public void bazelModuleResolved(BazelModuleResolutionEvent event) {
- bazelModuleResolutionEvent = event;
- }
}