Support deletion of branches via REST
A branch can now be deleted by DELETE on
/projects/<project-name>/branches/<branch-id>.
Change-Id: I2c9af129f024cd2668a46dd2bd8848bd0bc0655c
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 1dc8bc8..42dfcc2 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -598,6 +598,24 @@
}
----
+[[delete-branch]]
+Delete Branch
+~~~~~~~~~~~~~
+[verse]
+'DELETE /projects/link:#project-name[\{project-name\}]/branches/link:#branch-id[\{branch-id\}]'
+
+Deletes a branch.
+
+.Request
+----
+ DELETE /projects/MyProject/branches/stable HTTP/1.0
+----
+
+.Response
+----
+ HTTP/1.1 204 No Content
+----
+
[[child-project-endpoints]]
Child Project Endpoints
-----------------------
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java
index 110fe15..6681d94 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.project;
import com.google.gerrit.extensions.restapi.RestView;
+import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.project.ListBranches.BranchInfo;
import com.google.inject.TypeLiteral;
@@ -32,4 +33,12 @@
public BranchInfo getBranchInfo() {
return branchInfo;
}
+
+ public Branch.NameKey getBranchKey() {
+ return new Branch.NameKey(getNameKey(), branchInfo.ref);
+ }
+
+ public String getRef() {
+ return branchInfo.ref;
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
new file mode 100644
index 0000000..2978c89
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
@@ -0,0 +1,108 @@
+// Copyright (C) 2013 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.google.gerrit.server.project;
+
+import com.google.gerrit.common.ChangeHooks;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.DeleteBranch.Input;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class DeleteBranch implements RestModifyView<BranchResource, Input>{
+ private static final Logger log = LoggerFactory.getLogger(CreateBranch.class);
+
+ static class Input {
+ }
+
+ private final IdentifiedUser identifiedUser;
+ private final GitRepositoryManager repoManager;
+ private final Provider<ReviewDb> dbProvider;
+ private final GitReferenceUpdated referenceUpdated;
+ private final ChangeHooks hooks;
+
+ @Inject
+ DeleteBranch(IdentifiedUser identifiedUser, GitRepositoryManager repoManager,
+ Provider<ReviewDb> dbProvider, GitReferenceUpdated referenceUpdated,
+ ChangeHooks hooks) {
+ this.identifiedUser = identifiedUser;
+ this.repoManager = repoManager;
+ this.dbProvider = dbProvider;
+ this.referenceUpdated = referenceUpdated;
+ this.hooks = hooks;
+ }
+
+ @Override
+ public Object apply(BranchResource rsrc, Input input) throws AuthException,
+ ResourceConflictException, OrmException, IOException {
+ if (!rsrc.getControl().controlForRef(rsrc.getBranchKey()).canDelete()) {
+ throw new AuthException("Cannot delete branch");
+ }
+ if (dbProvider.get().changes().byBranchOpenAll(rsrc.getBranchKey())
+ .iterator().hasNext()) {
+ throw new ResourceConflictException("branch " + rsrc.getBranchKey()
+ + " has open changes");
+ }
+
+ Repository r = repoManager.openRepository(rsrc.getNameKey());
+ try {
+ RefUpdate.Result result;
+ RefUpdate u;
+ try {
+ u = r.updateRef(rsrc.getRef());
+ u.setForceUpdate(true);
+ result = u.delete();
+ } catch (IOException e) {
+ log.error("Cannot delete " + rsrc.getBranchKey(), e);
+ throw e;
+ }
+
+ switch (result) {
+ case NEW:
+ case NO_CHANGE:
+ case FAST_FORWARD:
+ case FORCED:
+ referenceUpdated.fire(rsrc.getNameKey(), u);
+ hooks.doRefUpdatedHook(rsrc.getBranchKey(), u, identifiedUser.getAccount());
+ break;
+
+ case REJECTED_CURRENT_BRANCH:
+ log.warn("Cannot delete " + rsrc.getBranchKey() + ": " + result.name());
+ throw new ResourceConflictException("cannot delete current branch");
+
+ default:
+ log.error("Cannot delete " + rsrc.getBranchKey() + ": " + result.name());
+ throw new ResourceConflictException("cannot delete branch: " + result.name());
+ }
+ } finally {
+ r.close();
+ }
+ return Response.none();
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
index 3b44f66..82b016c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
@@ -55,6 +55,7 @@
child(PROJECT_KIND, "branches").to(BranchesCollection.class);
put(BRANCH_KIND).to(PutBranch.class);
get(BRANCH_KIND).to(GetBranch.class);
+ delete(BRANCH_KIND).to(DeleteBranch.class);
install(new FactoryModuleBuilder().build(CreateBranch.Factory.class));
child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class);