Merge branch 'stable-2.11' into stable-2.12
* stable-2.11:
Destination: parse replication delay and retry as time units
Remove obsolete remote.NAME.timeout from config documentation
Change-Id: I57016ead4f30def6153b66dee41922cddad36804
diff --git a/BUCK b/BUCK
index 2e8a623..3da69ef 100644
--- a/BUCK
+++ b/BUCK
@@ -1,3 +1,5 @@
+include_defs('//lib/maven.defs')
+
gerrit_plugin(
name = 'replication',
srcs = glob(['src/main/java/**/*.java']),
@@ -9,15 +11,27 @@
'Gerrit-Module: com.googlesource.gerrit.plugins.replication.ReplicationModule',
'Gerrit-SshModule: com.googlesource.gerrit.plugins.replication.SshModule'
],
+ deps = [
+ ':commons-io',
+ ],
provided_deps = [
- '//lib/commons:io',
+ '//lib:gson',
'//lib/log:log4j'
],
)
+maven_jar(
+ name = 'commons-io',
+ id = 'commons-io:commons-io:1.4',
+ sha1 = 'a8762d07e76cfde2395257a5da47ba7c1dbd3dce',
+ license = 'Apache2.0',
+)
+
java_test(
name = 'replication_tests',
srcs = glob(['src/test/java/**/*.java']),
+ labels = ['replication'],
+ source_under_test = [':replication__plugin'],
deps = [
':replication__plugin',
'//gerrit-common:server',
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
index 62cad2c..2c946a5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadConfigDecorator.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.googlesource.gerrit.plugins.replication;
+import com.google.gerrit.common.FileUtil;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.SitePaths;
@@ -43,12 +44,14 @@
private final GitRepositoryManager gitRepositoryManager;
private final GroupBackend groupBackend;
private final WorkQueue workQueue;
+ private final ReplicationStateListener stateLog;
@Inject
public AutoReloadConfigDecorator(Injector injector, SitePaths site,
RemoteSiteUser.Factory ruf, PluginUser pu,
GitRepositoryManager grm, GroupBackend gb,
- WorkQueue workQueue) throws ConfigInvalidException,
+ WorkQueue workQueue,
+ ReplicationStateListener stateLog) throws ConfigInvalidException,
IOException {
this.injector = injector;
this.site = site;
@@ -57,15 +60,20 @@
this.gitRepositoryManager = grm;
this.groupBackend = gb;
this.currentConfig = loadConfig();
- this.currentConfigTs = currentConfig.getCfgPath().lastModified();
+ this.currentConfigTs = getLastModified(currentConfig);
this.workQueue = workQueue;
+ this.stateLog = stateLog;
+ }
+
+ private static long getLastModified(ReplicationFileBasedConfig cfg) {
+ return FileUtil.lastModified(cfg.getCfgPath());
}
private ReplicationFileBasedConfig loadConfig()
throws ConfigInvalidException, IOException {
return new ReplicationFileBasedConfig(injector, site,
remoteSiteUserFactory, pluginUser, gitRepositoryManager,
- groupBackend);
+ groupBackend, stateLog);
}
private synchronized boolean isAutoReload() {
@@ -79,25 +87,27 @@
}
private void reloadIfNeeded() {
- if (isAutoReload()
- && currentConfig.getCfgPath().lastModified() > currentConfigTs) {
- try {
- ReplicationFileBasedConfig newConfig = loadConfig();
- newConfig.startup(workQueue);
- int discarded = currentConfig.shutdown();
+ try {
+ if (isAutoReload()) {
+ long lastModified = getLastModified(currentConfig);
+ if (lastModified > currentConfigTs) {
+ ReplicationFileBasedConfig newConfig = loadConfig();
+ newConfig.startup(workQueue);
+ int discarded = currentConfig.shutdown();
- this.currentConfig = newConfig;
- this.currentConfigTs = currentConfig.getCfgPath().lastModified();
- log.info("Configuration reloaded: "
+ this.currentConfig = newConfig;
+ this.currentConfigTs = lastModified;
+ log.info("Configuration reloaded: "
+ currentConfig.getDestinations(FilterType.ALL).size() + " destinations, "
+ discarded + " replication events discarded");
- } catch (Exception e) {
- log.error(
- "Cannot reload replication configuration: keeping existing settings",
- e);
- return;
+ }
}
+ } catch (Exception e) {
+ log.error(
+ "Cannot reload replication configuration: keeping existing settings",
+ e);
+ return;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadSecureCredentialsFactoryDecorator.java b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadSecureCredentialsFactoryDecorator.java
index 4017822..3a0cc3f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadSecureCredentialsFactoryDecorator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/AutoReloadSecureCredentialsFactoryDecorator.java
@@ -11,18 +11,20 @@
// 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.replication;
+import static com.google.gerrit.common.FileUtil.lastModified;
+
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.concurrent.atomic.AtomicReference;
public class AutoReloadSecureCredentialsFactoryDecorator implements
@@ -47,32 +49,29 @@
}
private long getSecureConfigLastEditTs() {
- FileBasedConfig cfg = new FileBasedConfig(site.secure_config, FS.DETECTED);
- if (cfg.getFile().exists()) {
- return cfg.getFile().lastModified();
- } else {
+ if (!Files.exists(site.secure_config)) {
return 0L;
}
+ return lastModified(site.secure_config);
}
@Override
public SecureCredentialsProvider create(String remoteName) {
- if (needsReload()) {
- try {
+ try {
+ if (needsReload()) {
secureCredentialsFactory.compareAndSet(secureCredentialsFactory.get(),
new SecureCredentialsFactory(site));
secureCredentialsFactoryLoadTs = getSecureConfigLastEditTs();
log.info("secure.config reloaded as it was updated on the file system");
- } catch (Exception e) {
- log.error("Unexpected error while trying to reload "
- + "secure.config: keeping existing credentials", e);
}
+ } catch (Exception e) {
+ log.error("Unexpected error while trying to reload "
+ + "secure.config: keeping existing credentials", e);
}
return secureCredentialsFactory.get().create(remoteName);
}
-
private boolean needsReload() {
return config.getConfig().getBoolean("gerrit", "autoReload", false) &&
getSecureConfigLastEditTs() != secureCredentialsFactoryLoadTs;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
index eea1038..ee8d08d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -29,7 +30,6 @@
import com.google.gerrit.server.account.GroupBackends;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.config.RequestScopedReviewDbProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.PerThreadRequestScope;
@@ -66,15 +66,16 @@
class Destination {
private static final Logger repLog = ReplicationQueue.repLog;
- private static final ReplicationStateLogger stateLog =
- new ReplicationStateLogger(repLog);
+ private final ReplicationStateListener stateLog;
private final int poolThreads;
private final String poolName;
private final RemoteConfig remote;
private final String[] adminUrls;
+ private final String[] urls;
private final String[] projects;
+ private final String[] authGroupNames;
private final int delay;
private final int retryDelay;
private final Object stateLock = new Object();
@@ -101,15 +102,19 @@
final RemoteSiteUser.Factory replicationUserFactory,
final PluginUser pluginUser,
final GitRepositoryManager gitRepositoryManager,
- final GroupBackend groupBackend) {
+ final GroupBackend groupBackend,
+ final ReplicationStateListener stateLog) {
remote = rc;
gitManager = gitRepositoryManager;
+ this.stateLog = stateLog;
+
delay = Math.max(0,
getTimeUnit(rc, cfg, "replicationdelay", 15, TimeUnit.SECONDS));
retryDelay = Math.max(0,
getTimeUnit(rc, cfg, "replicationretry", 1, TimeUnit.MINUTES));
lockErrorMaxRetries = cfg.getInt("replication", "lockErrorMaxRetries", 0);
adminUrls = cfg.getStringList("remote", rc.getName(), "adminUrl");
+ urls = cfg.getStringList("remote", rc.getName(), "url");
poolThreads = Math.max(0, getInt(rc, cfg, "threads", 1));
poolName = "ReplicateTo-" + rc.getName();
@@ -124,7 +129,7 @@
projects = cfg.getStringList("remote", rc.getName(), "projects");
final CurrentUser remoteUser;
- String[] authGroupNames = cfg.getStringList("remote", rc.getName(), "authGroup");
+ authGroupNames = cfg.getStringList("remote", rc.getName(), "authGroup");
if (authGroupNames.length > 0) {
ImmutableSet.Builder<AccountGroup.UUID> builder = ImmutableSet.builder();
for (String name : authGroupNames) {
@@ -160,7 +165,7 @@
final Provider<RequestScopedReviewDbProvider> dbProvider) {
final RequestContext requestContext = new RequestContext() {
@Override
- public CurrentUser getCurrentUser() {
+ public CurrentUser getUser() {
return remoteUser;
}
@@ -239,27 +244,23 @@
e = pending.get(uri);
}
if (e == null) {
- Repository git;
- try {
- git = gitManager.openRepository(project);
- } catch (IOException err) {
- stateLog.error(String.format(
- "source project %s not available", project), err, state);
- return;
- }
- try {
- Ref head = git.getRef(Constants.HEAD);
- if (head != null
- && head.isSymbolic()
- && RefNames.REFS_CONFIG.equals(head.getLeaf().getName())) {
+ try (Repository git = gitManager.openRepository(project)) {
+ try {
+ Ref head = git.getRef(Constants.HEAD);
+ if (head != null
+ && head.isSymbolic()
+ && RefNames.REFS_CONFIG.equals(head.getLeaf().getName())) {
+ return;
+ }
+ } catch (IOException err) {
+ stateLog.error(String.format(
+ "cannot check type of project %s", project), err, state);
return;
}
} catch (IOException err) {
stateLog.error(String.format(
- "cannot check type of project %s", project), err, state);
+ "source project %s not available", project), err, state);
return;
- } finally {
- git.close();
}
}
}
@@ -504,6 +505,22 @@
return adminUrls;
}
+ String[] getUrls() {
+ return urls;
+ }
+
+ RemoteConfig getRemoteConfig() {
+ return remote;
+ }
+
+ String[] getAuthGroupNames() {
+ return authGroupNames;
+ }
+
+ String[] getProjects() {
+ return projects;
+ }
+
int getLockErrorMaxRetries() {
return lockErrorMaxRetries;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ListCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ListCommand.java
new file mode 100644
index 0000000..91fa65a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ListCommand.java
@@ -0,0 +1,118 @@
+// Copyright (C) 2015 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.replication;
+
+import com.google.common.base.Strings;
+import com.google.gerrit.common.data.GlobalCapability;
+import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.sshd.CommandMetaData;
+import com.google.gerrit.sshd.SshCommand;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.google.inject.Inject;
+
+import com.googlesource.gerrit.plugins.replication.ReplicationConfig.FilterType;
+
+import org.kohsuke.args4j.Option;
+
+import java.util.List;
+
+@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
+@CommandMetaData(name = "list", description = "List specific remote destinations information")
+final class ListCommand extends SshCommand {
+ @Option(name = "--remote", metaVar = "PATTERN", usage = "pattern to match remote name on")
+ private String remote;
+
+ @Option(name = "--detail", usage = "print remote destination detail information")
+ private boolean detail;
+
+ @Option(name = "--json", usage = "output in json format")
+ private boolean json;
+
+ @Inject
+ private ReplicationConfig config;
+
+ @Override
+ protected void run() {
+ List<Destination> dest = config.getDestinations(FilterType.ALL);
+ for (Destination d : dest) {
+ if (matches(d.getRemoteConfig().getName())) {
+ printRemote(d, detail);
+ }
+ }
+ }
+
+ private boolean matches(String name) {
+ return (Strings.isNullOrEmpty(remote)
+ || name.contains(remote)
+ || name.matches(remote));
+ }
+
+ private void addProperty(JsonObject obj, String key, String[] values) {
+ if (values.length > 0) {
+ JsonArray list = new JsonArray();
+ for (String v : values) {
+ list.add(new JsonPrimitive(v));
+ }
+ obj.add(key, list);
+ }
+ }
+
+ private void printRemote(Destination d, boolean detail) {
+ if (json) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty("remote", d.getRemoteConfig().getName());
+ addProperty(obj, "Url", d.getUrls());
+ if (detail) {
+ addProperty(obj, "AdminUrl", d.getAdminUrls());
+ addProperty(obj, "AuthGroup", d.getAuthGroupNames());
+ addProperty(obj, "Project", d.getProjects());
+ }
+ stdout.print(obj.toString() + "\n");
+ } else {
+ StringBuilder out = new StringBuilder();
+ out.append("Remote: ")
+ .append(d.getRemoteConfig().getName())
+ .append("\n");
+ for (String url : d.getUrls()) {
+ out.append("Url: ")
+ .append(url)
+ .append("\n");
+ }
+
+ if (detail) {
+ for (String adminUrl : d.getAdminUrls()) {
+ out.append("AdminUrl: ")
+ .append(adminUrl)
+ .append("\n");
+ }
+
+ for (String authGroup : d.getAuthGroupNames()) {
+ out.append("AuthGroup: ")
+ .append(authGroup)
+ .append("\n");
+ }
+
+ for (String project : d.getProjects()) {
+ out.append("Project: ")
+ .append(project)
+ .append("\n");
+ }
+ }
+ stdout.print(out.toString() + "\n");
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
index c6ad873..5ff4035 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushAll.java
@@ -25,8 +25,7 @@
import java.util.concurrent.TimeUnit;
class PushAll implements Runnable {
- private static final ReplicationStateLogger stateLog =
- new ReplicationStateLogger(ReplicationQueue.repLog);
+ private final ReplicationStateListener stateLog;
interface Factory {
PushAll create(String urlMatch,
@@ -45,12 +44,14 @@
PushAll(WorkQueue wq,
ProjectCache projectCache,
ReplicationQueue rq,
+ ReplicationStateListener stateLog,
@Assisted @Nullable String urlMatch,
@Assisted ReplicationFilter filter,
@Assisted ReplicationState state) {
this.workQueue = wq;
this.projectCache = projectCache;
this.replication = rq;
+ this.stateLog = stateLog;
this.urlMatch = urlMatch;
this.filter = filter;
this.state = state;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
index 255c51b..4a2d01b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
@@ -14,6 +14,8 @@
package com.googlesource.gerrit.plugins.replication;
+import static com.googlesource.gerrit.plugins.replication.ReplicationQueue.repLog;
+
import com.google.common.base.Throwables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Lists;
@@ -59,7 +61,6 @@
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
-import org.slf4j.Logger;
import org.slf4j.MDC;
import java.io.IOException;
@@ -78,9 +79,7 @@
* take that lock to ensure they are working with a current view of the object.
*/
class PushOne implements ProjectRunnable {
- private static final Logger repLog = ReplicationQueue.repLog;
- private static final ReplicationStateLogger stateLog =
- new ReplicationStateLogger(repLog);
+ private final ReplicationStateListener stateLog;
static final String ALL_REFS = "..all..";
static final String ID_MDC_KEY = "pushOneId";
@@ -124,6 +123,7 @@
final ChangeCache cc,
final ReplicationQueue rq,
final IdGenerator ig,
+ final ReplicationStateListener sl,
@Assisted final Project.NameKey d,
@Assisted final URIish u) {
gitManager = grm;
@@ -140,6 +140,7 @@
lockRetryCount = 0;
maxLockRetries = pool.getLockErrorMaxRetries();
id = ig.next();
+ stateLog = sl;
createdAt = TimeUtil.nowMs();
}
@@ -243,7 +244,7 @@
if (!stateMap.isEmpty() && !isRetrying()) {
for (Map.Entry<String,ReplicationState> entry : stateMap.entries()) {
entry.getValue().notifyRefReplicated(projectName.get(), entry.getKey(), uri,
- RefPushResult.FAILED);
+ RefPushResult.FAILED, null);
}
}
}
@@ -427,19 +428,13 @@
local = n;
}
- ReviewDb db;
- try {
- db = schema.open();
+ try (ReviewDb db = schema.open()) {
+ local = new VisibleRefFilter(tagCache, changeCache, git, pc, db, true)
+ .filter(local, true);
} catch (OrmException e) {
stateLog.error("Cannot read database to replicate to " + projectName, e, getStatesAsArray());
return Collections.emptyList();
}
- try {
- local = new VisibleRefFilter(tagCache, changeCache, git, pc, db, true)
- .filter(local, true);
- } finally {
- db.close();
- }
}
return pushAllRefs ? doPushAll(tn, local) : doPushDelta(local);
@@ -549,6 +544,7 @@
throws LockFailureException {
Set<String> doneRefs = new HashSet<>();
boolean anyRefFailed = false;
+ RemoteRefUpdate.Status lastRefStatusError = RemoteRefUpdate.Status.OK;
for (RemoteRefUpdate u : refUpdates) {
RefPushResult pushStatus = RefPushResult.SUCCEEDED;
@@ -574,6 +570,7 @@
u.getRemoteName(), uri, u.getStatus()), logStatesArray);
pushStatus = RefPushResult.FAILED;
anyRefFailed = true;
+ lastRefStatusError = u.getStatus();
break;
case REJECTED_OTHER_REASON:
@@ -591,30 +588,31 @@
}
pushStatus = RefPushResult.FAILED;
anyRefFailed = true;
+ lastRefStatusError = u.getStatus();
break;
}
for (ReplicationState rs : getStatesByRef(u.getSrcRef())) {
rs.notifyRefReplicated(projectName.get(), u.getSrcRef(),
- uri, pushStatus);
+ uri, pushStatus, u.getStatus());
}
}
doneRefs.add(ALL_REFS);
for (ReplicationState rs : getStatesByRef(ALL_REFS)) {
- rs.notifyRefReplicated(projectName.get(), ALL_REFS,
- uri, anyRefFailed ? RefPushResult.FAILED : RefPushResult.SUCCEEDED);
+ rs.notifyRefReplicated(projectName.get(), ALL_REFS, uri, anyRefFailed
+ ? RefPushResult.FAILED : RefPushResult.SUCCEEDED, lastRefStatusError);
}
- for (Map.Entry<String,ReplicationState> entry : stateMap.entries()) {
+ for (Map.Entry<String, ReplicationState> entry : stateMap.entries()) {
if (!doneRefs.contains(entry.getKey())) {
- entry.getValue().notifyRefReplicated(projectName.get(), entry.getKey(), uri,
- RefPushResult.NOT_ATTEMPTED);
+ entry.getValue().notifyRefReplicated(projectName.get(), entry.getKey(),
+ uri, RefPushResult.NOT_ATTEMPTED, null);
}
}
stateMap.clear();
}
- public class LockFailureException extends TransportException {
+ public static class LockFailureException extends TransportException {
private static final long serialVersionUID = 1L;
public LockFailureException(URIish uri, String message) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java
index 0f8cc9e..c63d346 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java
@@ -26,6 +26,7 @@
import com.googlesource.gerrit.plugins.replication.ReplicationState.RefPushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.URIish;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +36,8 @@
public abstract class PushResultProcessing {
- abstract void onRefReplicatedToOneNode(String project, String ref, URIish uri, RefPushResult status);
+ abstract void onRefReplicatedToOneNode(String project, String ref,
+ URIish uri, RefPushResult status, RemoteRefUpdate.Status refStatus);
abstract void onRefReplicatedToAllNodes(String project, String ref, int nodesCount);
@@ -83,7 +85,7 @@
@Override
void onRefReplicatedToOneNode(String project, String ref, URIish uri,
- RefPushResult status) {
+ RefPushResult status, RemoteRefUpdate.Status refStatus) {
StringBuilder sb = new StringBuilder();
sb.append("Replicate ");
sb.append(project);
@@ -107,6 +109,9 @@
sb.append("UNKNOWN RESULT!");
break;
}
+ sb.append(" (");
+ sb.append(refStatus.toString());
+ sb.append(")");
writeStdOut(sb.toString());
}
@@ -167,9 +172,9 @@
@Override
void onRefReplicatedToOneNode(String project, String ref, URIish uri,
- RefPushResult status) {
+ RefPushResult status, RemoteRefUpdate.Status refStatus) {
RefReplicatedEvent event =
- new RefReplicatedEvent(project, ref, resolveNodeName(uri), status);
+ new RefReplicatedEvent(project, ref, resolveNodeName(uri), status, refStatus);
postEvent(project, ref, event);
}
@@ -185,16 +190,11 @@
}
private void postEvent(String project, String ref, RefEvent event) {
- if (PatchSet.isRef(ref)) {
- try {
- ReviewDb db = schema.open();
- try {
- Change change = retrieveChange(ref, db);
- if (change != null) {
- dispatcher.postEvent(change, event, db);
- }
- } finally {
- db.close();
+ if (PatchSet.isChangeRef(ref)) {
+ try (ReviewDb db = schema.open()) {
+ Change change = retrieveChange(ref, db);
+ if (change != null) {
+ dispatcher.postEvent(change, event, db);
}
} catch (Exception e) {
log.error("Cannot post event", e);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/RefReplicatedEvent.java b/src/main/java/com/googlesource/gerrit/plugins/replication/RefReplicatedEvent.java
index 664e819..f200194 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/RefReplicatedEvent.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/RefReplicatedEvent.java
@@ -19,19 +19,24 @@
import com.googlesource.gerrit.plugins.replication.ReplicationState.RefPushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
+
public class RefReplicatedEvent extends RefEvent {
public final String project;
public final String ref;
public final String targetNode;
public final String status;
+ public final Status refStatus;
public RefReplicatedEvent(String project, String ref, String targetNode,
- RefPushResult status) {
+ RefPushResult status, RemoteRefUpdate.Status refStatus) {
super("ref-replicated");
this.project = project;
this.ref = ref;
this.targetNode = targetNode;
this.status = toStatusString(status);
+ this.refStatus = refStatus;
}
private String toStatusString(RefPushResult status) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
index f56185d..1486f1b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationFileBasedConfig.java
@@ -35,9 +35,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -46,7 +46,7 @@
public class ReplicationFileBasedConfig implements ReplicationConfig {
static final Logger log = LoggerFactory.getLogger(ReplicationFileBasedConfig.class);
private List<Destination> destinations;
- private File cfgPath;
+ private Path cfgPath;
private boolean replicateAllOnPluginStart;
private boolean defaultForceUpdate;
private Injector injector;
@@ -55,20 +55,23 @@
private final GitRepositoryManager gitRepositoryManager;
private final GroupBackend groupBackend;
private final FileBasedConfig config;
+ private final ReplicationStateListener stateLog;
@Inject
public ReplicationFileBasedConfig(final Injector injector, final SitePaths site,
final RemoteSiteUser.Factory ruf, final PluginUser pu,
final GitRepositoryManager grm,
- final GroupBackend gb) throws ConfigInvalidException, IOException {
- this.cfgPath = new File(site.etc_dir, "replication.config");
+ final GroupBackend gb,
+ final ReplicationStateListener stateLog) throws ConfigInvalidException, IOException {
+ this.cfgPath = site.etc_dir.resolve("replication.config");
this.injector = injector;
this.replicationUserFactory = ruf;
this.pluginUser = pu;
this.gitRepositoryManager = grm;
this.groupBackend = gb;
- this.config = new FileBasedConfig(cfgPath, FS.DETECTED);
+ this.config = new FileBasedConfig(cfgPath.toFile(), FS.DETECTED);
this.destinations = allDestinations();
+ this.stateLog = stateLog;
}
/*
@@ -115,7 +118,7 @@
private List<Destination> allDestinations()
throws ConfigInvalidException, IOException {
if (!config.getFile().exists()) {
- log.warn("Config file " + config.getFile() + "does not exist; not replicating");
+ log.warn("Config file " + config.getFile() + " does not exist; not replicating");
return Collections.emptyList();
}
if (config.getFile().length() == 0) {
@@ -159,7 +162,7 @@
Destination destination =
new Destination(injector, c, config, replicationUserFactory,
- pluginUser, gitRepositoryManager, groupBackend);
+ pluginUser, gitRepositoryManager, groupBackend, stateLog);
if (!destination.isSingleProjectMatch()) {
for (URIish u : c.getURIs()) {
@@ -215,7 +218,7 @@
return destinations.isEmpty();
}
- File getCfgPath() {
+ Path getCfgPath() {
return cfgPath;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
index 50f1b8b..fcc3437 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationLogFile.java
@@ -14,55 +14,19 @@
package com.googlesource.gerrit.plugins.replication;
-import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.systemstatus.ServerInformation;
+import com.google.gerrit.server.util.PluginLogFile;
import com.google.gerrit.server.util.SystemLog;
import com.google.inject.Inject;
-import org.apache.log4j.AsyncAppender;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
-public class ReplicationLogFile implements LifecycleListener {
-
- private final SystemLog systemLog;
- private final ServerInformation serverInfo;
- private static boolean started;
+public class ReplicationLogFile extends PluginLogFile {
@Inject
- public ReplicationLogFile(final SystemLog systemLog,
+ public ReplicationLogFile(SystemLog systemLog,
ServerInformation serverInfo) {
- this.systemLog = systemLog;
- this.serverInfo = serverInfo;
- }
-
- @Override
- public void start() {
- if (!started) {
- Logger replicationLogger =
- LogManager.getLogger(ReplicationQueue.REPLICATION_LOG_NAME);
- String loggerName = replicationLogger.getName();
- AsyncAppender asyncAppender = systemLog.createAsyncAppender(
- loggerName, new PatternLayout("[%d] [%X{"
- + PushOne.ID_MDC_KEY + "}] %m%n"));
- replicationLogger.removeAppender(loggerName);
- replicationLogger.addAppender(asyncAppender);
- replicationLogger.setAdditivity(false);
- started = true;
- }
- }
-
- @Override
- public void stop() {
- // stop is called when plugin is unloaded or when the server shutdown.
- // Only clean up when the server is shutting down to prevent issue when a
- // plugin is reloaded. The issue is that gerrit load the new plugin and then
- // unload the old one so because loggers are static, the unload of the old
- // plugin would remove the appenders just created by the new plugin.
- if (serverInfo.getState() == ServerInformation.State.SHUTDOWN) {
- LogManager.getLogger(ReplicationQueue.repLog.getName())
- .removeAllAppenders();
- }
+ super(systemLog, serverInfo, ReplicationQueue.REPLICATION_LOG_NAME,
+ new PatternLayout("[%d] [%X{" + PushOne.ID_MDC_KEY + "}] %m%n"));
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
index b9575b9..a5d0b82 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
@@ -31,6 +31,8 @@
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.internal.UniqueAnnotations;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+
class ReplicationModule extends AbstractModule {
@Override
@@ -62,8 +64,10 @@
install(new FactoryModuleBuilder().build(RemoteSiteUser.Factory.class));
bind(ReplicationConfig.class).to(AutoReloadConfigDecorator.class);
+ bind(ReplicationStateListener.class).to(ReplicationStateLogger.class);
- EventTypes.registerClass(new RefReplicatedEvent(null, null, null, SUCCEEDED));
+ EventTypes.registerClass(new RefReplicatedEvent(null, null, null,
+ SUCCEEDED, RemoteRefUpdate.Status.OK));
EventTypes.registerClass(new RefReplicationDoneEvent(null, null, 0));
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
index 95693d9..67d172f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -63,8 +63,8 @@
static final String REPLICATION_LOG_NAME = "replication_log";
static final Logger repLog = LoggerFactory.getLogger(REPLICATION_LOG_NAME);
private static final int SSH_REMOTE_TIMEOUT = 120 * 1000;
- private static final ReplicationStateLogger stateLog =
- new ReplicationStateLogger(repLog);
+
+ private final ReplicationStateListener stateLog;
static String replaceName(String in, String name, boolean keyIsOptional) {
String key = "${name}";
@@ -85,12 +85,16 @@
private volatile boolean running;
@Inject
- ReplicationQueue(final WorkQueue wq, final ReplicationConfig rc,
- final SchemaFactory<ReviewDb> db, final EventDispatcher dis) {
+ ReplicationQueue(final WorkQueue wq,
+ final ReplicationConfig rc,
+ final SchemaFactory<ReviewDb> db,
+ final EventDispatcher dis,
+ final ReplicationStateListener sl) {
workQueue = wq;
database = db;
dispatcher = dis;
config = rc;
+ stateLog = sl;
}
@Override
@@ -256,18 +260,13 @@
}
private static void createLocally(URIish uri, String head) {
- try {
- Repository repo = new FileRepository(uri.getPath());
- try {
- repo.create(true /* bare */);
+ try (Repository repo = new FileRepository(uri.getPath())) {
+ repo.create(true /* bare */);
- if (head != null) {
- RefUpdate u = repo.updateRef(Constants.HEAD);
- u.disableRefLog();
- u.link(head);
- }
- } finally {
- repo.close();
+ if (head != null) {
+ RefUpdate u = repo.updateRef(Constants.HEAD);
+ u.disableRefLog();
+ u.link(head);
}
} catch (IOException e) {
repLog.error(String.format(
@@ -385,15 +384,10 @@
}
private static void updateHeadLocally(URIish uri, String newHead) {
- try {
- Repository repo = new FileRepository(uri.getPath());
- try {
- if (newHead != null) {
- RefUpdate u = repo.updateRef(Constants.HEAD);
- u.link(newHead);
- }
- } finally {
- repo.close();
+ try (Repository repo = new FileRepository(uri.getPath())) {
+ if (newHead != null) {
+ RefUpdate u = repo.updateRef(Constants.HEAD);
+ u.link(newHead);
}
} catch (IOException e) {
repLog.error(
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationState.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationState.java
index c851db6..b29456d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationState.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationState.java
@@ -17,6 +17,7 @@
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.URIish;
import java.util.concurrent.CountDownLatch;
@@ -69,8 +70,9 @@
}
public void notifyRefReplicated(String project, String ref, URIish uri,
- RefPushResult status) {
- pushResultProcessing.onRefReplicatedToOneNode(project, ref, uri, status);
+ RefPushResult status, RemoteRefUpdate.Status refUpdateStatus) {
+ pushResultProcessing.onRefReplicatedToOneNode(project, ref, uri, status,
+ refUpdateStatus);
RefReplicationStatus completedRefStatus = null;
boolean allPushTaksCompleted = false;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateListener.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateListener.java
new file mode 100644
index 0000000..e5ac9d5
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateListener.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2015 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.replication;
+
+/**
+ * Interface for notifying replication status updates.
+ */
+public interface ReplicationStateListener {
+
+ /**
+ * Notify a non-fatal replication error.
+ *
+ * Replication states received a non-fatal error with an associated
+ * warning message.
+ *
+ * @param msg message description of the error
+ * @param states replication states impacted
+ */
+ public abstract void warn(String msg, ReplicationState... states);
+
+ /**
+ * Notify a fatal replication error.
+ *
+ * Replication states have received a fatal error and replication has
+ * failed.
+ *
+ * @param msg message description of the error
+ * @param states replication states impacted
+ */
+ public abstract void error(String msg, ReplicationState... states);
+
+ /**
+ * Notify a fatal replication error with the associated exception.
+ *
+ * Replication states have received a fatal exception and replication has failed.
+ *
+ * @param msg message description of the error
+ * @param t exception that caused the replication to fail
+ * @param states replication states impacted
+ */
+ public abstract void error(String msg, Throwable t,
+ ReplicationState... states);
+
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateLogger.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateLogger.java
index cb1d4ce..0a59ad3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationStateLogger.java
@@ -14,7 +14,9 @@
package com.googlesource.gerrit.plugins.replication;
-import org.slf4j.Logger;
+import static com.googlesource.gerrit.plugins.replication.ReplicationQueue.repLog;
+
+import com.google.inject.Singleton;
/**
* Wrapper around a Logger that also logs out the replication state.
@@ -24,32 +26,25 @@
* and logs additional information about the replication state to the
* stderr console.
*/
-public class ReplicationStateLogger {
+@Singleton
+class ReplicationStateLogger implements ReplicationStateListener {
- private final Logger logger;
-
- public ReplicationStateLogger(Logger logger) {
- this.logger = logger;
- }
-
+ @Override
public void warn(String msg, ReplicationState... states) {
stateWriteErr("Warning: " + msg, states);
- logger.warn(msg);
+ repLog.warn(msg);
}
- public void warn(String msg, Throwable t, ReplicationState... states) {
- stateWriteErr("Warning: " + msg, states);
- logger.warn(msg, t);
- }
-
+ @Override
public void error(String msg, ReplicationState... states) {
stateWriteErr("Error: " + msg, states);
- logger.error(msg);
+ repLog.error(msg);
}
+ @Override
public void error(String msg, Throwable t, ReplicationState... states) {
stateWriteErr("Error: " + msg, states);
- logger.error(msg, t);
+ repLog.error(msg, t);
}
private void stateWriteErr(String msg, ReplicationState[] states) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/SecureCredentialsFactory.java b/src/main/java/com/googlesource/gerrit/plugins/replication/SecureCredentialsFactory.java
index 32d3905..a10f62f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/SecureCredentialsFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/SecureCredentialsFactory.java
@@ -36,7 +36,8 @@
private static Config load(SitePaths site)
throws ConfigInvalidException, IOException {
- FileBasedConfig cfg = new FileBasedConfig(site.secure_config, FS.DETECTED);
+ FileBasedConfig cfg =
+ new FileBasedConfig(site.secure_config.toFile(), FS.DETECTED);
if (cfg.getFile().exists() && cfg.getFile().length() > 0) {
try {
cfg.load();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/SshModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/SshModule.java
index dd33049..0cab7b1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/SshModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/SshModule.java
@@ -20,5 +20,6 @@
@Override
protected void configureCommands() {
command(StartCommand.class);
+ command(ListCommand.class);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/StartCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/StartCommand.java
index 17a2df9..be5242e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/StartCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/StartCommand.java
@@ -23,8 +23,6 @@
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -35,8 +33,9 @@
@RequiresCapability(StartReplicationCapability.START_REPLICATION)
@CommandMetaData(name = "start", description = "Start replication for specific project or all projects")
final class StartCommand extends SshCommand {
- private static final Logger log = LoggerFactory.getLogger(StartCommand.class);
- private static final ReplicationStateLogger stateLog = new ReplicationStateLogger(log);
+ @Inject
+ private ReplicationStateLogger stateLog;
+
@Option(name = "--all", usage = "push all known projects")
private boolean all;
diff --git a/src/main/resources/Documentation/cmd-list.md b/src/main/resources/Documentation/cmd-list.md
new file mode 100644
index 0000000..84bb56b
--- /dev/null
+++ b/src/main/resources/Documentation/cmd-list.md
@@ -0,0 +1,76 @@
+@PLUGIN@ list
+==============
+
+NAME
+----
+@PLUGIN@ list - List specific remote destinations information
+
+SYNOPSIS
+--------
+```
+ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list
+ [--remote <PATTERN>]
+ [--detail]
+ [--json]
+```
+
+DESCRIPTION
+-----------
+List all remote destinations information, or only those whose
+name match the pattern given on the command line.
+
+ACCESS
+------
+Caller must be a member of the privileged 'Administrators' group.
+
+SCRIPTING
+---------
+This command is intended to be used in scripts. It is very useful
+for replication status check for administrators as well.
+
+OPTIONS
+-------
+
+`--remote <PATTERN>`
+: Only print destinations whose remote name contains
+ the substring `PATTERN`.
+
+`--detail`
+: Print remote detail information: Name, Url, AdminUrl,
+ AuthGroup and Project.
+
+`--json`
+: Output in json format.
+
+EXAMPLES
+--------
+List all destinations:
+
+```
+ $ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list
+```
+
+List all destinations detail information:
+
+```
+ $ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list --detail
+```
+
+List all destinations detail information in json format:
+
+```
+ $ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list --detail --json
+```
+
+List destinations whose name contains mirror:
+
+```
+ $ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list --remote mirror
+ $ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ list --remote ^.*mirror.*
+```
+
+SEE ALSO
+--------
+
+* [Replication Configuration](config.html)
+* [Access Control](../../../Documentation/access-control.html)
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
index a400dca..c6b2eb6 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/GitUpdateProcessingTest.java
@@ -39,6 +39,7 @@
import junit.framework.TestCase;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.URIish;
import java.net.URISyntaxException;
@@ -73,14 +74,15 @@
reset(dispatcherMock);
RefReplicatedEvent expectedEvent =
new RefReplicatedEvent("someProject", "refs/heads/master", "someHost",
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
dispatcherMock.postEvent(anyObject(Branch.NameKey.class),
RefReplicatedEventEquals.eqEvent(expectedEvent));
expectLastCall().once();
replay(dispatcherMock);
- gitUpdateProcessing.onRefReplicatedToOneNode("someProject", "refs/heads/master",
- new URIish("git://someHost/someProject.git"), RefPushResult.SUCCEEDED);
+ gitUpdateProcessing.onRefReplicatedToOneNode("someProject",
+ "refs/heads/master", new URIish("git://someHost/someProject.git"),
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
verify(dispatcherMock);
}
@@ -93,7 +95,7 @@
reset(dispatcherMock);
RefReplicatedEvent expectedEvent =
new RefReplicatedEvent("someProject", "refs/changes/01/1/1", "someHost",
- RefPushResult.FAILED);
+ RefPushResult.FAILED, RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD);
dispatcherMock.postEvent(eq(expectedChange),
RefReplicatedEventEquals.eqEvent(expectedEvent),
anyObject(ReviewDb.class));
@@ -102,7 +104,7 @@
gitUpdateProcessing.onRefReplicatedToOneNode("someProject",
"refs/changes/01/1/1", new URIish("git://someHost/someProject.git"),
- RefPushResult.FAILED);
+ RefPushResult.FAILED, RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD);
verify(dispatcherMock);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationStateTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationStateTest.java
index a0bf576..1408ed6 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationStateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/ReplicationStateTest.java
@@ -23,6 +23,7 @@
import com.googlesource.gerrit.plugins.replication.ReplicationState.RefPushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.URIish;
import org.junit.Before;
import org.junit.Test;
@@ -73,7 +74,7 @@
//expected events
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "someRef",
- uri, RefPushResult.SUCCEEDED);
+ uri, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToAllNodes("someProject",
"someRef", 1);
pushResultProcessingMock.onAllRefsReplicatedToAllNodes(1);
@@ -83,7 +84,7 @@
replicationState.increasePushTaskCount("someProject", "someRef");
replicationState.markAllPushTasksScheduled();
replicationState.notifyRefReplicated("someProject", "someRef", uri,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
verify(pushResultProcessingMock);
}
@@ -96,9 +97,9 @@
//expected events
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "someRef",
- uri1, RefPushResult.SUCCEEDED);
+ uri1, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "someRef",
- uri2, RefPushResult.FAILED);
+ uri2, RefPushResult.FAILED, RemoteRefUpdate.Status.NON_EXISTING);
pushResultProcessingMock.onRefReplicatedToAllNodes("someProject",
"someRef", 2);
pushResultProcessingMock.onAllRefsReplicatedToAllNodes(2);
@@ -109,9 +110,9 @@
replicationState.increasePushTaskCount("someProject", "someRef");
replicationState.markAllPushTasksScheduled();
replicationState.notifyRefReplicated("someProject", "someRef", uri1,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "someRef", uri2,
- RefPushResult.FAILED);
+ RefPushResult.FAILED, RemoteRefUpdate.Status.NON_EXISTING);
verify(pushResultProcessingMock);
}
@@ -125,15 +126,15 @@
//expected events
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref1",
- uri1, RefPushResult.SUCCEEDED);
+ uri1, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref1",
- uri2, RefPushResult.SUCCEEDED);
+ uri2, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref1",
- uri3, RefPushResult.SUCCEEDED);
+ uri3, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref2",
- uri1, RefPushResult.SUCCEEDED);
+ uri1, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref2",
- uri2, RefPushResult.SUCCEEDED);
+ uri2, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock
.onRefReplicatedToAllNodes("someProject", "ref1", 3);
pushResultProcessingMock
@@ -149,15 +150,15 @@
replicationState.increasePushTaskCount("someProject", "ref2");
replicationState.markAllPushTasksScheduled();
replicationState.notifyRefReplicated("someProject", "ref1", uri1,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "ref1", uri2,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "ref1", uri3,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "ref2", uri1,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "ref2", uri2,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
verify(pushResultProcessingMock);
}
@@ -169,9 +170,9 @@
//expected events
pushResultProcessingMock.onRefReplicatedToOneNode("project1", "ref1", uri,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("project2", "ref2", uri,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToAllNodes("project1", "ref1", 1);
pushResultProcessingMock.onRefReplicatedToAllNodes("project2", "ref2", 1);
pushResultProcessingMock.onAllRefsReplicatedToAllNodes(2);
@@ -182,9 +183,9 @@
replicationState.increasePushTaskCount("project2", "ref2");
replicationState.markAllPushTasksScheduled();
replicationState.notifyRefReplicated("project1", "ref1", uri,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("project2", "ref2", uri,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
verify(pushResultProcessingMock);
}
@@ -196,9 +197,9 @@
//expected events
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref1",
- uri1, RefPushResult.SUCCEEDED);
+ uri1, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock.onRefReplicatedToOneNode("someProject", "ref2",
- uri1, RefPushResult.SUCCEEDED);
+ uri1, RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
pushResultProcessingMock
.onRefReplicatedToAllNodes("someProject", "ref1", 1);
pushResultProcessingMock
@@ -210,9 +211,9 @@
replicationState.increasePushTaskCount("someProject", "ref1");
replicationState.increasePushTaskCount("someProject", "ref2");
replicationState.notifyRefReplicated("someProject", "ref1", uri1,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.notifyRefReplicated("someProject", "ref2", uri1,
- RefPushResult.SUCCEEDED);
+ RefPushResult.SUCCEEDED, RemoteRefUpdate.Status.OK);
replicationState.markAllPushTasksScheduled();
verify(pushResultProcessingMock);
}