diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java index 8d4e942185b91d..183a6241b62040 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java @@ -180,7 +180,7 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti // fetch anyway. So the only task remaining is to record the use of "bind" for whoever // collects resolved information. env.getReporter().post(resolveBind(rule)); - } else if (shouldSync(rule, syncOptions.configure)) { + } else if (shouldSync(rule, syncOptions)) { // TODO(aehlig): avoid the detour of serializing and then parsing the repository name try { repositoriesToFetch.add( @@ -221,12 +221,16 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti return BlazeCommandResult.exitCode(exitCode); } - private static boolean shouldSync(Rule rule, boolean configure) { + private static boolean shouldSync(Rule rule, SyncOptions options) { if (!rule.getRuleClassObject().getWorkspaceOnly()) { // We should only sync workspace rules return false; } - if (configure) { + if (options.only != null && !options.only.isEmpty() && !options.only.contains(rule.getName())) { + // There is a whitelist of what to sync, but the rule is not in this white list + return false; + } + if (options.configure) { // If this is only a configure run, only sync Starlark rules that // declare themselves as configure-like. return SkylarkRepositoryFunction.isConfigureRule(rule); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncOptions.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncOptions.java index 0397921b86cf96..a577cfe6dbaf5f 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncOptions.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncOptions.java @@ -17,6 +17,7 @@ import com.google.devtools.common.options.OptionDocumentationCategory; import com.google.devtools.common.options.OptionEffectTag; import com.google.devtools.common.options.OptionsBase; +import java.util.List; /** Defines the options specific to Bazel's sync command */ public class SyncOptions extends OptionsBase { @@ -27,4 +28,15 @@ public class SyncOptions extends OptionsBase { effectTags = {OptionEffectTag.CHANGES_INPUTS}, help = "Only sync repositories marked as 'configure' for system-configuration purpose.") public boolean configure; + + @Option( + name = "only", + defaultValue = "null", + allowMultiple = true, + documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY, + effectTags = {OptionEffectTag.CHANGES_INPUTS}, + help = + "If this option is given, only sync the repositories specified with this option." + + " Still consider all (or all configure-like, of --configure is given) outdated.") + public List only; } diff --git a/src/test/shell/bazel/skylark_repository_test.sh b/src/test/shell/bazel/skylark_repository_test.sh index c5186e6ae135bb..d9701106d90819 100755 --- a/src/test/shell/bazel/skylark_repository_test.sh +++ b/src/test/shell/bazel/skylark_repository_test.sh @@ -1413,6 +1413,55 @@ EOF || fail "expected success after successful sync" } +function test_sync_only() { + # Set up two repositories that count how often they are fetched + cat >environ.bzl <<'EOF' +def environ(r_ctx, var): + return r_ctx.os.environ[var] if var in r_ctx.os.environ else "undefined" +EOF + cat <<'EOF' >bar.tpl +FOO=%{FOO} BAR=%{BAR} BAZ=%{BAZ} +EOF + write_environ_skylark "${TEST_TMPDIR}/executionFOO" "" + mv test.bzl testfoo.bzl + write_environ_skylark "${TEST_TMPDIR}/executionBAR" "" + mv test.bzl testbar.bzl + cat > WORKSPACE <<'EOF' +load("//:testfoo.bzl", foorepo="repo") +load("//:testbar.bzl", barrepo="repo") +foorepo(name="foo") +barrepo(name="bar") +EOF + touch BUILD + bazel clean --expunge + echo 0 > "${TEST_TMPDIR}/executionFOO" + echo 0 > "${TEST_TMPDIR}/executionBAR" + + # Normal sync should hit both repositories + echo; echo bazel sync; echo + bazel sync + assert_equals 1 $(cat "${TEST_TMPDIR}/executionFOO") + assert_equals 1 $(cat "${TEST_TMPDIR}/executionBAR") + + # Only foo + echo; echo bazel sync --only foo; echo + bazel sync --only foo + assert_equals 2 $(cat "${TEST_TMPDIR}/executionFOO") + assert_equals 1 $(cat "${TEST_TMPDIR}/executionBAR") + + # Only bar + echo; echo bazel sync --only bar; echo + bazel sync --only bar + assert_equals 2 $(cat "${TEST_TMPDIR}/executionFOO") + assert_equals 2 $(cat "${TEST_TMPDIR}/executionBAR") + + # Only bar + echo; echo bazel sync --only bar; echo + bazel sync --only bar + assert_equals 2 $(cat "${TEST_TMPDIR}/executionFOO") + assert_equals 3 $(cat "${TEST_TMPDIR}/executionBAR") +} + function test_download_failure_message() { # Regression test for #7850 # Verify that the for a failed downlaod, it is clearly indicated