Merge "Add adminUrl to replication for repository creation"
diff --git a/Documentation/config-replication.txt b/Documentation/config-replication.txt
index 76b7fff..81fda98 100644
--- a/Documentation/config-replication.txt
+++ b/Documentation/config-replication.txt
@@ -93,6 +93,19 @@
See link:http://www.kernel.org/pub/software/scm/git/docs/git-push.html#URLS[GIT URLS]
for details on Git URL syntax.
+[[remote.name.url]]remote.<name>.adminUrl::
++
+Address of the alternative remote server only for repository creation. Multiple URLs may
+be specified within a single remote block, listing different
+destinations which share the same settings.
++
+The adminUrl can be used as a ssh alternative to the url option, but only related to repository creation.
+If not specified, the repository creation tries to follow the default way through the url value specified.
++
+It is useful when remote.<name>.url protocols does not allow repository creation
+although their usage are mandatory in the local environment.
+In that case, an alternative ssh url could be specified to repository creation.
+
[[remote.name.receivepack]]remote.<name>.receivepack::
+
Path of the `git-receive-pack` executable on the remote system, if
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
index 9126947..9db9e44 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
@@ -122,7 +122,12 @@
private static String replace(final String pat, final String key,
final String val) {
final int n = pat.indexOf("${" + key + "}");
- return pat.substring(0, n) + val + pat.substring(n + 3 + key.length());
+
+ if (n != -1) {
+ return pat.substring(0, n) + val + pat.substring(n + 3 + key.length());
+ } else {
+ return null;
+ }
}
private List<ReplicationConfig> allConfigs(final SitePaths site)
@@ -162,7 +167,8 @@
}
}
- // In case if refspec destination for push is not set then we assume it is equal to source
+ // In case if refspec destination for push is not set then we assume it is
+ // equal to source
for (RefSpec ref : c.getPushRefSpecs()) {
if (ref.getDestination() == null) {
ref.setDestination(ref.getSource());
@@ -208,9 +214,39 @@
for (ReplicationConfig config : configs) {
List<URIish> uriList = config.getURIs(projectName, "*");
+ String[] adminUrls = config.getAdminUrls();
+ boolean adminURLUsed = false;
- for (URIish uri : uriList) {
- replicateProject(uri, head);
+ for (String url : adminUrls) {
+ URIish adminURI = null;
+ try {
+ if (url != null && !url.isEmpty()) {
+ adminURI = new URIish(url);
+ }
+ } catch (URISyntaxException e) {
+ log.error("The URL '" + url + "' is invalid");
+ }
+
+ if (adminURI != null) {
+ final String replacedPath =
+ replace(adminURI.getPath(), "name", projectName.get());
+ if (replacedPath != null) {
+ adminURI = adminURI.setPath(replacedPath);
+ if (usingSSH(adminURI)) {
+ replicateProject(adminURI, head);
+ adminURLUsed = true;
+ } else {
+ log.error("The adminURL '" + url
+ + "' is non-SSH which is not allowed");
+ }
+ }
+ }
+ }
+
+ if (!adminURLUsed) {
+ for (URIish uri : uriList) {
+ replicateProject(uri, head);
+ }
}
}
}
@@ -296,6 +332,7 @@
static class ReplicationConfig {
private final RemoteConfig remote;
+ private final String[] adminUrls;
private final int delay;
private final int retryDelay;
private final WorkQueue.Executor pool;
@@ -325,6 +362,8 @@
authGroups = ReplicationUser.EVERYTHING_VISIBLE;
}
+ adminUrls = cfg.getStringList("remote", rc.getName(), "adminUrl");
+
final ReplicationUser remoteUser =
replicationUserFactory.create(authGroups);
@@ -492,13 +531,21 @@
final List<URIish> r = new ArrayList<URIish>(remote.getURIs().size());
for (URIish uri : remote.getURIs()) {
if (matches(uri, urlMatch)) {
- uri = uri.setPath(replace(uri.getPath(), "name", project.get()));
- r.add(uri);
+ final String replacedPath =
+ replace(uri.getPath(), "name", project.get());
+ if (replacedPath != null) {
+ uri = uri.setPath(replacedPath);
+ r.add(uri);
+ }
}
}
return r;
}
+ String[] getAdminUrls() {
+ return this.adminUrls;
+ }
+
private boolean matches(URIish uri, final String urlMatch) {
if (urlMatch == null || urlMatch.equals("") || urlMatch.equals("*")) {
return true;