mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-01 12:19:14 +01:00
create endpoint for branch deletion
This commit is contained in:
@@ -47,6 +47,7 @@ import sonia.scm.web.VndMediaType;
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.Valid;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
@@ -57,6 +58,7 @@ import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Optional;
|
||||
|
||||
import static sonia.scm.AlreadyExistsException.alreadyExists;
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
@@ -308,4 +310,50 @@ public class BranchRootResource {
|
||||
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a branch.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "repository" privilege.
|
||||
*
|
||||
* @param branch the name of the branch to delete.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("{branch}")
|
||||
@Operation(summary = "Delete branch", description = "Deletes the given branch.", tags = "Repository")
|
||||
@ApiResponse(responseCode = "204", description = "delete success or nothing to delete")
|
||||
@ApiResponse(responseCode = "400", description = "the default branch cannot be deleted")
|
||||
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||
@ApiResponse(responseCode = "403", description = "not authorized, the current user has no privileges to modify the repository")
|
||||
@ApiResponse(
|
||||
responseCode = "500",
|
||||
description = "internal server error",
|
||||
content = @Content(
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
)
|
||||
)
|
||||
public Response delete(@PathParam("namespace") String namespace,
|
||||
@PathParam("name") String name,
|
||||
@PathParam("branch") String branch) {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
RepositoryPermissions.modify(repositoryService.getRepository()).check();
|
||||
|
||||
Optional<Branch> branchToBeDeleted = repositoryService.getBranchesCommand().getBranches().getBranches().stream()
|
||||
.filter(b -> b.getName().equalsIgnoreCase(branch))
|
||||
.findFirst();
|
||||
|
||||
if (branchToBeDeleted.isPresent()) {
|
||||
if (branchToBeDeleted.get().isDefaultBranch()) {
|
||||
return Response.status(400).build();
|
||||
} else {
|
||||
repositoryService.getBranchCommand().delete(branch);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return Response.serverError().build();
|
||||
}
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.inject.util.Providers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.subject.support.SubjectThreadState;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
@@ -56,11 +56,12 @@ import sonia.scm.web.RestDispatcher;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -68,6 +69,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -271,6 +273,62 @@ public class BranchRootResourceTest extends RepositoryTestBase {
|
||||
verify(branchCommandBuilder, never()).branch(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotDeleteBranchIfNotPermitted() throws IOException, URISyntaxException {
|
||||
doThrow(AuthorizationException.class).when(subject).checkPermission("repository:modify:repoId");
|
||||
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.normalBranch("suspicious", "0")));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(403, response.getStatus());
|
||||
verify(branchCommandBuilder, never()).delete("suspicious");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotDeleteDefaultBranch() throws IOException, URISyntaxException {
|
||||
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.defaultBranch("main", "0")));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/main");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteBranch() throws IOException, URISyntaxException {
|
||||
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches(Branch.normalBranch("suspicious", "0")));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(204, response.getStatus());
|
||||
verify(branchCommandBuilder).delete("suspicious");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAnswer204IfNothingWasDeleted() throws IOException, URISyntaxException {
|
||||
when(branchesCommandBuilder.getBranches()).thenReturn(new Branches());
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.delete("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/branches/suspicious");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(204, response.getStatus());
|
||||
verify(branchCommandBuilder, never()).delete(anyString());
|
||||
}
|
||||
|
||||
private Branch createBranch(String existing_branch) {
|
||||
return Branch.normalBranch(existing_branch, REVISION);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user