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() {