mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 00:15:44 +01:00
Add parameter for parent of new branch
This commit is contained in:
@@ -44,17 +44,20 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public final class BranchCommandBuilder {
|
public final class BranchCommandBuilder {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BranchCommandBuilder.class);
|
|
||||||
|
|
||||||
public BranchCommandBuilder(BranchCommand command) {
|
public BranchCommandBuilder(BranchCommand command) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Branch branch(String name) throws IOException {
|
public BranchCommandBuilder from(String parentBranch) {
|
||||||
LOG.debug("branch {}", name);
|
request.setParentBranch(parentBranch);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
return command.branch(name);
|
public Branch branch(String name) throws IOException {
|
||||||
|
request.setNewBranch(name);
|
||||||
|
return command.branch(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BranchCommand command;
|
private BranchCommand command;
|
||||||
|
private BranchRequest request = new BranchRequest();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package sonia.scm.repository.api;
|
||||||
|
|
||||||
|
public class BranchRequest {
|
||||||
|
private String parentBranch;
|
||||||
|
private String newBranch;
|
||||||
|
|
||||||
|
public String getParentBranch() {
|
||||||
|
return parentBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentBranch(String parentBranch) {
|
||||||
|
this.parentBranch = parentBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewBranch() {
|
||||||
|
return newBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewBranch(String newBranch) {
|
||||||
|
this.newBranch = newBranch;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,6 +46,7 @@ import sonia.scm.repository.PreProcessorUtil;
|
|||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.spi.HookChangesetProvider;
|
import sonia.scm.repository.spi.HookChangesetProvider;
|
||||||
import sonia.scm.repository.spi.HookChangesetRequest;
|
import sonia.scm.repository.spi.HookChangesetRequest;
|
||||||
|
import sonia.scm.repository.spi.HookChangesetResponse;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
@@ -115,8 +116,8 @@ public final class HookChangesetBuilder
|
|||||||
*/
|
*/
|
||||||
public Iterable<Changeset> getChangesets()
|
public Iterable<Changeset> getChangesets()
|
||||||
{
|
{
|
||||||
Iterable<Changeset> changesets =
|
HookChangesetResponse hookChangesetResponse = provider.handleRequest(request);
|
||||||
provider.handleRequest(request).getChangesets();
|
Iterable<Changeset> changesets = hookChangesetResponse.getChangesets();
|
||||||
|
|
||||||
if (!disablePreProcessors)
|
if (!disablePreProcessors)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ package sonia.scm.repository.spi;
|
|||||||
|
|
||||||
|
|
||||||
import sonia.scm.repository.Branch;
|
import sonia.scm.repository.Branch;
|
||||||
|
import sonia.scm.repository.api.BranchRequest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -41,5 +42,5 @@ import java.io.IOException;
|
|||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public interface BranchCommand {
|
public interface BranchCommand {
|
||||||
Branch branch(String name) throws IOException;
|
Branch branch(BranchRequest name) throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class VndMediaType {
|
|||||||
public static final String TAG = PREFIX + "tag" + SUFFIX;
|
public static final String TAG = PREFIX + "tag" + SUFFIX;
|
||||||
public static final String TAG_COLLECTION = PREFIX + "tagCollection" + SUFFIX;
|
public static final String TAG_COLLECTION = PREFIX + "tagCollection" + SUFFIX;
|
||||||
public static final String BRANCH = PREFIX + "branch" + SUFFIX;
|
public static final String BRANCH = PREFIX + "branch" + SUFFIX;
|
||||||
|
public static final String BRANCH_REQUEST = PREFIX + "branchRequest" + SUFFIX;
|
||||||
public static final String DIFF = PLAIN_TEXT_PREFIX + "diff" + PLAIN_TEXT_SUFFIX;
|
public static final String DIFF = PLAIN_TEXT_PREFIX + "diff" + PLAIN_TEXT_SUFFIX;
|
||||||
public static final String USER_COLLECTION = PREFIX + "userCollection" + SUFFIX;
|
public static final String USER_COLLECTION = PREFIX + "userCollection" + SUFFIX;
|
||||||
public static final String GROUP_COLLECTION = PREFIX + "groupCollection" + SUFFIX;
|
public static final String GROUP_COLLECTION = PREFIX + "groupCollection" + SUFFIX;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import sonia.scm.repository.GitUtil;
|
|||||||
import sonia.scm.repository.GitWorkdirFactory;
|
import sonia.scm.repository.GitWorkdirFactory;
|
||||||
import sonia.scm.repository.InternalRepositoryException;
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
|
import sonia.scm.repository.api.BranchRequest;
|
||||||
import sonia.scm.repository.util.WorkingCopy;
|
import sonia.scm.repository.util.WorkingCopy;
|
||||||
|
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
@@ -56,19 +57,22 @@ public class GitBranchCommand extends AbstractGitCommand implements BranchComman
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Branch branch(String name) {
|
public Branch branch(BranchRequest request) {
|
||||||
try (WorkingCopy<org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context)) {
|
try (WorkingCopy<org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context)) {
|
||||||
Git clone = new Git(workingCopy.get());
|
Git clone = new Git(workingCopy.get());
|
||||||
Ref ref = clone.branchCreate().setName(name).call();
|
if (request.getParentBranch() != null) {
|
||||||
Iterable<PushResult> call = clone.push().add(name).call();
|
clone.checkout().setName(request.getParentBranch());
|
||||||
|
}
|
||||||
|
Ref ref = clone.branchCreate().setName(request.getNewBranch()).call();
|
||||||
|
Iterable<PushResult> call = clone.push().add(request.getNewBranch()).call();
|
||||||
StreamSupport.stream(call.spliterator(), false)
|
StreamSupport.stream(call.spliterator(), false)
|
||||||
.flatMap(pushResult -> pushResult.getRemoteUpdates().stream())
|
.flatMap(pushResult -> pushResult.getRemoteUpdates().stream())
|
||||||
.filter(remoteRefUpdate -> remoteRefUpdate.getStatus() != RemoteRefUpdate.Status.OK)
|
.filter(remoteRefUpdate -> remoteRefUpdate.getStatus() != RemoteRefUpdate.Status.OK)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.ifPresent(this::handlePushError);
|
.ifPresent(this::handlePushError);
|
||||||
return Branch.normalBranch(name, GitUtil.getId(ref.getObjectId()));
|
return Branch.normalBranch(request.getNewBranch(), GitUtil.getId(ref.getObjectId()));
|
||||||
} catch (GitAPIException ex) {
|
} catch (GitAPIException ex) {
|
||||||
throw new InternalRepositoryException(repository, "could not create branch " + name, ex);
|
throw new InternalRepositoryException(repository, "could not create branch " + request.getNewBranch(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.assertj.core.api.Assertions;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import sonia.scm.repository.Branch;
|
import sonia.scm.repository.Branch;
|
||||||
|
import sonia.scm.repository.api.BranchRequest;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -20,7 +21,10 @@ public class GitBranchCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
||||||
|
|
||||||
new GitBranchCommand(context, repository, new SimpleGitWorkdirFactory()).branch("new_branch");
|
BranchRequest branchRequest = new BranchRequest();
|
||||||
|
branchRequest.setNewBranch("new_branch");
|
||||||
|
|
||||||
|
new GitBranchCommand(context, repository, new SimpleGitWorkdirFactory()).branch(branchRequest);
|
||||||
|
|
||||||
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,16 @@ package sonia.scm.repository.spi;
|
|||||||
|
|
||||||
import com.aragost.javahg.Changeset;
|
import com.aragost.javahg.Changeset;
|
||||||
import com.aragost.javahg.commands.CommitCommand;
|
import com.aragost.javahg.commands.CommitCommand;
|
||||||
|
import com.aragost.javahg.commands.UpdateCommand;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.repository.Branch;
|
import sonia.scm.repository.Branch;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
|
import sonia.scm.repository.api.BranchRequest;
|
||||||
import sonia.scm.repository.util.WorkingCopy;
|
import sonia.scm.repository.util.WorkingCopy;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mercurial implementation of the {@link BranchCommand}.
|
* Mercurial implementation of the {@link BranchCommand}.
|
||||||
* Note that this creates an empty commit to "persist" the new branch.
|
* Note that this creates an empty commit to "persist" the new branch.
|
||||||
@@ -54,21 +58,24 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Branch branch(String name) {
|
public Branch branch(BranchRequest request) throws IOException {
|
||||||
try (WorkingCopy<RepositoryCloseableWrapper> workingCopy = workdirFactory.createWorkingCopy(getContext())) {
|
try (WorkingCopy<RepositoryCloseableWrapper> workingCopy = workdirFactory.createWorkingCopy(getContext())) {
|
||||||
com.aragost.javahg.Repository repository = workingCopy.get().get();
|
com.aragost.javahg.Repository repository = workingCopy.get().get();
|
||||||
com.aragost.javahg.commands.BranchCommand.on(repository).set(name);
|
if (request.getParentBranch() != null) {
|
||||||
|
UpdateCommand.on(repository).rev(request.getParentBranch()).execute();
|
||||||
|
}
|
||||||
|
com.aragost.javahg.commands.BranchCommand.on(repository).set(request.getNewBranch());
|
||||||
|
|
||||||
Changeset emptyChangeset = CommitCommand
|
Changeset emptyChangeset = CommitCommand
|
||||||
.on(repository)
|
.on(repository)
|
||||||
.user("SCM-Manager")
|
.user("SCM-Manager")
|
||||||
.message("Create new branch " + name)
|
.message("Create new branch " + request.getNewBranch())
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
LOG.debug("Created new branch '{}' in repository {} with changeset {}",
|
LOG.debug("Created new branch '{}' in repository {} with changeset {}",
|
||||||
name, getRepository().getNamespaceAndName(), emptyChangeset.getNode());
|
request.getNewBranch(), getRepository().getNamespaceAndName(), emptyChangeset.getNode());
|
||||||
|
|
||||||
return Branch.normalBranch(name, emptyChangeset.getNode());
|
return Branch.normalBranch(request.getNewBranch(), emptyChangeset.getNode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ import org.assertj.core.api.Assertions;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import sonia.scm.repository.Branch;
|
import sonia.scm.repository.Branch;
|
||||||
import sonia.scm.repository.HgTestUtil;
|
import sonia.scm.repository.HgTestUtil;
|
||||||
|
import sonia.scm.repository.api.BranchRequest;
|
||||||
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HgBranchCommandTest extends AbstractHgCommandTestBase {
|
public class HgBranchCommandTest extends AbstractHgCommandTestBase {
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateBranch() {
|
public void shouldCreateBranch() throws IOException {
|
||||||
Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
||||||
|
|
||||||
HgRepositoryEnvironmentBuilder hgRepositoryEnvironmentBuilder =
|
HgRepositoryEnvironmentBuilder hgRepositoryEnvironmentBuilder =
|
||||||
@@ -19,7 +21,10 @@ public class HgBranchCommandTest extends AbstractHgCommandTestBase {
|
|||||||
|
|
||||||
SimpleHgWorkdirFactory workdirFactory = new SimpleHgWorkdirFactory(Providers.of(hgRepositoryEnvironmentBuilder), pc -> {});
|
SimpleHgWorkdirFactory workdirFactory = new SimpleHgWorkdirFactory(Providers.of(hgRepositoryEnvironmentBuilder), pc -> {});
|
||||||
|
|
||||||
new HgBranchCommand(cmdContext, repository, workdirFactory).branch("new_branch");
|
BranchRequest branchRequest = new BranchRequest();
|
||||||
|
branchRequest.setNewBranch("new_branch");
|
||||||
|
|
||||||
|
new HgBranchCommand(cmdContext, repository, workdirFactory).branch(branchRequest);
|
||||||
|
|
||||||
Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
import static sonia.scm.api.v2.resources.BranchDto.VALID_BRANCH_NAMES;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class BranchRequestDto {
|
||||||
|
|
||||||
|
@NotEmpty @Length(min = 1, max=100) @Pattern(regexp = VALID_BRANCH_NAMES)
|
||||||
|
private String name;
|
||||||
|
private String parent;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
||||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
||||||
@@ -13,6 +14,7 @@ import sonia.scm.repository.ChangesetPagingResult;
|
|||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.RepositoryPermissions;
|
import sonia.scm.repository.RepositoryPermissions;
|
||||||
|
import sonia.scm.repository.api.BranchCommandBuilder;
|
||||||
import sonia.scm.repository.api.CommandNotSupportedException;
|
import sonia.scm.repository.api.CommandNotSupportedException;
|
||||||
import sonia.scm.repository.api.RepositoryService;
|
import sonia.scm.repository.api.RepositoryService;
|
||||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||||
@@ -134,12 +136,12 @@ public class BranchRootResource {
|
|||||||
*
|
*
|
||||||
* @param namespace the namespace of the repository
|
* @param namespace the namespace of the repository
|
||||||
* @param name the name of the repository
|
* @param name the name of the repository
|
||||||
* @param branchName The branch to be created.
|
* @param branchRequest the request giving the name of the new branch and an optional parent branch
|
||||||
* @return A response with the link to the new branch (if created successfully).
|
* @return A response with the link to the new branch (if created successfully).
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("")
|
@Path("")
|
||||||
@Consumes(VndMediaType.BRANCH)
|
@Consumes(VndMediaType.BRANCH_REQUEST)
|
||||||
@StatusCodes({
|
@StatusCodes({
|
||||||
@ResponseCode(code = 201, condition = "create success"),
|
@ResponseCode(code = 201, condition = "create success"),
|
||||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||||
@@ -151,16 +153,24 @@ public class BranchRootResource {
|
|||||||
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created branch"))
|
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created branch"))
|
||||||
public Response create(@PathParam("namespace") String namespace,
|
public Response create(@PathParam("namespace") String namespace,
|
||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@Valid BranchDto branchToCreate) throws IOException {
|
@Valid BranchRequestDto branchRequest) throws IOException {
|
||||||
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
|
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
|
||||||
String branchName = branchToCreate.getName();
|
String branchName = branchRequest.getName();
|
||||||
|
String parentName = branchRequest.getParent();
|
||||||
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
||||||
if (branchExists(branchName, repositoryService)) {
|
if (branchExists(branchName, repositoryService)) {
|
||||||
throw alreadyExists(entity(Branch.class, branchName).in(Repository.class, namespace + "/" + name));
|
throw alreadyExists(entity(Branch.class, branchName).in(Repository.class, namespace + "/" + name));
|
||||||
}
|
}
|
||||||
Repository repository = repositoryService.getRepository();
|
Repository repository = repositoryService.getRepository();
|
||||||
RepositoryPermissions.push(repository).check();
|
RepositoryPermissions.push(repository).check();
|
||||||
Branch newBranch = repositoryService.getBranchCommand().branch(branchName);
|
BranchCommandBuilder branchCommand = repositoryService.getBranchCommand();
|
||||||
|
if (!Strings.isNullOrEmpty(parentName)) {
|
||||||
|
if (!branchExists(parentName, repositoryService)) {
|
||||||
|
throw notFound(entity(Branch.class, parentName).in(Repository.class, namespace + "/" + name));
|
||||||
|
}
|
||||||
|
branchCommand.from(parentName);
|
||||||
|
}
|
||||||
|
Branch newBranch = branchCommand.branch(branchName);
|
||||||
return Response.created(URI.create(resourceLinks.branch().self(namespaceAndName, newBranch.getName()))).build();
|
return Response.created(URI.create(resourceLinks.branch().self(namespaceAndName, newBranch.getName()))).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user