Merge branch 'stable-3.3' into stable-3.4
* stable-3.3:
Add step to check for collisions to magic refs
Add branch protection check during the project import
Set version to 3.3.0
Change-Id: I30951d25d4461d17d313682e208059b91f61e2cd
diff --git a/README.md b/README.md
index 018f4d0..d01069d 100644
--- a/README.md
+++ b/README.md
@@ -190,3 +190,22 @@
After the installation, Eclipse must be restarted and compilation
errors should disappear.
+
+### Notes
+
+#### Magic refs
+
+Before importing a repository from github, this plugin checks that its git refs
+do not clash with Gerrit magic refs, since importing those refs would prevent
+users from creating change requests.
+
+Attempting to import repositories having refs starting with `refs/for/` or
+`refs/meta` will fail with an error message.
+For example:
+
+```text
+Found 2 ref(s): Please remove or rename the following refs and try again:
+ refs/for/foo, refs/meta/bar
+```
+
+More information on Gerrit magic refs can be found [here](https://gerrit-review.googlesource.com/Documentation/intro-user.html#upload-change)
\ No newline at end of file
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
index 12acdb2..f75030d 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/GuiceHttpModule.java
@@ -24,6 +24,8 @@
import com.googlesource.gerrit.plugins.github.git.GitCloneStep;
import com.googlesource.gerrit.plugins.github.git.GitHubRepository;
import com.googlesource.gerrit.plugins.github.git.GitImporter;
+import com.googlesource.gerrit.plugins.github.git.MagicRefCheckStep;
+import com.googlesource.gerrit.plugins.github.git.ProtectedBranchesCheckStep;
import com.googlesource.gerrit.plugins.github.git.PullRequestImportJob;
import com.googlesource.gerrit.plugins.github.git.ReplicateProjectStep;
import com.googlesource.gerrit.plugins.github.notification.WebhookServlet;
@@ -51,6 +53,10 @@
install(
new FactoryModuleBuilder()
+ .implement(ProtectedBranchesCheckStep.class, ProtectedBranchesCheckStep.class)
+ .build(ProtectedBranchesCheckStep.Factory.class));
+ install(
+ new FactoryModuleBuilder()
.implement(GitCloneStep.class, GitCloneStep.class)
.build(GitCloneStep.Factory.class));
install(
@@ -63,6 +69,10 @@
.build(ReplicateProjectStep.Factory.class));
install(
new FactoryModuleBuilder()
+ .implement(MagicRefCheckStep.class, MagicRefCheckStep.class)
+ .build(MagicRefCheckStep.Factory.class));
+ install(
+ new FactoryModuleBuilder()
.implement(PullRequestImportJob.class, PullRequestImportJob.class)
.build(PullRequestImportJob.Factory.class));
install(
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
index 4421841..753575f 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/AbstractCloneJob.java
@@ -26,6 +26,9 @@
protected String getErrorDescription(Throwable exception) {
LOG.error("Job " + this + " FAILED", exception);
+ if (exception instanceof ProtectedBranchFoundException) {
+ return exception.getMessage();
+ }
if (GitException.class.isAssignableFrom(exception.getClass())) {
return ((GitException) exception).getErrorDescription();
} else if (ProvisionException.class.isAssignableFrom(exception.getClass())) {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
index 0176091..ff81411 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitImporter.java
@@ -26,31 +26,48 @@
public static class Provider extends HttpSessionProvider<GitImporter> {}
private static final Logger log = LoggerFactory.getLogger(GitImporter.class);
+ private final ProtectedBranchesCheckStep.Factory protectedBranchesCheckFactory;
+ private final MagicRefCheckStep.Factory magicRefCheckFactory;
private final GitCloneStep.Factory cloneFactory;
private final CreateProjectStep.Factory projectFactory;
private final ReplicateProjectStep.Factory replicateFactory;
@Inject
public GitImporter(
+ ProtectedBranchesCheckStep.Factory protectedBranchesCheckFactory,
GitCloneStep.Factory cloneFactory,
CreateProjectStep.Factory projectFactory,
ReplicateProjectStep.Factory replicateFactory,
+ MagicRefCheckStep.Factory magicRefCheckFactory,
JobExecutor executor,
IdentifiedUser user) {
super(executor, user);
+ this.protectedBranchesCheckFactory = protectedBranchesCheckFactory;
this.cloneFactory = cloneFactory;
this.projectFactory = projectFactory;
this.replicateFactory = replicateFactory;
+ this.magicRefCheckFactory = magicRefCheckFactory;
}
public void clone(int idx, String organisation, String repository, String description) {
try {
+ ProtectedBranchesCheckStep protectedBranchesCheckStep =
+ protectedBranchesCheckFactory.create(organisation, repository);
GitCloneStep cloneStep = cloneFactory.create(organisation, repository);
+ MagicRefCheckStep magicRefCheckStep = magicRefCheckFactory.create(organisation, repository);
CreateProjectStep projectStep =
projectFactory.create(organisation, repository, description, user.getUserName().get());
ReplicateProjectStep replicateStep = replicateFactory.create(organisation, repository);
GitImportJob gitCloneJob =
- new GitImportJob(idx, organisation, repository, cloneStep, projectStep, replicateStep);
+ new GitImportJob(
+ idx,
+ organisation,
+ repository,
+ protectedBranchesCheckStep,
+ magicRefCheckStep,
+ cloneStep,
+ projectStep,
+ replicateStep);
log.debug("New Git clone job created: " + gitCloneJob);
schedule(idx, gitCloneJob);
} catch (Throwable e) {
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefCheckStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefCheckStep.java
new file mode 100644
index 0000000..616a31c
--- /dev/null
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefCheckStep.java
@@ -0,0 +1,72 @@
+// Copyright (C) 2021 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.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.server.util.MagicBranch;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.github.GitHubConfig;
+import java.util.List;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.kohsuke.github.GHRef;
+
+public class MagicRefCheckStep extends ImportStep {
+ public interface Factory {
+ MagicRefCheckStep create(
+ @Assisted("organisation") String organisation, @Assisted("name") String repository);
+ }
+
+ @Inject
+ public MagicRefCheckStep(
+ GitHubConfig config,
+ GitHubRepository.Factory gitHubRepoFactory,
+ @Assisted("organisation") String organisation,
+ @Assisted("name") String repository) {
+ super(config.gitHubUrl, organisation, repository, gitHubRepoFactory);
+ }
+
+ @Override
+ public void doImport(ProgressMonitor progress) throws Exception {
+ try {
+ GHRef[] allRefs = getRepository().getRefs();
+ progress.beginTask("Checking magic refs", allRefs.length);
+
+ List<String> offendingRefs = Lists.newLinkedList();
+ for (GHRef ref : allRefs) {
+ if (MagicBranch.isMagicBranch(ref.getRef())
+ || ref.getRef().startsWith(RefNames.REFS_META)) {
+ offendingRefs.add(ref.getRef());
+ }
+ progress.update(1);
+ }
+
+ if (!offendingRefs.isEmpty()) {
+ throw new MagicRefFoundException(
+ String.format(
+ "Found %d ref(s): Please remove or rename the following ref(s) and try again: %s",
+ offendingRefs.size(), Joiner.on(", ").join(offendingRefs)));
+ }
+ } finally {
+ progress.endTask();
+ }
+ }
+
+ @Override
+ public boolean rollback() {
+ return true;
+ }
+}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefFoundException.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefFoundException.java
new file mode 100644
index 0000000..263ee9d
--- /dev/null
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/MagicRefFoundException.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 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;
+
+public class MagicRefFoundException extends GitException {
+
+ public MagicRefFoundException(String message) {
+ super(message);
+ }
+
+ @Override
+ public String getErrorDescription() {
+ return String.format("Clash with Gerrit magic refs. %s", getMessage());
+ }
+}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchFoundException.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchFoundException.java
new file mode 100644
index 0000000..221152f
--- /dev/null
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchFoundException.java
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 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;
+
+public class ProtectedBranchFoundException extends Exception {
+
+ public ProtectedBranchFoundException(String msg) {
+ super(msg);
+ }
+}
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchesCheckStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchesCheckStep.java
new file mode 100644
index 0000000..5b2f763
--- /dev/null
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/ProtectedBranchesCheckStep.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2021 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.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.github.GitHubConfig;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.kohsuke.github.GHBranch;
+
+public class ProtectedBranchesCheckStep extends ImportStep {
+
+ public interface Factory {
+ ProtectedBranchesCheckStep create(
+ @Assisted("organisation") String organisation, @Assisted("name") String repository);
+ }
+
+ @Inject
+ public ProtectedBranchesCheckStep(
+ GitHubConfig config,
+ GitHubRepository.Factory gitHubRepoFactory,
+ @Assisted("organisation") String organisation,
+ @Assisted("name") String repository) {
+ super(config.gitHubUrl, organisation, repository, gitHubRepoFactory);
+ }
+
+ @Override
+ public void doImport(ProgressMonitor progress) throws Exception {
+ Collection<GHBranch> branches = getRepository().getBranches().values();
+ progress.beginTask("Checking branch protection", branches.size());
+ List<String> protectedBranchNames = Lists.newLinkedList();
+ for (GHBranch branch : branches) {
+ if (branch.isProtected()) {
+ protectedBranchNames.add(branch.getName());
+ }
+ progress.update(1);
+ }
+ progress.endTask();
+ if (!protectedBranchNames.isEmpty()) {
+ throw new ProtectedBranchFoundException(
+ String.format(
+ "Cannot import project with protected branches, you should remove protection from:%s",
+ Joiner.on(",").join(protectedBranchNames)));
+ }
+ }
+
+ @Override
+ public boolean rollback() {
+ return true;
+ }
+}