BranchApi: Implement get and delete

Update tests to use new APIs.

Change-Id: I1f27ea08d94ffd97650dccedf818003126bba3a9
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
index 3cadf66..6d93060 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateBranchIT.java
@@ -18,17 +18,25 @@
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static com.google.gerrit.server.project.Util.block;
+import static org.junit.Assert.fail;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.extensions.api.projects.BranchApi;
+import com.google.gerrit.extensions.api.projects.BranchInfo;
+import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.server.git.ProjectConfig;
 
-import org.apache.http.HttpStatus;
+import org.eclipse.jgit.lib.Constants;
 import org.junit.Before;
 import org.junit.Test;
 
+@NoHttpd
 public class CreateBranchIT extends AbstractDaemonTest {
   private Branch.NameKey branch;
 
@@ -39,65 +47,32 @@
 
   @Test
   public void createBranch_Forbidden() throws Exception {
-    RestResponse r =
-        userSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_FORBIDDEN);
+    setApiUser(user);
+    assertCreateFails(AuthException.class);
   }
 
   @Test
   public void createBranchByAdmin() throws Exception {
-    RestResponse r =
-        adminSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_CREATED);
-    r.consume();
-
-    r = adminSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_OK);
+    assertCreateSucceeds();
   }
 
   @Test
   public void branchAlreadyExists_Conflict() throws Exception {
-    RestResponse r =
-        adminSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_CREATED);
-    r.consume();
-
-    r = adminSession.put("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_CONFLICT);
+    assertCreateSucceeds();
+    assertCreateFails(ResourceConflictException.class);
   }
 
   @Test
   public void createBranchByProjectOwner() throws Exception {
     grantOwner();
-
-    RestResponse r =
-        userSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_CREATED);
-    r.consume();
-
-    r = adminSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_OK);
+    setApiUser(user);
+    assertCreateSucceeds();
   }
 
   @Test
   public void createBranchByAdminCreateReferenceBlocked() throws Exception {
     blockCreateReference();
-    RestResponse r =
-        adminSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_CREATED);
-    r.consume();
-
-    r = adminSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_OK);
+    assertCreateSucceeds();
   }
 
   @Test
