aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java')
-rw-r--r--src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java
new file mode 100644
index 0000000..d6cba28
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java
@@ -0,0 +1,175 @@
+//
+// Copyright (C) 2019 The Qt Company
+//
+
+package com.googlesource.gerrit.plugins.qtcodereview;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.InternalUser;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.permissions.ProjectPermission;
+import com.google.gerrit.server.permissions.RefPermission;
+import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.gerrit.server.project.NoSuchRefException;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.update.BatchUpdate;
+import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.util.time.TimeUtil;
+import com.google.gerrit.sshd.SshCommand;
+import com.google.gerrit.sshd.CommandMetaData;
+
+import com.google.gwtorm.server.OrmException;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.kohsuke.args4j.Option;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map.Entry;
+
+@CommandMetaData(name="staging-new-build", description="Create unique build branch of the current staging branch and change the gerrit status of the changes to INTEGRATING.")
+class QtCommandNewBuild extends SshCommand {
+
+ @Inject
+ private PermissionBackend permissionBackend;
+
+ @Inject
+ private GitRepositoryManager gitManager;
+
+ @Inject
+ private Provider<ReviewDb> dbProvider;
+
+ @Inject
+ private BatchUpdate.Factory updateFactory;
+
+ @Inject
+ private QtUtil qtUtil;
+
+ @Inject
+ private QtChangeUpdateOp.Factory qtUpdateFactory;
+
+ @Option(name = "--project", aliases = {"-p"},
+ required = true, usage = "project name")
+ private String project;
+
+ @Option(name = "--staging-branch", aliases = {"-s"},
+ required = true, usage = "branch name, e.g. refs/staging/master or just master")
+ private String stagingBranch;
+
+ @Option(name = "--build-id", aliases = {"-i"},
+ required = true, usage = "build id, e.g. refs/builds/my_build or just my_build")
+ private String build;
+
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private Repository git;
+
+
+ @Override
+ protected void run() throws UnloggedFailure {
+
+ logger.atInfo().log("qtcodereview: staging-new-build -p %s -s %s -i %s", project, stagingBranch, build);
+
+ try {
+ Project.NameKey projectKey = new Project.NameKey(project);
+ git = gitManager.openRepository(projectKey);
+
+ Branch.NameKey buildBranchKey = QtUtil.getNameKeyLong(project, QtUtil.R_BUILDS, build);
+ Branch.NameKey stagingBranchKey = QtUtil.getNameKeyLong(project, QtUtil.R_STAGING, stagingBranch);
+ Branch.NameKey destBranchShortKey = QtUtil.getNameKeyShort(project, QtUtil.R_STAGING, stagingBranch);
+ Branch.NameKey destinationKey = QtUtil.getNameKeyLong(project, QtUtil.R_HEADS, stagingBranch);
+
+ // Check required permissions
+ permissionBackend.user(user).project(projectKey).ref(destinationKey.get()).check(RefPermission.UPDATE);
+ permissionBackend.user(user).project(projectKey).ref(buildBranchKey.get()).check(RefPermission.CREATE);
+
+ if (QtUtil.branchExists(git, buildBranchKey) == true) {
+ logger.atSevere().log("qtcodereview: staging-new-build Target build %s already exists", buildBranchKey);
+ throw die("Target build already exists!");
+ }
+
+ if (QtUtil.branchExists(git, stagingBranchKey) == false) {
+ logger.atSevere().log("qtcodereview: staging-new-build staging ref %s not found", stagingBranchKey);
+ throw die("Staging ref not found!");
+ }
+
+ // Create build reference.
+ Result result = qtUtil.createBuildRef(git, user.asIdentifiedUser(),
+ projectKey, stagingBranchKey, buildBranchKey);
+ String message = String.format("Added to build %s for %s", build, destinationKey);
+
+ if (result != Result.NEW && result != Result.FAST_FORWARD) {
+ logger.atSevere().log("qtcodereview: staging-new-build failed to create new build ref %s result %s",
+ buildBranchKey, result);
+ throw new UnloggedFailure(1, "fatal: failed to create new build ref: " + result);
+ } else {
+ // list the changes in staging branch but missing from the destination branch
+ List<Entry<ChangeData, RevCommit>> openChanges = qtUtil.listChangesNotMerged(git, buildBranchKey, destBranchShortKey);
+
+ // Make sure that there are changes in the staging branch.
+ if (openChanges.isEmpty()) {
+ logger.atSevere().log("qtcodereview: staging-new-build No changes in staging branch %s.", stagingBranchKey);
+ throw die("No changes in staging branch. Not creating a build reference");
+ }
+
+ QtChangeUpdateOp op = qtUpdateFactory.create(Change.Status.INTEGRATING, message, null, null, null);
+ try (BatchUpdate u = updateFactory.create(dbProvider.get(), projectKey, user, TimeUtil.nowTs())) {
+ for (Entry<ChangeData, RevCommit> item: openChanges) {
+ Change change = item.getKey().change();
+ logger.atInfo().log("qtcodereview: staging-new-build inserted change %s (%s) into build %s for %s",
+ change, item.getValue().toString(), build, destinationKey);
+ u.addOp(change.getId(), op);
+ }
+ u.execute();
+ }
+ }
+
+ logger.atInfo().log("qtcodereview: staging-new-build build %s for %s created", build, destBranchShortKey);
+
+ } catch (AuthException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Authentication failed to access repository: %s", e);
+ throw die("Authentication failed to access repository");
+ } catch (PermissionBackendException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Not enough permissions to access repository %s", e);
+ throw die("Not enough permissions to access repository");
+ } catch (RepositoryNotFoundException e) {
+ throw die("project not found");
+ } catch (IOException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Failed to access repository %s", e);
+ throw die("Failed to access repository");
+ } catch (OrmException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Failed to access database %s", e);
+ throw die("Failed to access database");
+ } catch (QtUtil.BranchNotFoundException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Failed to access build or staging ref %s", e);
+ throw die("Failed to access build or staging ref");
+ } catch (NoSuchRefException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build Invalid branch name %s", e);
+ throw die("Invalid branch name");
+ } catch (UpdateException | RestApiException e) {
+ logger.atSevere().log("qtcodereview: staging-new-build failed to update change status %s", e);
+ throw die("Failed to update change status");
+ } finally {
+ if (git != null) {
+ git.close();
+ }
+ }
+ }
+
+}