Pass --no-filter and --no-tags in git download commands In partial clone checkouts (e.g. --filter=blob:none or blob:limit=10k), fetching a change ref without explicit filter overrides can omit blobs for the incoming change if the remote matches a configured promisor remote. Subsequent checkout, cherry-pick, or reset operations then trigger on-demand unadvertised object fetches (POST /git-upload-pack with 'want <blob_sha>'), which can cause expensive server-side reachability walks and timeouts. Additionally, omitting --no-tags causes git fetch and git pull to request refs/tags/ and perform automated tag following and backfilling across remote tags. Pass --no-filter and --no-tags in GitDownloadCommand for all git fetch download commands (Branch, Checkout, Cherry Pick, Format Patch, and Reset To), and pass --no-tags in PullCommand (as git pull forwards --no-tags to git fetch but does not accept --no-filter). TAG=agy CONV=e5a86656-4920-42a4-8645-c41d9f59a203 Google-Bug-Id: b/532920848 Release-Notes: Pass --no-filter and --no-tags in git download commands Change-Id: Icdf55d95fa8136ae66a3bad50297df6f51226582
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java index 9dc2b68..72fb10e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java
@@ -33,10 +33,7 @@ @Override String getCommand(String url, String ref, String id) { - return "git fetch " - + QuoteUtil.quote(url) - + " " - + ref + return getGitFetch(url, ref) + " && " + getGitCheckout("-b change-") + id.replaceAll("/", "-")
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java index c9be564..b6f8a4e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java
@@ -33,13 +33,7 @@ @Override String getCommand(String url, String ref, String id) { - return "git fetch " - + QuoteUtil.quote(url) - + " " - + ref - + " && " - + getGitCheckout() - + "FETCH_HEAD"; + return getGitFetch(url, ref) + " && " + getGitCheckout() + "FETCH_HEAD"; } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java index bb6d4f2..0f22031 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java
@@ -33,7 +33,7 @@ @Override String getCommand(String url, String ref, String id) { - return "git fetch " + QuoteUtil.quote(url) + " " + ref + " && git cherry-pick FETCH_HEAD"; + return getGitFetch(url, ref) + " && git cherry-pick FETCH_HEAD"; } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java index 10d08ef..6221f6c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java
@@ -33,10 +33,6 @@ @Override String getCommand(String url, String ref, String id) { - return "git fetch " - + QuoteUtil.quote(url) - + " " - + ref - + " && git format-patch -1 --stdout FETCH_HEAD"; + return getGitFetch(url, ref) + " && git format-patch -1 --stdout FETCH_HEAD"; } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java index e2867c7..ade4d7b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java
@@ -97,6 +97,10 @@ return null; } + protected String getGitFetch(String url, String ref) { + return "git fetch --no-filter --no-tags " + QuoteUtil.quote(url) + " " + ref; + } + protected String getGitCheckout() { return getGitCheckout(""); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java index 4358b09..adef4f1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java
@@ -33,6 +33,6 @@ @Override String getCommand(String url, String ref, String id) { - return "git pull " + recurseSubmodulesFlag + QuoteUtil.quote(url) + " " + ref; + return "git pull --no-tags " + recurseSubmodulesFlag + QuoteUtil.quote(url) + " " + ref; } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/ResetCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/ResetCommand.java index 2fa79c3..1f918dd 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/download/command/ResetCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/ResetCommand.java
@@ -33,12 +33,6 @@ @Override String getCommand(String url, String ref, String id) { - return "git fetch " - + QuoteUtil.quote(url) - + " " - + ref - + " && git reset " - + recurseSubmodulesFlag - + "--hard FETCH_HEAD"; + return getGitFetch(url, ref) + " && git reset " + recurseSubmodulesFlag + "--hard FETCH_HEAD"; } }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/BranchCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/BranchCommandTest.java index 9150a3c..3bf071e 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/download/command/BranchCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/BranchCommandTest.java
@@ -27,7 +27,7 @@ private static final String TEST_REF = "origin/main"; private static final String TEST_ID = "1234"; private static final String CHECKOUT_COMMAND_PREFIX = - "git fetch " + TEST_URL + " " + TEST_REF + " && "; + "git fetch --no-filter --no-tags " + TEST_URL + " " + TEST_REF + " && "; @Test public void buildBranchCommand() {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommandTest.java index 3fc7e4d..67b28fe 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommandTest.java
@@ -27,7 +27,7 @@ private static final String TEST_REF = "origin/main"; private static final String TEST_ID = "none"; private static final String CHECKOUT_COMMAND_PREFIX = - "git fetch " + TEST_URL + " " + TEST_REF + " && "; + "git fetch --no-filter --no-tags " + TEST_URL + " " + TEST_REF + " && "; @Test public void buildCheckoutCommand() {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommandTest.java new file mode 100644 index 0000000..82f96fe --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommandTest.java
@@ -0,0 +1,53 @@ +// Copyright (C) 2026 The Android Open Source Project +// +// 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. +package com.googlesource.gerrit.plugins.download.command; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + +import com.google.gerrit.server.config.DownloadConfig; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.googlesource.gerrit.plugins.download.DownloadCommandTest; +import org.eclipse.jgit.lib.Config; +import org.junit.Test; + +public class CherryPickCommandTest extends DownloadCommandTest { + private static final String TEST_URL = "unit.test/"; + private static final String TEST_REF = "origin/main"; + private static final String TEST_ID = "none"; + private static final String CHERRY_PICK_COMMAND_PREFIX = + "git fetch --no-filter --no-tags " + TEST_URL + " " + TEST_REF + " && "; + + @Test + public void buildCherryPickCommand() { + CherryPickCommand cherryPickCommand = newCherryPickCommand(defaultGerritConfig()); + + String actual = cherryPickCommand.getCommand(TEST_URL, TEST_REF, TEST_ID); + + assertThat(actual).isEqualTo(CHERRY_PICK_COMMAND_PREFIX + "git cherry-pick FETCH_HEAD"); + } + + private CherryPickCommand newCherryPickCommand(Config cfg) { + GitRepositoryManager gitRepositoryManagerMock = mock(GitRepositoryManager.class); + + return new CherryPickCommand(cfg, new DownloadConfig(cfg), gitRepositoryManagerMock); + } + + private Config defaultGerritConfig() { + Config cfg = new Config(); + cfg.setString("download", null, "command", "cherry_pick"); + + return cfg; + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommandTest.java new file mode 100644 index 0000000..d2b6d70 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommandTest.java
@@ -0,0 +1,54 @@ +// Copyright (C) 2026 The Android Open Source Project +// +// 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. +package com.googlesource.gerrit.plugins.download.command; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + +import com.google.gerrit.server.config.DownloadConfig; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.googlesource.gerrit.plugins.download.DownloadCommandTest; +import org.eclipse.jgit.lib.Config; +import org.junit.Test; + +public class FormatPatchCommandTest extends DownloadCommandTest { + private static final String TEST_URL = "unit.test/"; + private static final String TEST_REF = "origin/main"; + private static final String TEST_ID = "none"; + private static final String FORMAT_PATCH_COMMAND_PREFIX = + "git fetch --no-filter --no-tags " + TEST_URL + " " + TEST_REF + " && "; + + @Test + public void buildFormatPatchCommand() { + FormatPatchCommand formatPatchCommand = newFormatPatchCommand(defaultGerritConfig()); + + String actual = formatPatchCommand.getCommand(TEST_URL, TEST_REF, TEST_ID); + + assertThat(actual) + .isEqualTo(FORMAT_PATCH_COMMAND_PREFIX + "git format-patch -1 --stdout FETCH_HEAD"); + } + + private FormatPatchCommand newFormatPatchCommand(Config cfg) { + GitRepositoryManager gitRepositoryManagerMock = mock(GitRepositoryManager.class); + + return new FormatPatchCommand(cfg, new DownloadConfig(cfg), gitRepositoryManagerMock); + } + + private Config defaultGerritConfig() { + Config cfg = new Config(); + cfg.setString("download", null, "command", "format_patch"); + + return cfg; + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/PullCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/PullCommandTest.java index e98d6a0..3824982 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/download/command/PullCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/PullCommandTest.java
@@ -34,7 +34,7 @@ String actual = pullCommand.getCommand(TEST_URL, TEST_REF, TEST_ID); - assertThat(actual).isEqualTo("git pull " + PULL_COMMAND_SUFFIX); + assertThat(actual).isEqualTo("git pull --no-tags " + PULL_COMMAND_SUFFIX); } @Test @@ -45,7 +45,7 @@ String actual = pullCommand.getCommand(TEST_URL, TEST_REF, TEST_ID); - assertThat(actual).isEqualTo("git pull --recurse-submodules " + PULL_COMMAND_SUFFIX); + assertThat(actual).isEqualTo("git pull --no-tags --recurse-submodules " + PULL_COMMAND_SUFFIX); } private PullCommand newPullCommand(Config cfg) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/download/command/ResetCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/download/command/ResetCommandTest.java index 81d15df..f1e2a3f 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/download/command/ResetCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/download/command/ResetCommandTest.java
@@ -27,7 +27,7 @@ private static final String TEST_REF = "origin/main"; private static final String TEST_ID = "none"; private static final String RESET_COMMAND_PREFIX = - "git fetch " + TEST_URL + " " + TEST_REF + " && "; + "git fetch --no-filter --no-tags " + TEST_URL + " " + TEST_REF + " && "; @Test public void buildResetCommand() {