@@ -105,10 +80,8 @@
       throws Exception {
     grantOwner();
     blockCreateReference();
-    RestResponse r =
-        userSession.put("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_FORBIDDEN);
+    setApiUser(user);
+    assertCreateFails(AuthException.class);
   }
 
   private void blockCreateReference() throws Exception {
@@ -120,4 +93,26 @@
   private void grantOwner() throws Exception {
     allow(Permission.OWNER, REGISTERED_USERS, "refs/*");
   }
+
+  private BranchApi branch() throws Exception {
+    return gApi.projects()
+        .name(branch.getParentKey().get())
+        .branch(branch.get());
+  }
+
+  private void assertCreateSucceeds() throws Exception {
+    BranchInfo created = branch().create(new BranchInput()).get();
+    assertThat(created.ref)
+        .isEqualTo(Constants.R_HEADS + branch.getShortName());
+  }
+
+  private void assertCreateFails(Class<? extends RestApiException> errType)
+      throws Exception {
+    try {
+      branch().create(new BranchInput());
+      fail("Expected " + errType.getSimpleName());
+    } catch (RestApiException expected) {
+      assertThat(expected).isInstanceOf(errType);
+    }
+  }
 }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index 8be6c92..959c280 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -14,21 +14,25 @@
 
 package com.google.gerrit.acceptance.rest.project;
 
-import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static com.google.gerrit.server.project.Util.block;
+import static org.junit.Assert.fail;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.extensions.api.projects.BranchApi;
+import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.server.git.ProjectConfig;
 
-import org.apache.http.HttpStatus;
 import org.junit.Before;
 import org.junit.Test;
 
+@NoHttpd
 public class DeleteBranchIT extends AbstractDaemonTest {
 
   private Branch.NameKey branch;
@@ -36,62 +40,31 @@
   @Before
   public void setUp() throws Exception {
     branch = new Branch.NameKey(project, "test");
-    adminSession.put("/projects/" + project.get()
-        + "/branches/" + branch.getShortName()).consume();
+    branch().create(new BranchInput());
   }
 
   @Test
   public void deleteBranch_Forbidden() throws Exception {
-    RestResponse r =
-        userSession.delete("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_FORBIDDEN);
-    r.consume();
+    setApiUser(user);
+    assertDeleteForbidden();
   }
 
   @Test
   public void deleteBranchByAdmin() throws Exception {
-    RestResponse r =
-        adminSession.delete("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NO_CONTENT);
-    r.consume();
-
-    r = adminSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NOT_FOUND);
-    r.consume();
+    assertDeleteSucceeds();
   }
 
   @Test
   public void deleteBranchByProjectOwner() throws Exception {
     grantOwner();
-
-    RestResponse r =
-        userSession.delete("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NO_CONTENT);
-    r.consume();
-
-    r = userSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NOT_FOUND);
-    r.consume();
+    setApiUser(user);
+    assertDeleteSucceeds();
   }
 
   @Test
   public void deleteBranchByAdminForcePushBlocked() throws Exception {
     blockForcePush();
-    RestResponse r =
-        adminSession.delete("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NO_CONTENT);
-    r.consume();
-
-    r = adminSession.get("/projects/" + project.get()
-        + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_NOT_FOUND);
-    r.consume();
+    assertDeleteSucceeds();
   }
 
   @Test
@@ -99,11 +72,8 @@
       throws Exception {
     grantOwner();
     blockForcePush();
-    RestResponse r =
-        userSession.delete("/projects/" + project.get()
-            + "/branches/" + branch.getShortName());
-    assertThat(r.getStatusCode()).isEqualTo(HttpStatus.SC_FORBIDDEN);
-    r.consume();
+    setApiUser(user);
+    assertDeleteForbidden();
   }
 
   private void blockForcePush() throws Exception {
@@ -115,4 +85,30 @@
   private void grantOwner() throws Exception {
     allow(Permission.OWNER, REGISTERED_USERS, "refs/*");
   }
+
+  private BranchApi branch() throws Exception {
+    return gApi.projects()
+        .name(branch.getParentKey().get())
+        .branch(branch.get());
+  }
+
+  private void assertDeleteSucceeds() throws Exception {
+    branch().delete();
+    try {
+      branch().get();
+      fail("Expected ResourceNotFoundException");
+    } catch (ResourceNotFoundException expected) {
+      // Expected.
+    }
+  }
+
+  private void assertDeleteForbidden() throws Exception {
+    try {
+      branch().delete();
+      fail("Expected AuthException");
+    } catch (AuthException expected) {
+      // Expected.
+    }
+    branch().get();
+  }
 }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
index f88a2cb..91cb70e 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
@@ -20,6 +20,10 @@
 public interface BranchApi {
   BranchApi create(BranchInput in) throws RestApiException;
 
+  BranchInfo get() throws RestApiException;
+
+  void delete() throws RestApiException;
+
   /**
    * A default implementation which allows source compatibility
    * when adding new methods to the interface.
@@ -29,5 +33,15 @@
     public BranchApi create(BranchInput in) throws RestApiException {
       throw new NotImplementedException();
     }
+
+    @Override
+    public BranchInfo get() throws RestApiException {
+      throw new NotImplementedException();
+    }
+
+    @Override
+    public void delete() throws RestApiException {
+      throw new NotImplementedException();
+    }
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
index 39166c3..0bb395f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/BranchApiImpl.java
@@ -15,10 +15,16 @@
 package com.google.gerrit.server.api.projects;
 
 import com.google.gerrit.extensions.api.projects.BranchApi;
+import com.google.gerrit.extensions.api.projects.BranchInfo;
 import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.project.BranchResource;
+import com.google.gerrit.server.project.BranchesCollection;
 import com.google.gerrit.server.project.CreateBranch;
+import com.google.gerrit.server.project.DeleteBranch;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -29,16 +35,21 @@
     BranchApiImpl create(ProjectResource project, String ref);
   }
 
+  private final BranchesCollection branches;
   private final CreateBranch.Factory createBranchFactory;
+  private final DeleteBranch deleteBranch;
   private final String ref;
   private final ProjectResource project;
 
   @Inject
-  BranchApiImpl(
+  BranchApiImpl(BranchesCollection branches,
       CreateBranch.Factory createBranchFactory,
+      DeleteBranch deleteBranch,
       @Assisted ProjectResource project,
       @Assisted String ref) {
+    this.branches = branches;
     this.createBranchFactory = createBranchFactory;
+    this.deleteBranch = deleteBranch;
     this.project = project;
     this.ref = ref;
   }
@@ -55,4 +66,26 @@
       throw new RestApiException("Cannot create branch", e);
     }
   }
+
+  @Override
+  public BranchInfo get() throws RestApiException {
+    try {
+      return resource().getBranchInfo();
+    } catch (IOException e) {
+      throw new RestApiException("Cannot read branch", e);
+    }
+  }
+
+  @Override
+  public void delete() throws RestApiException {
+    try {
+      deleteBranch.apply(resource(), new DeleteBranch.Input());
+    } catch (OrmException | IOException e) {
+      throw new RestApiException("Cannot delete branch", e);
+    }
+  }
+
+  private BranchResource resource() throws RestApiException, IOException {
+    return branches.parse(project, IdString.fromDecoded(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
index 4aba333..175aeca 100644
--- 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
@@ -46,7 +46,7 @@
   private static final int MAX_LOCK_FAILURE_CALLS = 10;
   private static final long SLEEP_ON_LOCK_FAILURE_MS = 15;
 
-  static class Input {
+  public static class Input {
   }
 
   private final Provider<IdentifiedUser> identifiedUser;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index e62301c..e507de7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -259,6 +259,7 @@
     switch (getCurrentUser().getAccessPath()) {
       case REST_API:
       case JSON_RPC:
+      case UNKNOWN:
         owner = isOwner();
         admin = getCurrentUser().getCapabilities().canAdministrateServer();
         break;