Use replication plugin API to update and access its config
Instead of directly modifying the replication plugin configuration files
in the `$site_path/etc` directory use new API. This guarantee that the
configuration will be stored and read in a correct format and location.
Bug: Issue 325000746
Change-Id: I9bde7e1148d932fb6861f51edb3521449ec20bef
diff --git a/github-plugin/BUILD b/github-plugin/BUILD
index 589f7c6..3ff3d06 100644
--- a/github-plugin/BUILD
+++ b/github-plugin/BUILD
@@ -30,6 +30,7 @@
resources = glob(["src/main/resources/**/*"]),
deps = [
":github-plugin-lib",
+ ":replication-api",
"//plugins/github/github-oauth:github-oauth-lib",
"@axis-jaxrpc//jar",
"@axis//jar",
@@ -76,7 +77,9 @@
":github-plugin__plugin",
"//javatests/com/google/gerrit/util/http/testutil",
"//plugins/github/github-oauth:github-oauth-lib",
+ "//plugins/replication:replication-api",
"@commons-io//jar",
+ "@github-api//jar",
],
)
@@ -93,3 +96,9 @@
neverlink = True,
exports = ["@lombok//jar"],
)
+
+java_library(
+ name = "replication-api",
+ neverlink = True,
+ exports = ["//plugins/replication:replication-api"],
+)
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
index 9bff585..991ba5a 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceModule.java
@@ -18,18 +18,13 @@
import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.events.EventListener;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gson.Gson;
import com.google.inject.AbstractModule;
-import com.google.inject.Inject;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
-import com.googlesource.gerrit.plugins.github.git.FanoutReplicationConfig;
-import com.googlesource.gerrit.plugins.github.git.FileBasedReplicationConfig;
-import com.googlesource.gerrit.plugins.github.git.ReplicationConfig;
import com.googlesource.gerrit.plugins.github.group.GitHubGroupBackend;
import com.googlesource.gerrit.plugins.github.group.GitHubGroupMembership;
import com.googlesource.gerrit.plugins.github.group.GitHubGroupsCache;
@@ -42,17 +37,9 @@
import com.googlesource.gerrit.plugins.github.replication.ReplicationStatusFlatFile;
import com.googlesource.gerrit.plugins.github.replication.ReplicationStatusListener;
import com.googlesource.gerrit.plugins.github.replication.ReplicationStatusStore;
-import java.nio.file.Files;
public class GuiceModule extends AbstractModule {
- private final SitePaths site;
-
- @Inject
- public GuiceModule(SitePaths site) {
- this.site = site;
- }
-
@Override
protected void configure() {
bind(new TypeLiteral<UserScopedProvider<GitHubLogin>>() {})
@@ -75,12 +62,6 @@
}
});
- if (Files.exists(site.etc_dir.resolve("replication"))) {
- bind(ReplicationConfig.class).to(FanoutReplicationConfig.class).in(Scopes.SINGLETON);
- } else {
- bind(ReplicationConfig.class).to(FileBasedReplicationConfig.class).in(Scopes.SINGLETON);
- }
-
bind(ReplicationStatusStore.class).to(ReplicationStatusFlatFile.class).in(Scopes.SINGLETON);
bind(Gson.class).toProvider(GerritGsonProvider.class);
}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FanoutReplicationConfig.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FanoutReplicationConfig.java
deleted file mode 100644
index 4a3bc4b..0000000
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FanoutReplicationConfig.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2020 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.github.git;
-
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-
-public class FanoutReplicationConfig implements ReplicationConfig {
- private final SitePaths site;
- private final FileBasedConfig secureConf;
-
- @Inject
- public FanoutReplicationConfig(final SitePaths site) {
- this.site = site;
- this.secureConf = new FileBasedConfig(site.secure_config.toFile(), FS.DETECTED);
- }
-
- @Override
- public void addSecureCredentials(String authUsername, String authToken)
- throws IOException, ConfigInvalidException {
- secureConf.load();
- secureConf.setString("remote", authUsername, "username", authUsername);
- secureConf.setString("remote", authUsername, "password", authToken);
- secureConf.save();
- }
-
- @Override
- public void addReplicationRemote(String githubUsername, String url, String projectName)
- throws IOException, ConfigInvalidException {
-
- FileBasedConfig replicationConf =
- new FileBasedConfig(
- new File(site.etc_dir.toFile(), String.format("replication/%s.config", githubUsername)),
- FS.DETECTED);
-
- replicationConf.load();
- String currentUrl = replicationConf.getString("remote", null, "url");
- if (currentUrl == null) {
- replicationConf.setString("remote", null, "url", url);
- }
- List<String> projects =
- new ArrayList<>(Arrays.asList(replicationConf.getStringList("remote", null, "projects")));
- projects.add(projectName);
- replicationConf.setStringList("remote", null, "projects", projects);
-
- String currentPushRefs = replicationConf.getString("remote", null, "push");
- if (currentPushRefs == null) {
- replicationConf.setString("remote", null, "push", "refs/*:refs/*");
- }
- replicationConf.save();
- }
-}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FileBasedReplicationConfig.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FileBasedReplicationConfig.java
deleted file mode 100644
index 842bde3..0000000
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/FileBasedReplicationConfig.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2013 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.github.git;
-
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-
-public class FileBasedReplicationConfig implements ReplicationConfig {
- private final FileBasedConfig secureConf;
- private final FileBasedConfig replicationConf;
-
- @Inject
- public FileBasedReplicationConfig(final SitePaths site) {
- replicationConf =
- new FileBasedConfig(new File(site.etc_dir.toFile(), "replication.config"), FS.DETECTED);
- secureConf = new FileBasedConfig(site.secure_config.toFile(), FS.DETECTED);
- }
-
- @Override
- public synchronized void addSecureCredentials(String authUsername, String authToken)
- throws IOException, ConfigInvalidException {
- secureConf.load();
- secureConf.setString("remote", authUsername, "username", authUsername);
- secureConf.setString("remote", authUsername, "password", authToken);
- secureConf.save();
- }
-
- @Override
- public synchronized void addReplicationRemote(String username, String url, String projectName)
- throws IOException, ConfigInvalidException {
- replicationConf.load();
- replicationConf.setString("remote", username, "url", url);
- List<String> projects =
- new ArrayList<>(
- Arrays.asList(replicationConf.getStringList("remote", username, "projects")));
- projects.add(projectName);
- replicationConf.setStringList("remote", username, "projects", projects);
- replicationConf.setString("remote", username, "push", "refs/*:refs/*");
- replicationConf.save();
- }
-}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
index 5109cd2..4e75d31 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicateProjectStep.java
@@ -13,22 +13,21 @@
// limitations under the License.
package com.googlesource.gerrit.plugins.github.git;
+import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.github.GitHubURL;
-import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
-import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+import com.googlesource.gerrit.plugins.replication.api.ReplicationRemotesApi;
import java.io.IOException;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ReplicateProjectStep extends ImportStep {
private static final Logger LOG = LoggerFactory.getLogger(ReplicateProjectStep.class);
- private final ReplicationConfig replicationConfig;
- private final String authUsername;
- private final String authToken;
- private final String gitHubUrl;
+ private final DynamicItem<ReplicationRemotesApi> replicationRemotesUpdaterItem;
+ private final ReplicationRemoteConfigBuilder remoteConfigBuilder;
public interface Factory {
ReplicateProjectStep create(
@@ -37,20 +36,17 @@
@Inject
public ReplicateProjectStep(
- final ReplicationConfig replicationConfig,
+ final DynamicItem<ReplicationRemotesApi> replicationRemotesUpdaterItem,
final GitHubRepository.Factory gitHubRepoFactory,
- final ScopedProvider<GitHubLogin> ghLoginProvider,
+ ReplicationRemoteConfigBuilder remoteConfigBuilder,
@GitHubURL String gitHubUrl,
@Assisted("organisation") String organisation,
@Assisted("name") String repository)
throws IOException {
super(gitHubUrl, organisation, repository, gitHubRepoFactory);
+ this.remoteConfigBuilder = remoteConfigBuilder;
LOG.debug("Gerrit ReplicateProject " + organisation + "/" + repository);
- this.replicationConfig = replicationConfig;
- GitHubLogin ghLogin = ghLoginProvider.get();
- this.authUsername = ghLogin.getMyself().getLogin();
- this.authToken = ghLogin.getAccessToken();
- this.gitHubUrl = gitHubUrl;
+ this.replicationRemotesUpdaterItem = replicationRemotesUpdaterItem;
}
@Override
@@ -58,11 +54,15 @@
progress.beginTask("Setting up Gerrit replication", 2);
String repositoryName = getOrganisation() + "/" + getRepositoryName();
+ Config remoteConfig = remoteConfigBuilder.build(repositoryName);
progress.update(1);
- replicationConfig.addSecureCredentials(authUsername, authToken);
+
+ ReplicationRemotesApi updater = replicationRemotesUpdaterItem.get();
+ if (updater != null) {
+ updater.update(remoteConfig);
+ }
progress.update(1);
- replicationConfig.addReplicationRemote(
- authUsername, gitHubUrl + "/${name}.git", repositoryName);
+
progress.endTask();
}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java
deleted file mode 100644
index 8b7712a..0000000
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationConfig.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2013 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.github.git;
-
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-
-public interface ReplicationConfig {
-
- void addSecureCredentials(String authUsername, String authToken)
- throws IOException, ConfigInvalidException;
-
- void addReplicationRemote(String username, String url, String projectName)
- throws IOException, ConfigInvalidException;
-}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilder.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilder.java
new file mode 100644
index 0000000..bef109c
--- /dev/null
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilder.java
@@ -0,0 +1,72 @@
+// Copyright (C) 2024 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.github.git;
+
+import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.github.GitHubURL;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+import com.googlesource.gerrit.plugins.replication.api.ReplicationRemotesApi;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.jgit.lib.Config;
+
+class ReplicationRemoteConfigBuilder {
+ private final String gitHubUrl;
+ private final String username;
+ private final String authToken;
+ private final DynamicItem<ReplicationRemotesApi> replicationConfigItem;
+
+ @Inject
+ ReplicationRemoteConfigBuilder(
+ DynamicItem<ReplicationRemotesApi> replicationRemotesItem,
+ ScopedProvider<GitHubLogin> ghLoginProvider,
+ @GitHubURL String gitHubUrl)
+ throws IOException {
+ this.gitHubUrl = gitHubUrl;
+ this.replicationConfigItem = replicationRemotesItem;
+ GitHubLogin ghLogin = ghLoginProvider.get();
+ this.username = ghLogin.getMyself().getLogin();
+ this.authToken = ghLogin.getAccessToken();
+ }
+
+ Config build(String repositoryName) {
+ Config remoteConfig = new Config();
+
+ remoteConfig.setString("remote", username, "username", username);
+ remoteConfig.setString("remote", username, "password", authToken);
+
+ remoteConfig.setString("remote", username, "url", gitHubUrl + "/${name}.git");
+
+ String[] existingProjects = getProjects();
+ List<String> projects = new ArrayList<>(List.of(existingProjects));
+ projects.add(repositoryName);
+
+ remoteConfig.setStringList("remote", username, "projects", projects);
+ remoteConfig.setString("remote", username, "push", "refs/*:refs/*");
+
+ return remoteConfig;
+ }
+
+ private String[] getProjects() {
+ ReplicationRemotesApi config = replicationConfigItem.get();
+ if (config != null) {
+ return config.get(username).getStringList("remote", username, "projects");
+ }
+
+ return new String[0];
+ }
+}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
index 810632a..6d24b3e 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/replication/GitHubDestinations.java
@@ -18,22 +18,17 @@
import com.google.common.collect.Lists;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
-import java.io.IOException;
+import com.googlesource.gerrit.plugins.replication.api.ReplicationConfig;
import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
-import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -60,15 +55,15 @@
@Inject
GitHubDestinations(
- final SitePaths site,
+ final ReplicationConfig replicationConfig,
final RemoteSiteUser.Factory ruf,
final GroupBackend gb,
final PluginUser pu)
- throws ConfigInvalidException, IOException {
+ throws ConfigInvalidException {
pluginUser = pu;
replicationUserFactory = ruf;
groupBackend = gb;
- configs = getDestinations(site.etc_dir.resolve("replication.config"));
+ configs = getDestinations(replicationConfig.getConfig());
organisations = getOrganisations(configs);
}
@@ -83,22 +78,7 @@
return result;
}
- private List<Destination> getDestinations(Path cfgPath)
- throws ConfigInvalidException, IOException {
- if (!Files.exists(cfgPath) || Files.size(cfgPath) == 0) {
- return Collections.emptyList();
- }
-
- FileBasedConfig cfg = new FileBasedConfig(cfgPath.toFile(), FS.DETECTED);
- try {
- cfg.load();
- } catch (ConfigInvalidException e) {
- throw new ConfigInvalidException(
- String.format("Config file %s is invalid: %s", cfg.getFile(), e.getMessage()), e);
- } catch (IOException e) {
- throw new IOException(String.format("Cannot read %s: %s", cfg.getFile(), e.getMessage()), e);
- }
-
+ private List<Destination> getDestinations(Config cfg) throws ConfigInvalidException {
ImmutableList.Builder<Destination> dest = ImmutableList.builder();
for (RemoteConfig c : allRemotes(cfg)) {
if (c.getURIs().isEmpty()) {
@@ -108,9 +88,7 @@
for (URIish u : c.getURIs()) {
if (u.getPath() == null || !u.getPath().contains("${name}")) {
throw new ConfigInvalidException(
- String.format(
- "remote.%s.url \"%s\" lacks ${name} placeholder in %s",
- c.getName(), u, cfg.getFile()));
+ String.format("remote.%s.url \"%s\" lacks ${name} placeholder", c.getName(), u));
}
}
@@ -131,7 +109,7 @@
return dest.build();
}
- private static List<RemoteConfig> allRemotes(FileBasedConfig cfg) throws ConfigInvalidException {
+ private static List<RemoteConfig> allRemotes(Config cfg) throws ConfigInvalidException {
Set<String> names = cfg.getSubsections("remote");
List<RemoteConfig> result = Lists.newArrayListWithCapacity(names.size());
for (String name : names) {
@@ -140,8 +118,7 @@
result.add(new RemoteConfig(cfg, name));
}
} catch (URISyntaxException e) {
- throw new ConfigInvalidException(
- String.format("remote %s has invalid URL in %s", name, cfg.getFile()));
+ throw new ConfigInvalidException(String.format("remote %s has invalid URL", name));
}
}
return result;
diff --git a/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/FanoutReplicationConfigTest.java b/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/FanoutReplicationConfigTest.java
deleted file mode 100644
index 3613c41..0000000
--- a/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/FanoutReplicationConfigTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2023 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.github;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.server.config.SitePaths;
-import com.googlesource.gerrit.plugins.github.git.FanoutReplicationConfig;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class FanoutReplicationConfigTest {
-
- private static final String CUSTOM_KEY = "mykey";
- private static final String CUSTOM_VALUE = "myvalue";
- private static final String REMOTE_ENDPOINT = "my-remote-endpoint";
- private static final String TEST_REMOTE_URL = "http://github.com/myurl";
- private static final String TEST_PROJECT_NAME = "myprojectname";
- private Path tempDir;
- private SitePaths sitePaths;
-
- @Before
- public void setup() throws Exception {
- tempDir = Files.createTempDirectory(getClass().getSimpleName());
- sitePaths = new SitePaths(tempDir);
- Files.createDirectories(sitePaths.etc_dir);
- }
-
- @After
- public void teardown() throws Exception {
- FileUtils.deleteDirectory(tempDir.toFile());
- }
-
- @Test
- public void shoudKeepAdHocSettingsInFanoutReplicationConfig() throws Exception {
- FileBasedConfig currConfig = getReplicationConfig();
- currConfig.setString("remote", null, CUSTOM_KEY, CUSTOM_VALUE);
- currConfig.save();
-
- String url = "http://github.com/myurl";
- FanoutReplicationConfig fanoutReplicationConfig = new FanoutReplicationConfig(sitePaths);
- fanoutReplicationConfig.addReplicationRemote(REMOTE_ENDPOINT, url, "myproject");
-
- currConfig.load();
- assertThat(currConfig.getString("remote", null, CUSTOM_KEY)).isEqualTo(CUSTOM_VALUE);
- }
-
- @Test
- public void shoudKeepCustomUrlInFanoutReplicationConfig() throws Exception {
- FileBasedConfig currConfig = getReplicationConfig();
- String customUrl = "http://my-custom-url";
- currConfig.setString("remote", null, "url", customUrl);
- currConfig.save();
-
- new FanoutReplicationConfig(sitePaths)
- .addReplicationRemote(REMOTE_ENDPOINT, TEST_REMOTE_URL, TEST_PROJECT_NAME);
-
- currConfig.load();
- assertThat(currConfig.getString("remote", null, "url")).isEqualTo(customUrl);
- }
-
- @Test
- public void shoudKeepCustomPushRefSpecInFanoutReplicationConfig() throws Exception {
- FileBasedConfig currConfig = getReplicationConfig();
- String customPushRefSpec = "+refs/heads/myheads/*:refs/heads/myheads/*";
- currConfig.setString("remote", null, "push", customPushRefSpec);
- currConfig.save();
-
- new FanoutReplicationConfig(sitePaths)
- .addReplicationRemote(REMOTE_ENDPOINT, TEST_REMOTE_URL, TEST_PROJECT_NAME);
-
- currConfig.load();
- assertThat(currConfig.getString("remote", null, "push")).isEqualTo(customPushRefSpec);
- }
-
- private FileBasedConfig getReplicationConfig() {
- return new FileBasedConfig(
- sitePaths.etc_dir.resolve("replication").resolve(REMOTE_ENDPOINT + ".config").toFile(),
- FS.DETECTED);
- }
-}
diff --git a/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilderTest.java b/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilderTest.java
new file mode 100644
index 0000000..c6023e0
--- /dev/null
+++ b/github-plugin/src/test/java/com/googlesource/gerrit/plugins/github/git/ReplicationRemoteConfigBuilderTest.java
@@ -0,0 +1,86 @@
+// Copyright (C) 2024 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.github.git;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.gerrit.extensions.registration.DynamicItem;
+import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
+import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
+import com.googlesource.gerrit.plugins.replication.api.ReplicationRemotesApi;
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+import org.kohsuke.github.GHMyself;
+
+public class ReplicationRemoteConfigBuilderTest {
+ private final String repoName = "test-repo";
+ private final String username = "test-user";
+ private final String password = "myHighlySecretPassword";
+ private final String gitHubUrl = "htpps://github.com";
+
+ @Test
+ public void shouldBuildConfig() throws Exception {
+ ReplicationRemoteConfigBuilder builder = newReplicationRemoteConfigBuilder();
+ Config actual = builder.build(repoName);
+
+ assertThat(actual.getString("remote", username, "username")).isEqualTo(username);
+ assertThat(actual.getString("remote", username, "password")).isEqualTo(password);
+ assertThat(actual.getString("remote", username, "url")).isEqualTo(gitHubUrl + "/${name}.git");
+ assertThat(actual.getStringList("remote", username, "projects"))
+ .isEqualTo(new String[] {repoName});
+ assertThat(actual.getString("remote", username, "push")).isEqualTo("refs/*:refs/*");
+ }
+
+ @Test
+ public void shouldAppendProjectToConfig() throws Exception {
+ String prevProject = "imported-project";
+ Config currentConfig = new Config();
+ currentConfig.setString("remote", username, "projects", prevProject);
+
+ ReplicationRemoteConfigBuilder builder = newReplicationRemoteConfigBuilder(currentConfig);
+ Config actual = builder.build(repoName);
+
+ assertThat(actual.getString("remote", username, "username")).isEqualTo(username);
+ assertThat(actual.getString("remote", username, "password")).isEqualTo(password);
+ assertThat(actual.getString("remote", username, "url")).isEqualTo(gitHubUrl + "/${name}.git");
+ assertThat(actual.getStringList("remote", username, "projects"))
+ .isEqualTo(new String[] {prevProject, repoName});
+ assertThat(actual.getString("remote", username, "push")).isEqualTo("refs/*:refs/*");
+ }
+
+ private ReplicationRemoteConfigBuilder newReplicationRemoteConfigBuilder() throws Exception {
+ return newReplicationRemoteConfigBuilder(new Config());
+ }
+
+ private ReplicationRemoteConfigBuilder newReplicationRemoteConfigBuilder(Config currentConfig)
+ throws Exception {
+ GitHubLogin gitHubLoginMock = mock(GitHubLogin.class);
+ GHMyself ghMyselfMock = mock(GHMyself.class);
+ ScopedProvider<GitHubLogin> scopedProviderMock = mock(ScopedProvider.class);
+ ReplicationRemotesApi replicationRemotesApi = mock(ReplicationRemotesApi.class);
+ DynamicItem<ReplicationRemotesApi> replicationRemotesItem = mock(DynamicItem.class);
+
+ when(ghMyselfMock.getLogin()).thenReturn(username);
+ when(gitHubLoginMock.getMyself()).thenReturn(ghMyselfMock);
+ when(gitHubLoginMock.getAccessToken()).thenReturn(password);
+ when(scopedProviderMock.get()).thenReturn(gitHubLoginMock);
+ when(replicationRemotesApi.get(username)).thenReturn(currentConfig);
+ when(replicationRemotesItem.get()).thenReturn(replicationRemotesApi);
+
+ return new ReplicationRemoteConfigBuilder(
+ replicationRemotesItem, scopedProviderMock, gitHubUrl);
+ }
+}