Merge "Cross-host support."
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/ApiManager.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/ApiManager.java
new file mode 100644
index 0000000..8a44a07
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/ApiManager.java
@@ -0,0 +1,37 @@
+// Copyright (C) 2018 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.automerger;
+
+import com.google.gerrit.extensions.api.GerritApi;
+import com.google.inject.Inject;
+
+/** Interface for sending REST API requests to another Gerrit host. */
+public interface ApiManager {
+ public GerritApi forHostname(String hostname);
+
+ class DefaultApiManager implements ApiManager {
+ protected GerritApi gApi;
+
+ @Inject
+ public DefaultApiManager(GerritApi gApi) {
+ this.gApi = gApi;
+ }
+
+ @Override
+ public GerritApi forHostname(String hostname) {
+ return gApi;
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergeChangeAction.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergeChangeAction.java
index 92d8176..15ae823 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergeChangeAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergeChangeAction.java
@@ -27,6 +27,7 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Map;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.slf4j.Logger;
@@ -83,6 +84,10 @@
mdsMergeInput.obsoleteRevision = revision;
mdsMergeInput.currentRevision = revision;
+ String changeBranch = change.getDest().get();
+ mdsMergeInput.fromCrossHostMap = config.getFromCrossHostMap(changeBranch, branchMap.keySet());
+ mdsMergeInput.toCrossHostMap = config.getToCrossHostMap(changeBranch, branchMap.keySet());
+
log.debug("Multiple downstream merge input: {}", mdsMergeInput.dsBranchMap);
try {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergerModule.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergerModule.java
index b588a2f..227b22c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergerModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/AutomergerModule.java
@@ -50,5 +50,6 @@
}
});
DynamicSet.bind(binder(), WebUiPlugin.class).toInstance(new JavaScriptPlugin("automerger.js"));
+ bind(ApiManager.class).to(ApiManager.DefaultApiManager.class);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/ConfigLoader.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/ConfigLoader.java
index 2ecb88b..5ddf308 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/ConfigLoader.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/ConfigLoader.java
@@ -33,8 +33,10 @@
import com.google.re2j.Pattern;
import java.io.IOException;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
@@ -113,6 +115,42 @@
return false;
}
+ // Returns cross host URL if specified, null if not
+ public String getFromCrossHost(String fromBranch, String toBranch) throws ConfigInvalidException {
+ return getConfig()
+ .getString("automerger", fromBranch + BRANCH_DELIMITER + toBranch, "fromCrossHost");
+ }
+
+ public Map<String, String> getFromCrossHostMap(String fromBranch, Set<String> branches)
+ throws ConfigInvalidException {
+ Map<String, String> fromCrossHostMap = new HashMap<String, String>();
+ for (String branch : branches) {
+ String fromCrossHost = getFromCrossHost(fromBranch, branch);
+ if (fromCrossHost != null) {
+ fromCrossHostMap.put(fromBranch, fromCrossHost);
+ }
+ }
+ return fromCrossHostMap;
+ }
+
+ // Returns cross host URL if specified, null if not
+ public String getToCrossHost(String fromBranch, String toBranch) throws ConfigInvalidException {
+ return getConfig()
+ .getString("automerger", fromBranch + BRANCH_DELIMITER + toBranch, "toCrossHost");
+ }
+
+ public Map<String, String> getToCrossHostMap(String toBranch, Set<String> branches)
+ throws ConfigInvalidException {
+ Map<String, String> toCrossHostMap = new HashMap<String, String>();
+ for (String branch : branches) {
+ String toCrossHost = getToCrossHost(branch, toBranch);
+ if (toCrossHost != null) {
+ toCrossHostMap.put(branch, toCrossHost);
+ }
+ }
+ return toCrossHostMap;
+ }
+
private Pattern getConfigPattern(String key) throws ConfigInvalidException {
String[] patternList = getConfig().getStringList("global", null, key);
Set<String> mergeStrings = new HashSet<>(Arrays.asList(patternList));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
index 7de0782..7884411 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreator.java
@@ -78,6 +78,7 @@
private static final String CURRENT = "current";
protected GerritApi gApi;
+ protected ApiManager apiManager;
protected ConfigLoader config;
protected CurrentUser user;
@@ -85,8 +86,12 @@
@Inject
public DownstreamCreator(
- GerritApi gApi, ConfigLoader config, OneOffRequestContext oneOffRequestContext) {
+ GerritApi gApi,
+ ApiManager apiManager,
+ ConfigLoader config,
+ OneOffRequestContext oneOffRequestContext) {
this.gApi = gApi;
+ this.apiManager = apiManager;
this.config = config;
this.oneOffRequestContext = oneOffRequestContext;
}
@@ -159,11 +164,12 @@
} else {
for (String downstreamBranch : downstreamBranches) {
try {
+ String toCrossHost = config.getToCrossHost(change.branch, downstreamBranch);
List<Integer> existingDownstream =
- getExistingMergesOnBranch(revision, oldTopic, downstreamBranch);
+ getExistingMergesOnBranch(revision, oldTopic, downstreamBranch, toCrossHost);
for (Integer changeNumber : existingDownstream) {
log.debug("Setting topic {} on {}", change.topic, changeNumber);
- gApi.changes().id(changeNumber).topic(change.topic);
+ apiManager.forHostname(toCrossHost).changes().id(changeNumber).topic(change.topic);
}
} catch (RestApiException | InvalidQueryParameterException e) {
log.error("Failed to edit downstream topics of {}", change.id, e);
@@ -208,11 +214,16 @@
for (String downstreamBranch : downstreamBranches) {
try {
+ String toCrossHost = config.getToCrossHost(change.branch, downstreamBranch);
List<Integer> existingDownstream =
- getExistingMergesOnBranch(revision, change.topic, downstreamBranch);
+ getExistingMergesOnBranch(revision, change.topic, downstreamBranch, toCrossHost);
for (Integer changeNumber : existingDownstream) {
ChangeInfo downstreamChange =
- gApi.changes().id(changeNumber).get(EnumSet.of(ListChangesOption.CURRENT_REVISION));
+ apiManager
+ .forHostname(toCrossHost)
+ .changes()
+ .id(changeNumber)
+ .get(EnumSet.of(ListChangesOption.CURRENT_REVISION));
for (Map.Entry<String, LabelInfo> labelEntry : labels.entrySet()) {
if (labelEntry.getValue().all.size() > 0) {
OptionalInt maxVote =
@@ -225,7 +236,11 @@
.max();
if (maxVote.isPresent()) {
- updateVote(downstreamChange, labelEntry.getKey(), (short) maxVote.getAsInt());
+ updateVote(
+ downstreamChange,
+ labelEntry.getKey(),
+ (short) maxVote.getAsInt(),
+ toCrossHost);
}
}
}
@@ -315,13 +330,27 @@
// Make the vote on the original change
ChangeInfo originalChange =
- getOriginalChange(mdsMergeInput.changeNumber, mdsMergeInput.currentRevision);
+ getOriginalChange(
+ mdsMergeInput.changeNumber,
+ mdsMergeInput.currentRevision,
+ mdsMergeInput.sourceBranch,
+ null);
// if this fails, i.e. -2 is restricted, catch it and still post message without a vote.
try {
- gApi.changes().id(originalChange._number).revision(CURRENT).review(reviewInput);
+ apiManager
+ .forHostname(mdsMergeInput.fromCrossHostMap.get(originalChange.branch))
+ .changes()
+ .id(originalChange._number)
+ .revision(CURRENT)
+ .review(reviewInput);
} catch (AuthException e) {
reviewInput.labels = null;
- gApi.changes().id(originalChange._number).revision(CURRENT).review(reviewInput);
+ apiManager
+ .forHostname(mdsMergeInput.fromCrossHostMap.get(originalChange.branch))
+ .changes()
+ .id(originalChange._number)
+ .revision(CURRENT)
+ .review(reviewInput);
}
}
}
@@ -348,10 +377,14 @@
// If there are existing downstream merges, update them
// Otherwise, create them.
boolean createDownstreams = true;
+ String toCrossHost = config.getToCrossHost(mdsMergeInput.sourceBranch, downstreamBranch);
if (mdsMergeInput.obsoleteRevision != null) {
existingDownstream =
getExistingMergesOnBranch(
- mdsMergeInput.obsoleteRevision, mdsMergeInput.topic, downstreamBranch);
+ mdsMergeInput.obsoleteRevision,
+ mdsMergeInput.topic,
+ downstreamBranch,
+ toCrossHost);
if (!existingDownstream.isEmpty()) {
log.debug(
"Attempting to update downstream merge of {} on branch {}",
@@ -361,19 +394,26 @@
// it's possible to construct it so that it's not
for (Integer dsChangeNumber : existingDownstream) {
try {
+ log.info("mds merge input: {}", mdsMergeInput);
+ log.info("mds merge input crosshmap: {}", mdsMergeInput.toCrossHostMap);
+ log.info(
+ "mds merge input crosshmap: {}",
+ mdsMergeInput.toCrossHostMap.get(downstreamBranch));
updateDownstreamMerge(
mdsMergeInput.currentRevision,
mdsMergeInput.subject,
dsChangeNumber,
mdsMergeInput.dsBranchMap.get(downstreamBranch),
mdsMergeInput.changeNumber,
- downstreamBranch);
+ downstreamBranch,
+ mdsMergeInput.toCrossHostMap.get(downstreamBranch),
+ mdsMergeInput.fromCrossHostMap.get(mdsMergeInput.sourceBranch));
createDownstreams = false;
} catch (MergeConflictException e) {
failedMergeBranchMap.put(downstreamBranch, e.getMessage());
log.debug(
"Abandoning existing, obsolete {} due to merge conflict.", dsChangeNumber);
- abandonChange(dsChangeNumber);
+ abandonChange(dsChangeNumber, toCrossHost);
}
}
}
@@ -391,6 +431,8 @@
sdsMergeInput.subject = mdsMergeInput.subject;
sdsMergeInput.downstreamBranch = downstreamBranch;
sdsMergeInput.doMerge = mdsMergeInput.dsBranchMap.get(downstreamBranch);
+ sdsMergeInput.fromCrossHost = mdsMergeInput.fromCrossHostMap.get(downstreamBranch);
+ sdsMergeInput.toCrossHost = mdsMergeInput.toCrossHostMap.get(downstreamBranch);
try {
createSingleDownstreamMerge(sdsMergeInput);
} catch (MergeConflictException e) {
@@ -426,12 +468,12 @@
* @throws OrmException Throws if we fail to open the request context
*/
public List<Integer> getExistingMergesOnBranch(
- String upstreamRevision, String topic, String downstreamBranch)
+ String upstreamRevision, String topic, String downstreamBranch, String hostname)
throws RestApiException, InvalidQueryParameterException, OrmException,
ConfigInvalidException {
try (ManualRequestContext ctx = oneOffRequestContext.openAs(config.getContextUserId())) {
List<Integer> downstreamChangeNumbers = new ArrayList<>();
- List<ChangeInfo> changes = getChangesInTopicAndBranch(topic, downstreamBranch);
+ List<ChangeInfo> changes = getChangesInTopicAndBranch(topic, downstreamBranch, hostname);
for (ChangeInfo change : changes) {
String changeRevision = change.currentRevision;
@@ -488,7 +530,9 @@
downstreamChangeInput.baseChange =
getBaseChangeId(
getChangeParents(sdsMergeInput.changeNumber, sdsMergeInput.currentRevision),
- sdsMergeInput.downstreamBranch);
+ sdsMergeInput.downstreamBranch,
+ sdsMergeInput.fromCrossHost,
+ sdsMergeInput.toCrossHost);
if (!sdsMergeInput.doMerge) {
mergeInput.strategy = "ours";
@@ -501,8 +545,9 @@
sdsMergeInput.downstreamBranch);
}
- ChangeApi downstreamChange = gApi.changes().create(downstreamChangeInput);
- tagChange(downstreamChange.get(), "Automerger change created!");
+ ChangeApi downstreamChange =
+ apiManager.forHostname(sdsMergeInput.toCrossHost).changes().create(downstreamChangeInput);
+ tagChange(downstreamChange.get(), "Automerger change created!", sdsMergeInput.toCrossHost);
}
}
@@ -530,19 +575,21 @@
* @throws InvalidQueryParameterException
* @throws RestApiException
*/
- private String getBaseChangeId(List<String> parents, String branch)
+ private String getBaseChangeId(
+ List<String> parents, String branch, String fromCrossHost, String toCrossHost)
throws InvalidQueryParameterException, RestApiException {
if (parents.isEmpty()) {
log.info("No base change id for change with no parents.");
return null;
}
// 1) Get topic of first parent
- String firstParentTopic = getTopic(parents.get(0));
+ String firstParentTopic = getTopic(parents.get(0), fromCrossHost);
if (firstParentTopic == null) {
return null;
}
// 2) query that topic and use that to find A'
- List<ChangeInfo> changesInTopic = getChangesInTopicAndBranch(firstParentTopic, branch);
+ List<ChangeInfo> changesInTopic =
+ getChangesInTopicAndBranch(firstParentTopic, branch, toCrossHost);
String firstParent = parents.get(0);
for (ChangeInfo change : changesInTopic) {
List<CommitInfo> topicChangeParents =
@@ -568,8 +615,9 @@
return;
}
- // Map whether or not we should merge it or skip it for each downstream
+ // Map of whether or not we should merge it or skip it for each downstream
Map<String, Boolean> dsBranchMap = new HashMap<String, Boolean>();
+ // Map of downstream branch to corresponding API to use.
for (String downstreamBranch : downstreamBranches) {
boolean isSkipMerge = config.isSkipMerge(change.branch, downstreamBranch, change.subject);
dsBranchMap.put(downstreamBranch, !isSkipMerge);
@@ -583,11 +631,14 @@
mdsMergeInput.dsBranchMap = dsBranchMap;
mdsMergeInput.changeNumber = change._number;
mdsMergeInput.patchsetNumber = revisionInfo._number;
+ mdsMergeInput.sourceBranch = change.branch;
mdsMergeInput.project = change.project;
mdsMergeInput.topic = getOrSetTopic(change._number, change.topic);
mdsMergeInput.subject = change.subject;
mdsMergeInput.obsoleteRevision = previousRevision;
mdsMergeInput.currentRevision = currentRevision;
+ mdsMergeInput.fromCrossHostMap = config.getFromCrossHostMap(change.branch, downstreamBranches);
+ mdsMergeInput.toCrossHostMap = config.getToCrossHostMap(change.branch, downstreamBranches);
createMergesAndHandleConflicts(mdsMergeInput);
}
@@ -602,11 +653,13 @@
}
for (String downstreamBranch : downstreamBranches) {
+ String toCrossHost = config.getToCrossHost(change.branch, downstreamBranch);
+
List<Integer> existingDownstream =
- getExistingMergesOnBranch(revision, change.topic, downstreamBranch);
+ getExistingMergesOnBranch(revision, change.topic, downstreamBranch, toCrossHost);
log.debug("Abandoning existing downstreams: {}", existingDownstream);
for (Integer changeNumber : existingDownstream) {
- abandonChange(changeNumber);
+ abandonChange(changeNumber, toCrossHost);
}
}
} catch (RestApiException | IOException | InvalidQueryParameterException e) {
@@ -614,7 +667,8 @@
}
}
- private void updateVote(ChangeInfo change, String label, short vote) throws RestApiException {
+ private void updateVote(ChangeInfo change, String label, short vote, String hostname)
+ throws RestApiException {
log.debug("Giving {} for label {} to {}", vote, label, change.id);
// Vote on all downstream branches unless merge conflict.
ReviewInput reviewInput = new ReviewInput();
@@ -624,19 +678,30 @@
reviewInput.notify = NotifyHandling.NONE;
reviewInput.tag = AUTOMERGER_TAG;
try {
- gApi.changes().id(change.id).revision(CURRENT).review(reviewInput);
+ apiManager
+ .forHostname(hostname)
+ .changes()
+ .id(change.id)
+ .revision(CURRENT)
+ .review(reviewInput);
} catch (AuthException e) {
log.error("Automerger could not set label, but still continuing.", e);
}
}
- private void tagChange(ChangeInfo change, String message) throws RestApiException {
+ private void tagChange(ChangeInfo change, String message, String hostname)
+ throws RestApiException {
ReviewInput reviewInput = new ReviewInput();
reviewInput.message(message);
reviewInput.notify = NotifyHandling.NONE;
reviewInput.tag = AUTOMERGER_TAG;
try {
- gApi.changes().id(change.id).revision(CURRENT).review(reviewInput);
+ apiManager
+ .forHostname(hostname)
+ .changes()
+ .id(change.id)
+ .revision(CURRENT)
+ .review(reviewInput);
} catch (AuthException e) {
log.error("Automerger could not set label, but still continuing.", e);
}
@@ -645,10 +710,12 @@
private void updateDownstreamMerge(
String newParentRevision,
String upstreamSubject,
- Integer sourceNum,
+ Integer existingDownstreamNum,
boolean doMerge,
Integer upstreamChangeNumber,
- String downstreamBranch)
+ String downstreamBranch,
+ String fromCrossHost,
+ String toCrossHost)
throws RestApiException, InvalidQueryParameterException {
MergeInput mergeInput = new MergeInput();
mergeInput.source = newParentRevision;
@@ -661,15 +728,19 @@
mergeInput.strategy = "ours";
mergePatchSetInput.subject =
getSubjectForDownstreamMerge(upstreamSubject, newParentRevision, true);
- log.debug("Skipping merge for {} on {}", newParentRevision, sourceNum);
+ log.debug("Skipping merge for {} on {}", newParentRevision, existingDownstreamNum);
}
mergePatchSetInput.merge = mergeInput;
mergePatchSetInput.baseChange =
getBaseChangeId(
- getChangeParents(upstreamChangeNumber, newParentRevision), downstreamBranch);
+ getChangeParents(upstreamChangeNumber, newParentRevision),
+ downstreamBranch,
+ fromCrossHost,
+ toCrossHost);
- ChangeApi originalChange = gApi.changes().id(sourceNum);
+ ChangeApi originalChange =
+ apiManager.forHostname(toCrossHost).changes().id(existingDownstreamNum);
if (originalChange.info().status == ChangeStatus.ABANDONED) {
RestoreInput restoreInput = new RestoreInput();
@@ -699,20 +770,28 @@
return previousRevision;
}
- private ChangeInfo getOriginalChange(int changeNumber, String currentRevision)
- throws RestApiException, InvalidQueryParameterException {
+ private ChangeInfo getOriginalChange(
+ int changeNumber, String currentRevision, String downstreamBranch, String hostname)
+ throws RestApiException, InvalidQueryParameterException, ConfigInvalidException {
List<String> parents = getChangeParents(changeNumber, currentRevision);
if (parents.size() >= 2) {
String secondParentRevision = parents.get(1);
- String topic = gApi.changes().id(changeNumber).topic();
- List<ChangeInfo> changesInTopic = getChangesInTopic(topic);
+ String topic = apiManager.forHostname(hostname).changes().id(changeNumber).topic();
+ List<ChangeInfo> changesInTopic = getChangesInTopic(topic, hostname);
for (ChangeInfo change : changesInTopic) {
+ String newHostname = hostname;
+ String fromCrossHost = config.getFromCrossHost(change.branch, downstreamBranch);
+ if (fromCrossHost != null) {
+ newHostname = fromCrossHost;
+ }
if (change.currentRevision.equals(secondParentRevision)) {
- return getOriginalChange(change._number, secondParentRevision);
+ return getOriginalChange(
+ change._number, secondParentRevision, change.branch, newHostname);
}
}
}
- return gApi.changes().id(changeNumber).get();
+
+ return apiManager.forHostname(hostname).changes().id(changeNumber).get();
}
private List<String> getChangeParents(int changeNumber, String currentRevision)
@@ -729,19 +808,22 @@
return parents;
}
- private void abandonChange(Integer changeNumber) throws RestApiException {
+ private void abandonChange(Integer changeNumber, String toCrossHost) throws RestApiException {
log.debug("Abandoning change: {}", changeNumber);
AbandonInput abandonInput = new AbandonInput();
abandonInput.notify = NotifyHandling.NONE;
abandonInput.message = "Merge parent updated; abandoning due to upstream conflict.";
- gApi.changes().id(changeNumber).abandon(abandonInput);
+ apiManager.forHostname(toCrossHost).changes().id(changeNumber).abandon(abandonInput);
}
- private String getTopic(String revision) throws InvalidQueryParameterException, RestApiException {
+ private String getTopic(String revision, String hostname)
+ throws InvalidQueryParameterException, RestApiException {
QueryBuilder queryBuilder = new QueryBuilder();
queryBuilder.addParameter("commit", revision);
List<ChangeInfo> changes =
- gApi.changes()
+ apiManager
+ .forHostname(hostname)
+ .changes()
.query(queryBuilder.get())
.withOption(ListChangesOption.CURRENT_REVISION)
.get();
@@ -762,20 +844,25 @@
return queryBuilder;
}
- private List<ChangeInfo> getChangesInTopic(String topic)
+ private List<ChangeInfo> getChangesInTopic(String topic, String hostname)
throws InvalidQueryParameterException, RestApiException {
QueryBuilder queryBuilder = constructTopicQuery(topic);
- return gApi.changes()
+ return apiManager
+ .forHostname(hostname)
+ .changes()
.query(queryBuilder.get())
.withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
.get();
}
- private List<ChangeInfo> getChangesInTopicAndBranch(String topic, String downstreamBranch)
+ private List<ChangeInfo> getChangesInTopicAndBranch(
+ String topic, String downstreamBranch, String hostname)
throws InvalidQueryParameterException, RestApiException {
QueryBuilder queryBuilder = constructTopicQuery(topic);
queryBuilder.addParameter("branch", downstreamBranch);
- return gApi.changes()
+ return apiManager
+ .forHostname(hostname)
+ .changes()
.query(queryBuilder.get())
.withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
.get();
@@ -785,7 +872,8 @@
throws InvalidQueryParameterException, RestApiException {
// If we've already merged this commit to this branch, don't do it again.
List<ChangeInfo> changes =
- getChangesInTopicAndBranch(currentTopic, sdsMergeInput.downstreamBranch);
+ getChangesInTopicAndBranch(
+ currentTopic, sdsMergeInput.downstreamBranch, sdsMergeInput.toCrossHost);
for (ChangeInfo change : changes) {
if (change.branch.equals(sdsMergeInput.downstreamBranch)) {
List<CommitInfo> parents = change.revisions.get(change.currentRevision).commit.parents;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/MultipleDownstreamMergeInput.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/MultipleDownstreamMergeInput.java
index a62d9a7..d420d57 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/MultipleDownstreamMergeInput.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/MultipleDownstreamMergeInput.java
@@ -23,9 +23,12 @@
public Map<String, Boolean> dsBranchMap;
public int changeNumber;
public int patchsetNumber;
+ public String sourceBranch;
public String project;
public String topic;
public String subject;
public String obsoleteRevision;
public String currentRevision;
+ public Map<String, String> fromCrossHostMap;
+ public Map<String, String> toCrossHostMap;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/automerger/SingleDownstreamMergeInput.java b/src/main/java/com/googlesource/gerrit/plugins/automerger/SingleDownstreamMergeInput.java
index 5a5f0e7..4e4740c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/automerger/SingleDownstreamMergeInput.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/automerger/SingleDownstreamMergeInput.java
@@ -24,4 +24,6 @@
public String subject;
public String downstreamBranch;
public boolean doMerge;
+ public String fromCrossHost;
+ public String toCrossHost;
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java
index d692e95..91bb93a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java
@@ -181,6 +181,20 @@
.isEqualTo(expectedBranches);
}
+ @Test
+ public void getFromCrossHostTest() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(configLoader.getFromCrossHost("other_host_branch", "this_host_branch"))
+ .isEqualTo("https://boogieplex-android.example.com");
+ }
+
+ @Test
+ public void getToCrossHostTest() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(configLoader.getToCrossHost("this_host_branch", "that_host_branch"))
+ .isEqualTo("https://boogieplex-chrome.example.com");
+ }
+
private void defaultSetup(String resourceName) throws Exception {
createProject("All-Projects");
manifestNameKey = createProject("platform/manifest");
diff --git a/src/test/resources/com/googlesource/gerrit/plugins/automerger/automerger.config b/src/test/resources/com/googlesource/gerrit/plugins/automerger/automerger.config
index ea54637..82c4b6a 100644
--- a/src/test/resources/com/googlesource/gerrit/plugins/automerger/automerger.config
+++ b/src/test/resources/com/googlesource/gerrit/plugins/automerger/automerger.config
@@ -9,6 +9,12 @@
setProjects = platform/other/project
[automerger "ds_two:ds_three"]
setProjects = platform/some/project
+[automerger "other_host_branch:this_host_branch"]
+ setProjects = platform/some/project
+ fromCrossHost = https://boogieplex-android.example.com
+[automerger "this_host_branch:that_host_branch"]
+ setProjects = platform/some/project
+ toCrossHost = https://boogieplex-chrome.example.com
[global]
alwaysBlankMerge = .*Import translations. DO NOT MERGE.*
alwaysBlankMerge = .*DO NOT MERGE ANYWHERE.*