summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChad Horohoe <chorohoe@wikimedia.org>2013-06-07 20:56:23 -0400
committerIsmo Haataja <ismo.haataja@digia.com>2014-10-28 14:34:54 +0100
commitdc296fdabc5f55adff75a9e59c5f1c20b5a9802f (patch)
tree69f6f0af65a61ac2ce65fe55658987dd50dbfc39 /src
parentdf8cb393676880b6e27b42d4b49492be0804c0ee (diff)
Implement pattern-based project matching in replication.config
This allows you to use remote.$name.projects to either - Do wildcard-style matching, such as foo/* - Do regular-expression matching, such as ^foo/(bar|baz)$ Task-number: QTQAINFRA-892 Change-Id: I453d99ca354afeaf6dfbe467c7a81d2eb5440a74 (cherry picked from commit 0b9811b3bcd13e9d858d341935e660117c735569) Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Ismo Haataja <ismo.haataja@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java42
-rw-r--r--src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java11
-rw-r--r--src/main/resources/Documentation/config.md27
3 files changed, 76 insertions, 4 deletions
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 8256282..5032dd8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -18,6 +18,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
+import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
@@ -66,6 +67,7 @@ class Destination {
private final RemoteConfig remote;
private final String[] adminUrls;
+ private final String[] projects;
private final int delay;
private final int retryDelay;
private final Map<URIish, PushOne> pending = new HashMap<URIish, PushOne>();
@@ -97,6 +99,7 @@ class Destination {
cfg.getBoolean("remote", rc.getName(), "replicatePermissions", true);
remoteNameStyle = Objects.firstNonNull(
cfg.getString("remote", rc.getName(), "remoteNameStyle"), "slash");
+ projects = cfg.getStringList("remote", rc.getName(), "projects");
final CurrentUser remoteUser;
String[] authGroupNames = cfg.getStringList("remote", rc.getName(), "authGroup");
@@ -333,6 +336,45 @@ class Destination {
}
}
+ boolean wouldPushProject(Project.NameKey project) {
+ // by default push all projects
+ if (projects.length < 1) {
+ return true;
+ }
+
+ String projectName = project.get();
+ for (final String projectMatch : projects) {
+ if (isRE(projectMatch)) {
+ // projectMatch is a regular expression
+ if (projectName.matches(projectMatch)) {
+ return true;
+ }
+ } else if (isWildcard(projectMatch)) {
+ // projectMatch is a wildcard
+ if (projectName.startsWith(
+ projectMatch.substring(0, projectMatch.length() - 1))) {
+ return true;
+ }
+ } else {
+ // No special case, so we try to match directly
+ if (projectName.equals(projectMatch)) {
+ return true;
+ }
+ }
+ }
+
+ // Nothing matched, so don't push the project
+ return false;
+ }
+
+ private static boolean isRE(String str) {
+ return str.startsWith(AccessSection.REGEX_PREFIX);
+ }
+
+ private static boolean isWildcard(String str) {
+ return str.endsWith("*");
+ }
+
boolean wouldPushRef(String ref) {
if (!replicatePermissions && GitRepositoryManager.REF_CONFIG.equals(ref)) {
return false;
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 a6599fa..8991b7c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -129,8 +129,10 @@ class ReplicationQueue implements
}
for (Destination cfg : configs) {
- for (URIish uri : cfg.getURIs(project, urlMatch)) {
- cfg.schedule(project, PushOne.ALL_REFS, uri);
+ if (cfg.wouldPushProject(project)) {
+ for (URIish uri : cfg.getURIs(project, urlMatch)) {
+ cfg.schedule(project, PushOne.ALL_REFS, uri);
+ }
}
}
}
@@ -145,7 +147,7 @@ class ReplicationQueue implements
Project.NameKey project = new Project.NameKey(event.getProjectName());
for (GitReferenceUpdatedListener.Update u : event.getUpdates()) {
for (Destination cfg : configs) {
- if (cfg.wouldPushRef(u.getRefName())) {
+ if (cfg.wouldPushProject(project) && cfg.wouldPushRef(u.getRefName())) {
for (URIish uri : cfg.getURIs(project, null)) {
cfg.schedule(project, u.getRefName(), uri);
}
@@ -241,6 +243,9 @@ class ReplicationQueue implements
Project.NameKey projectName = new Project.NameKey(event.getProjectName());
for (Destination config : configs) {
+ if (!config.wouldPushProject(projectName)) {
+ continue;
+ }
List<URIish> uriList = config.getURIs(projectName, "*");
String[] adminUrls = config.getAdminUrls();
boolean adminURLUsed = false;
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index fd90581..4efcebe 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -198,7 +198,7 @@ remote.NAME.authGroup
can be specified for this group to control if a project should
be replicated or not to the remote.
- By default, replicates without group control, i.e replicates
+ By default, replicates without group control, i.e. replicates
everything to all remotes.
remote.NAME.replicatePermissions
@@ -229,6 +229,31 @@ remote.NAME.remoteNameStyle
By default, "slash," remote name will contain slashes as they
do in Gerrit.
+remote.NAME.projects
+: Specifies which repositories should be replicated to the
+ remote. It can be provided more than once, and supports three
+ formats: regular expressions, wildcard matching, and single
+ project matching. All three formats match case-sensitive.
+
+ Values starting with a caret `^` are treated as regular
+ expressions. `^foo/(bar|baz)` would match the projects
+ `foo/bar`, and `foo/baz`. Regular expressions have to fully
+ match the project name. So the above example would not match
+ `foo/bar2`, while `^foo/(bar|baz).*` would.
+
+ Values that are not regular expressions and end in `*` are
+ treated as wildcard matches. Wildcards match projects whose
+ name agrees from the beginning until the trailing `*`. So
+ `foo/b*` would match the projects `foo/b`, `foo/bar`, and
+ `foo/baz`, but neither `foobar`, nor `bar/foo/baz`.
+
+ Values that are neither regular expressions nor wildcards are
+ treated as single project matches. So `foo/bar` matches only
+ the project `foo/bar`, but no other project.
+
+ By default, replicates without matching, i.e. replicates
+ everything to all remotes.
+
File `secure.config`
--------------------