Merge branch 'stable-3.3' into stable-3.4

* stable-3.3:
  Fix the default logic in managing refs-filter
  Reuse Gerrit code for head update
  Add HEAD update REST API endpoint
  Add project initialisation during fetch REST Api call
  Add project delete REST API endpoint

Change-Id: I00d81c7eadc25c8f1d3b55b6479c94630804e7f2
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
index 0e4ace1..61f2a64 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
@@ -46,6 +46,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
+import org.apache.http.client.ClientProtocolException;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.transport.URIish;
@@ -232,17 +233,8 @@
           FetchRestApiClient fetchClient = fetchClientFactory.create(source);
 
           HttpResult result = fetchClient.callSendObject(project, refName, revision, uri);
-          if (!result.isSuccessful()
-              && source.isCreateMissingRepositories()
-              && result.isProjectMissing(project)) {
-            HttpResult initProjectResult = fetchClient.initProject(project, uri);
-            if (initProjectResult.isSuccessful()) {
-              result = fetchClient.callFetch(project, "refs/*", uri);
-            } else {
-              String errorMessage =
-                  initProjectResult.getMessage().map(e -> " - Error: " + e).orElse("");
-              repLog.error("Cannot create project " + project + errorMessage);
-            }
+          if (isProjectMissing(result, project) && source.isCreateMissingRepositories()) {
+            result = initProject(project, uri, fetchClient, result);
           }
           if (!result.isSuccessful()) {
             repLog.warn(
@@ -275,8 +267,10 @@
         try {
           URIish uri = new URIish(apiUrl);
           FetchRestApiClient fetchClient = fetchClientFactory.create(source);
-
           HttpResult result = fetchClient.callFetch(project, refName, uri);
+          if (isProjectMissing(result, project) && source.isCreateMissingRepositories()) {
+            result = initProject(project, uri, fetchClient, result);
+          }
           if (!result.isSuccessful()) {
             stateLog.warn(
                 String.format(
@@ -302,6 +296,23 @@
     return maxRetries == 0 || attempt < maxRetries;
   }
 
+  private Boolean isProjectMissing(HttpResult result, Project.NameKey project) {
+    return !result.isSuccessful() && result.isProjectMissing(project);
+  }
+
+  private HttpResult initProject(
+      Project.NameKey project, URIish uri, FetchRestApiClient fetchClient, HttpResult result)
+      throws IOException, ClientProtocolException {
+    HttpResult initProjectResult = fetchClient.initProject(project, uri);
+    if (initProjectResult.isSuccessful()) {
+      result = fetchClient.callFetch(project, "refs/*", uri);
+    } else {
+      String errorMessage = initProjectResult.getMessage().map(e -> " - Error: " + e).orElse("");
+      repLog.error("Cannot create project " + project + errorMessage);
+    }
+    return result;
+  }
+
   private void fireBeforeStartupEvents() {
     Set<String> eventsReplayed = new HashSet<>();
     for (ReferenceUpdatedEvent event : beforeStartupEventsQueue) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
index f94f49b..e7b3a7f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationApiModule.java
@@ -27,8 +27,12 @@
   protected void configure() {
     bind(FetchAction.class).in(Scopes.SINGLETON);
     bind(ApplyObjectAction.class).in(Scopes.SINGLETON);
+    bind(ProjectDeletionAction.class).in(Scopes.SINGLETON);
+    bind(UpdateHeadAction.class).in(Scopes.SINGLETON);
     post(PROJECT_KIND, "fetch").to(FetchAction.class);
     post(PROJECT_KIND, "apply-object").to(ApplyObjectAction.class);
+    delete(PROJECT_KIND, "delete-project").to(ProjectDeletionAction.class);
+    put(PROJECT_KIND, "HEAD").to(UpdateHeadAction.class);
 
     bind(FetchPreconditions.class).in(Scopes.SINGLETON);
     bind(CapabilityDefinition.class)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
index 44dd3bb..4af2bf7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
@@ -27,6 +27,7 @@
 
 import com.google.common.base.Splitter;
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.api.projects.HeadInput;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -80,6 +81,7 @@
   private ProjectsCollection projectsCollection;
   private Gson gson;
   private Provider<CurrentUser> userProvider;
+  private String pluginName;
 
   @Inject
   public PullReplicationFilter(
@@ -89,7 +91,8 @@
       UpdateHeadAction updateHEADAction,
       ProjectDeletionAction projectDeletionAction,
       ProjectsCollection projectsCollection,
-      Provider<CurrentUser> userProvider) {
+      Provider<CurrentUser> userProvider,
+      @PluginName String pluginName) {
     this.fetchAction = fetchAction;
     this.applyObjectAction = applyObjectAction;
     this.projectInitializationAction = projectInitializationAction;
@@ -97,6 +100,7 @@
     this.projectDeletionAction = projectDeletionAction;
     this.projectsCollection = projectsCollection;
     this.userProvider = userProvider;
+    this.pluginName = pluginName;
     this.gson = OutputFormat.JSON.newGsonBuilder().create();
   }
 
@@ -303,7 +307,7 @@
   }
 
   private boolean isDeleteProjectAction(HttpServletRequest httpRequest) {
-    return httpRequest.getRequestURI().matches("(/a)?/projects/[^/]+$")
+    return httpRequest.getRequestURI().endsWith(String.format("%s~delete-project", pluginName))
         && "DELETE".equals(httpRequest.getMethod());
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java
index 4195435..ae9c072 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java
@@ -14,66 +14,28 @@
 
 package com.googlesource.gerrit.plugins.replication.pull.api;
 
-import com.google.common.base.Strings;
-import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.api.projects.HeadInput;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.RefPermission;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.restapi.project.SetHead;
 import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.replication.LocalFS;
-import com.googlesource.gerrit.plugins.replication.pull.GerritConfigOps;
-import java.util.Optional;
-import org.eclipse.jgit.transport.URIish;
 
-@Singleton
 public class UpdateHeadAction implements RestModifyView<ProjectResource, HeadInput> {
-  private final GerritConfigOps gerritConfigOps;
-  private final PermissionBackend permissionBackend;
+
+  private final SetHead setHead;
 
   @Inject
-  UpdateHeadAction(GerritConfigOps gerritConfigOps, PermissionBackend permissionBackend) {
-    this.gerritConfigOps = gerritConfigOps;
-    this.permissionBackend = permissionBackend;
+  public UpdateHeadAction(SetHead setHead) {
+    this.setHead = setHead;
   }
 
   @Override
-  public Response<?> apply(ProjectResource projectResource, HeadInput input)
+  public Response<?> apply(ProjectResource resource, HeadInput input)
       throws AuthException, BadRequestException, ResourceConflictException, Exception {
-    if (input == null || Strings.isNullOrEmpty(input.ref)) {
-      throw new BadRequestException("ref required");
-    }
-    String ref = RefNames.fullName(input.ref);
-
-    permissionBackend
-        .user(projectResource.getUser())
-        .project(projectResource.getNameKey())
-        .ref(ref)
-        .check(RefPermission.SET_HEAD);
-
-    // TODO: the .git suffix should not be added here, but rather it should be
-    //  dealt with by the caller, honouring the naming style from the
-    //  replication.config (Issue 15221)
-    Optional<URIish> maybeRepo =
-        gerritConfigOps.getGitRepositoryURI(String.format("%s.git", projectResource.getName()));
-
-    if (maybeRepo.isPresent()) {
-      if (new LocalFS(maybeRepo.get()).updateHead(projectResource.getNameKey(), ref)) {
-        return Response.ok(ref);
-      }
-      throw new UnprocessableEntityException(
-          String.format(
-              "Could not update HEAD of repo %s to ref %s", projectResource.getName(), ref));
-    }
-    throw new ResourceNotFoundException(
-        String.format("Could not compute URL for repo: %s", projectResource.getName()));
+    return setHead.apply(resource, input);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
index df97609..a916a7c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClient.java
@@ -190,10 +190,10 @@
   }
 
   String getProjectDeletionUrl(String projectName) {
-    return String.format("a/projects/%s", Url.encode(projectName));
+    return String.format("a/projects/%s/%s~delete-project", Url.encode(projectName), pluginName);
   }
 
   String getProjectUpdateHeadUrl(String projectName) {
-    return String.format("a/projects/%s/HEAD", Url.encode(projectName));
+    return String.format("a/projects/%s/%s~HEAD", Url.encode(projectName), pluginName);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/ExcludedRefsFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/ExcludedRefsFilter.java
index f2e4ab3..63755b4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/ExcludedRefsFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/ExcludedRefsFilter.java
@@ -24,21 +24,8 @@
 
 @Singleton
 public class ExcludedRefsFilter extends RefsFilter {
-  @Inject
-  public ExcludedRefsFilter(ReplicationConfig replicationConfig) {
-    super(replicationConfig);
-  }
-
-  @Override
-  protected List<String> getRefNamePatterns(Config cfg) {
-    return ImmutableList.<String>builder()
-        .addAll(getDefaultExcludeRefPatterns())
-        .addAll(ImmutableList.copyOf(cfg.getStringList("replication", null, "excludeRefs")))
-        .build();
-  }
-
-  private List<String> getDefaultExcludeRefPatterns() {
-    return ImmutableList.of(
+  public static String[] DEFAULT_REPLICATION_EXCLUDE_REFS =
+      new String[] {
         RefNames.REFS_USERS + "*",
         RefNames.REFS_CONFIG,
         RefNames.REFS_SEQUENCES + "*",
@@ -46,6 +33,20 @@
         RefNames.REFS_GROUPS + "*",
         RefNames.REFS_GROUPNAMES,
         RefNames.REFS_CACHE_AUTOMERGE + "*",
-        RefNames.REFS_STARRED_CHANGES + "*");
+        RefNames.REFS_STARRED_CHANGES + "*"
+      };
+
+  @Inject
+  public ExcludedRefsFilter(ReplicationConfig replicationConfig) {
+    super(replicationConfig);
+  }
+
+  @Override
+  protected List<String> getRefNamePatterns(Config cfg) {
+    String[] replicationExcludeRefs = cfg.getStringList("replication", null, "excludeRefs");
+    if (replicationExcludeRefs.length == 0) {
+      replicationExcludeRefs = DEFAULT_REPLICATION_EXCLUDE_REFS;
+    }
+    return ImmutableList.copyOf(replicationExcludeRefs);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/RefsFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/RefsFilter.java
index 7ec19ea..7ab44f9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/RefsFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/RefsFilter.java
@@ -48,9 +48,6 @@
       throw new IllegalArgumentException(
           String.format("Ref name cannot be null or empty, but was %s", refName));
     }
-    if (refsPatterns.isEmpty()) {
-      return true;
-    }
 
     for (String pattern : refsPatterns) {
       if (matchesPattern(refName, pattern)) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/SyncRefsFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/SyncRefsFilter.java
index a069935..7d004f5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/SyncRefsFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/filter/SyncRefsFilter.java
@@ -30,6 +30,10 @@
 
   @Override
   protected List<String> getRefNamePatterns(Config cfg) {
-    return ImmutableList.copyOf(cfg.getStringList("replication", null, "syncRefs"));
+    String[] replicationSyncRefs = cfg.getStringList("replication", null, "syncRefs");
+    if (replicationSyncRefs.length == 0) {
+      replicationSyncRefs = new String[] {"*"};
+    }
+    return ImmutableList.copyOf(replicationSyncRefs);
   }
 }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 68c9001..b2470a4 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -169,7 +169,7 @@
     treated as single ref matches. So `foo/bar` matches only
     the ref `foo/bar`, but no other refs.
 
-    Following refs are always excluded from the git fetch calls:
+    By default, the following refs are excluded from the git fetch calls:
     - refs/users/*
     - refs/meta/config
     - refs/sequences/*
@@ -179,8 +179,6 @@
     - refs/cache-automerge/*
     - refs/starred-changes/*
 
-    By default, all other refs are included.
-
     Note that if you are using @PLUGIN@ together with multi-site, you should
     explicitly exclude `refs/multi-site/version` from being replicated.
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
index c2335e8..c5b1790 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
@@ -15,7 +15,6 @@
 package com.googlesource.gerrit.plugins.replication.pull;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
 import static java.util.stream.Collectors.toList;
 
 import com.google.common.flogger.FluentLogger;
@@ -38,11 +37,9 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.extensions.restapi.RestApiModule;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.project.ProjectResource;
-import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.replication.AutoReloadConfigDecorator;
@@ -83,28 +80,10 @@
   private FileBasedConfig config;
   private FileBasedConfig secureConfig;
 
-  static FakeDeleteProjectPlugin fakeDeleteProjectPlugin;
-
-  static class FakeDeleteModule extends AbstractModule {
-
-    @Override
-    public void configure() {
-      install(
-          new RestApiModule() {
-            @Override
-            public void configure() {
-              fakeDeleteProjectPlugin = new FakeDeleteProjectPlugin();
-              delete(PROJECT_KIND).toInstance(fakeDeleteProjectPlugin);
-            }
-          });
-    }
-  }
-
   @Override
   public void setUpTestPlugin() throws Exception {
     gitPath = sitePaths.site_path.resolve("git");
 
-    installPlugin("fakeDeleteProjectPlugin", FakeDeleteModule.class, null, null);
     config =
         new FileBasedConfig(sitePaths.etc_dir.resolve("replication.config").toFile(), FS.DETECTED);
     setReplicationSource(
@@ -278,12 +257,11 @@
             return NotifyHandling.NONE;
           }
         };
-
     for (ProjectDeletedListener l : deletedListeners) {
       l.onProjectDeleted(event);
     }
 
-    waitUntil(() -> fakeDeleteProjectPlugin.getDeleteEndpointCalls() == 1);
+    waitUntil(() -> !repoManager.list().contains(project));
   }
 
   @Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
index 78eb3f7..8402782 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
@@ -137,7 +137,7 @@
   public void shouldNotCallInitProjectWhenReplicateNewRepositoriesNotSet() throws IOException {
     Event event = new TestEvent("refs/changes/01/1/meta");
     when(httpResult.isSuccessful()).thenReturn(false);
-
+    when(httpResult.isProjectMissing(any())).thenReturn(true);
     when(source.isCreateMissingRepositories()).thenReturn(false);
 
     objectUnderTest.start();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
index 343ce66..34aaf8b 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ActionITBase.java
@@ -127,7 +127,6 @@
 
   protected HttpDelete createDeleteRequest() {
     HttpDelete delete = new HttpDelete(url);
-    delete.addHeader(new BasicHeader("Content-Type", "application/json"));
     return delete;
   }
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
index 4c09266..f5c8d4c 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectDeletionActionIT.java
@@ -31,6 +31,64 @@
   @Inject private ProjectOperations projectOperations;
 
   @Test
+  public void shouldReturnUnauthorizedForUserWithoutPermissions() throws Exception {
+    httpClientFactory
+        .create(source)
+        .execute(
+            createDeleteRequest(),
+            assertHttpResponseCode(HttpServletResponse.SC_UNAUTHORIZED),
+            getAnonymousContext());
+  }
+
+  @Test
+  public void shouldDeleteRepositoryWhenUserHasProjectDeletionCapabilities() throws Exception {
+    String testProjectName = project.get();
+    url = getURL(testProjectName);
+    httpClientFactory
+        .create(source)
+        .execute(
+            createDeleteRequest(),
+            assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+            getUserContext());
+
+    projectOperations
+        .project(allProjects)
+        .forUpdate()
+        .add(allowCapability(DELETE_PROJECT_PERMISSION).group(SystemGroupBackend.REGISTERED_USERS))
+        .update();
+
+    httpClientFactory
+        .create(source)
+        .execute(
+            createDeleteRequest(),
+            assertHttpResponseCode(HttpServletResponse.SC_OK),
+            getUserContext());
+  }
+
+  @Test
+  public void shouldReturnOKWhenProjectIsDeleted() throws Exception {
+    String testProjectName = project.get();
+    url = getURL(testProjectName);
+
+    httpClientFactory
+        .create(source)
+        .execute(
+            createDeleteRequest(), assertHttpResponseCode(HttpServletResponse.SC_OK), getContext());
+  }
+
+  @Test
+  public void shouldReturnInternalServerErrorIfProjectCannotBeDeleted() throws Exception {
+    url = getURL(INVALID_TEST_PROJECT_NAME);
+
+    httpClientFactory
+        .create(source)
+        .execute(
+            createDeleteRequest(),
+            assertHttpResponseCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR),
+            getContext());
+  }
+
+  @Test
   @GerritConfig(name = "container.replica", value = "true")
   public void shouldReturnUnauthorizedForUserWithoutPermissionsOnReplica() throws Exception {
     httpClientFactory
@@ -96,6 +154,8 @@
 
   @Override
   protected String getURL(String projectName) {
-    return String.format("%s/a/projects/%s", adminRestSession.url(), Url.encode(projectName));
+    return String.format(
+        "%s/a/projects/%s/pull-replication~delete-project",
+        adminRestSession.url(), Url.encode(projectName));
   }
 }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
index ed1eef4..a778049 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/client/FetchRestApiClientTest.java
@@ -376,7 +376,8 @@
 
     HttpDelete httpDelete = httpDeleteCaptor.getValue();
     assertThat(httpDelete.getURI().getHost()).isEqualTo("gerrit-host");
-    assertThat(httpDelete.getURI().getPath()).isEqualTo("/a/projects/test_repo");
+    assertThat(httpDelete.getURI().getPath())
+        .isEqualTo("/a/projects/test_repo/pull-replication~delete-project");
   }
 
   @Test
@@ -394,7 +395,7 @@
 
     assertThat(httpPut.getURI().getHost()).isEqualTo("gerrit-host");
     assertThat(httpPut.getURI().getPath())
-        .isEqualTo(String.format("/a/projects/%s/HEAD", projectName));
+        .isEqualTo(String.format("/a/projects/%s/pull-replication~HEAD", projectName));
     assertThat(payload).isEqualTo(String.format("{\"ref\": \"%s\"}", newHead));
   }