mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 09:25:43 +01:00
Merge with 2.0.0-m3
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MergeResultDto {
|
||||
private Collection<String> filesWithConflict;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import sonia.scm.repository.api.MergeCommandResult;
|
||||
|
||||
@Mapper
|
||||
public interface MergeResultToDtoMapper {
|
||||
MergeResultDto map(MergeCommandResult result);
|
||||
}
|
||||
@@ -68,6 +68,10 @@ public final class BranchCommandBuilder {
|
||||
return command.branch(request);
|
||||
}
|
||||
|
||||
public void delete(String branchName) {
|
||||
command.deleteOrClose(branchName);
|
||||
}
|
||||
|
||||
private BranchCommand command;
|
||||
private BranchRequest request = new BranchRequest();
|
||||
}
|
||||
|
||||
@@ -41,4 +41,6 @@ import sonia.scm.repository.api.BranchRequest;
|
||||
*/
|
||||
public interface BranchCommand {
|
||||
Branch branch(BranchRequest name);
|
||||
|
||||
void deleteOrClose(String branchName);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.ExceptionWithContext;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
public class CannotDeleteDefaultBranchException extends ExceptionWithContext {
|
||||
|
||||
public static final String CODE = "78RhWxTIw1";
|
||||
|
||||
public CannotDeleteDefaultBranchException(Repository repository, String branchName) {
|
||||
super(ContextEntry.ContextBuilder.entity("Branch", branchName).in(repository).build(), "default branch cannot be deleted");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return CODE;
|
||||
}
|
||||
}
|
||||
@@ -33,51 +33,120 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.transport.PushResult;
|
||||
import org.eclipse.jgit.transport.RemoteRefUpdate;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.repository.Branch;
|
||||
import sonia.scm.repository.GitUtil;
|
||||
import sonia.scm.repository.GitWorkdirFactory;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
|
||||
import sonia.scm.repository.PreReceiveRepositoryHookEvent;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryHookEvent;
|
||||
import sonia.scm.repository.RepositoryHookType;
|
||||
import sonia.scm.repository.api.BranchRequest;
|
||||
import sonia.scm.repository.util.WorkingCopy;
|
||||
import sonia.scm.repository.api.HookBranchProvider;
|
||||
import sonia.scm.repository.api.HookContext;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.repository.api.HookFeature;
|
||||
|
||||
import java.util.stream.StreamSupport;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singleton;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
|
||||
public class GitBranchCommand extends AbstractGitCommand implements BranchCommand {
|
||||
|
||||
private final GitWorkdirFactory workdirFactory;
|
||||
private final HookContextFactory hookContextFactory;
|
||||
private final ScmEventBus eventBus;
|
||||
|
||||
GitBranchCommand(GitContext context, Repository repository, GitWorkdirFactory workdirFactory) {
|
||||
GitBranchCommand(GitContext context, Repository repository, HookContextFactory hookContextFactory, ScmEventBus eventBus) {
|
||||
super(context, repository);
|
||||
this.workdirFactory = workdirFactory;
|
||||
this.hookContextFactory = hookContextFactory;
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch branch(BranchRequest request) {
|
||||
try (WorkingCopy<org.eclipse.jgit.lib.Repository, org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context, request.getParentBranch())) {
|
||||
Git clone = new Git(workingCopy.getWorkingRepository());
|
||||
Ref ref = clone.branchCreate().setName(request.getNewBranch()).call();
|
||||
Iterable<PushResult> call = clone.push().add(request.getNewBranch()).call();
|
||||
StreamSupport.stream(call.spliterator(), false)
|
||||
.flatMap(pushResult -> pushResult.getRemoteUpdates().stream())
|
||||
.filter(remoteRefUpdate -> remoteRefUpdate.getStatus() != RemoteRefUpdate.Status.OK)
|
||||
.findFirst()
|
||||
.ifPresent(r -> this.handlePushError(r, request, context.getRepository()));
|
||||
try (Git git = new Git(context.open())) {
|
||||
RepositoryHookEvent hookEvent = createBranchHookEvent(BranchHookContextProvider.createHookEvent(request.getNewBranch()));
|
||||
eventBus.post(new PreReceiveRepositoryHookEvent(hookEvent));
|
||||
Ref ref = git.branchCreate().setStartPoint(request.getParentBranch()).setName(request.getNewBranch()).call();
|
||||
eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent));
|
||||
return Branch.normalBranch(request.getNewBranch(), GitUtil.getId(ref.getObjectId()));
|
||||
} catch (GitAPIException ex) {
|
||||
} catch (GitAPIException | IOException ex) {
|
||||
throw new InternalRepositoryException(repository, "could not create branch " + request.getNewBranch(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePushError(RemoteRefUpdate remoteRefUpdate, BranchRequest request, Repository repository) {
|
||||
if (remoteRefUpdate.getStatus() != RemoteRefUpdate.Status.OK) {
|
||||
// TODO handle failed remote update
|
||||
throw new IntegrateChangesFromWorkdirException(repository,
|
||||
String.format("Could not push new branch '%s' into central repository", request.getNewBranch()));
|
||||
@Override
|
||||
public void deleteOrClose(String branchName) {
|
||||
try (Git gitRepo = new Git(context.open())) {
|
||||
RepositoryHookEvent hookEvent = createBranchHookEvent(BranchHookContextProvider.deleteHookEvent(branchName));
|
||||
eventBus.post(new PreReceiveRepositoryHookEvent(hookEvent));
|
||||
gitRepo
|
||||
.branchDelete()
|
||||
.setBranchNames(branchName)
|
||||
.setForce(true)
|
||||
.call();
|
||||
eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent));
|
||||
} catch (CannotDeleteCurrentBranchException e) {
|
||||
throw new CannotDeleteDefaultBranchException(context.getRepository(), branchName);
|
||||
} catch (GitAPIException | IOException ex) {
|
||||
throw new InternalRepositoryException(entity(context.getRepository()), String.format("Could not delete branch: %s", branchName));
|
||||
}
|
||||
}
|
||||
|
||||
private RepositoryHookEvent createBranchHookEvent(BranchHookContextProvider hookEvent) {
|
||||
HookContext context = hookContextFactory.createContext(hookEvent, this.context.getRepository());
|
||||
return new RepositoryHookEvent(context, this.context.getRepository(), RepositoryHookType.PRE_RECEIVE);
|
||||
}
|
||||
|
||||
private static class BranchHookContextProvider extends HookContextProvider {
|
||||
private final List<String> newBranches;
|
||||
private final List<String> deletedBranches;
|
||||
|
||||
private BranchHookContextProvider(List<String> newBranches, List<String> deletedBranches) {
|
||||
this.newBranches = newBranches;
|
||||
this.deletedBranches = deletedBranches;
|
||||
}
|
||||
|
||||
static BranchHookContextProvider createHookEvent(String newBranch) {
|
||||
return new BranchHookContextProvider(singletonList(newBranch), emptyList());
|
||||
}
|
||||
|
||||
static BranchHookContextProvider deleteHookEvent(String deletedBranch) {
|
||||
return new BranchHookContextProvider(emptyList(), singletonList(deletedBranch));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<HookFeature> getSupportedFeatures() {
|
||||
return singleton(HookFeature.BRANCH_PROVIDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HookBranchProvider getBranchProvider() {
|
||||
return new HookBranchProvider() {
|
||||
@Override
|
||||
public List<String> getCreatedOrModified() {
|
||||
return newBranches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDeletedOrClosed() {
|
||||
return deletedBranches;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public HookChangesetProvider getChangesetProvider() {
|
||||
return r -> new HookChangesetResponse(emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,12 @@ package sonia.scm.repository.spi;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.repository.Feature;
|
||||
import sonia.scm.repository.GitRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.Command;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.web.lfs.LfsBlobStoreFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -64,6 +66,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
Command.DIFF_RESULT,
|
||||
Command.LOG,
|
||||
Command.TAGS,
|
||||
Command.BRANCH,
|
||||
Command.BRANCHES,
|
||||
Command.INCOMING,
|
||||
Command.OUTGOING,
|
||||
@@ -77,10 +80,12 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
public GitRepositoryServiceProvider(GitRepositoryHandler handler, Repository repository, GitRepositoryConfigStoreProvider storeProvider, LfsBlobStoreFactory lfsBlobStoreFactory) {
|
||||
public GitRepositoryServiceProvider(GitRepositoryHandler handler, Repository repository, GitRepositoryConfigStoreProvider storeProvider, LfsBlobStoreFactory lfsBlobStoreFactory, HookContextFactory hookContextFactory, ScmEventBus eventBus) {
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
this.lfsBlobStoreFactory = lfsBlobStoreFactory;
|
||||
this.hookContextFactory = hookContextFactory;
|
||||
this.eventBus = eventBus;
|
||||
this.context = new GitContext(handler.getDirectory(repository.getId()), repository, storeProvider);
|
||||
}
|
||||
|
||||
@@ -133,7 +138,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
@Override
|
||||
public BranchCommand getBranchCommand()
|
||||
{
|
||||
return new GitBranchCommand(context, repository, handler.getWorkdirFactory());
|
||||
return new GitBranchCommand(context, repository, hookContextFactory, eventBus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,4 +297,8 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
private final Repository repository;
|
||||
|
||||
private final LfsBlobStoreFactory lfsBlobStoreFactory;
|
||||
|
||||
private final HookContextFactory hookContextFactory;
|
||||
|
||||
private final ScmEventBus eventBus;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@ package sonia.scm.repository.spi;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.GitRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.web.lfs.LfsBlobStoreFactory;
|
||||
|
||||
/**
|
||||
@@ -51,12 +53,16 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver {
|
||||
private final GitRepositoryHandler handler;
|
||||
private final GitRepositoryConfigStoreProvider storeProvider;
|
||||
private final LfsBlobStoreFactory lfsBlobStoreFactory;
|
||||
private final HookContextFactory hookContextFactory;
|
||||
private final ScmEventBus eventBus;
|
||||
|
||||
@Inject
|
||||
public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitRepositoryConfigStoreProvider storeProvider, LfsBlobStoreFactory lfsBlobStoreFactory) {
|
||||
public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitRepositoryConfigStoreProvider storeProvider, LfsBlobStoreFactory lfsBlobStoreFactory, HookContextFactory hookContextFactory, ScmEventBus eventBus) {
|
||||
this.handler = handler;
|
||||
this.storeProvider = storeProvider;
|
||||
this.lfsBlobStoreFactory = lfsBlobStoreFactory;
|
||||
this.hookContextFactory = hookContextFactory;
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,7 +70,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver {
|
||||
GitRepositoryServiceProvider provider = null;
|
||||
|
||||
if (GitRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) {
|
||||
provider = new GitRepositoryServiceProvider(handler, repository, storeProvider, lfsBlobStoreFactory);
|
||||
provider = new GitRepositoryServiceProvider(handler, repository, storeProvider, lfsBlobStoreFactory, hookContextFactory, eventBus);
|
||||
}
|
||||
|
||||
return provider;
|
||||
|
||||
@@ -1,20 +1,37 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.repository.Branch;
|
||||
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
|
||||
import sonia.scm.repository.PreReceiveRepositoryHookEvent;
|
||||
import sonia.scm.repository.api.BranchRequest;
|
||||
import sonia.scm.repository.util.WorkdirProvider;
|
||||
import sonia.scm.repository.api.HookContext;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GitBranchCommandTest extends AbstractGitCommandTestBase {
|
||||
|
||||
@Rule
|
||||
public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule();
|
||||
@Mock
|
||||
private HookContextFactory hookContextFactory;
|
||||
@Mock
|
||||
private ScmEventBus eventBus;
|
||||
|
||||
@Test
|
||||
public void shouldCreateBranchWithDefinedSourceBranch() throws IOException {
|
||||
@@ -26,10 +43,10 @@ public class GitBranchCommandTest extends AbstractGitCommandTestBase {
|
||||
branchRequest.setParentBranch(source.getName());
|
||||
branchRequest.setNewBranch("new_branch");
|
||||
|
||||
new GitBranchCommand(context, repository, new SimpleGitWorkdirFactory(new WorkdirProvider())).branch(branchRequest);
|
||||
createCommand().branch(branchRequest);
|
||||
|
||||
Branch newBranch = findBranch(context, "new_branch");
|
||||
Assertions.assertThat(newBranch.getRevision()).isEqualTo(source.getRevision());
|
||||
assertThat(newBranch.getRevision()).isEqualTo(source.getRevision());
|
||||
}
|
||||
|
||||
private Branch findBranch(GitContext context, String name) throws IOException {
|
||||
@@ -41,17 +58,79 @@ public class GitBranchCommandTest extends AbstractGitCommandTestBase {
|
||||
public void shouldCreateBranch() throws IOException {
|
||||
GitContext context = createContext();
|
||||
|
||||
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
||||
assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isEmpty();
|
||||
|
||||
BranchRequest branchRequest = new BranchRequest();
|
||||
branchRequest.setNewBranch("new_branch");
|
||||
|
||||
new GitBranchCommand(context, repository, new SimpleGitWorkdirFactory(new WorkdirProvider())).branch(branchRequest);
|
||||
createCommand().branch(branchRequest);
|
||||
|
||||
Assertions.assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
||||
assertThat(readBranches(context)).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDeleteBranch() throws IOException {
|
||||
GitContext context = createContext();
|
||||
String branchToBeDeleted = "squash";
|
||||
createCommand().deleteOrClose(branchToBeDeleted);
|
||||
assertThat(readBranches(context)).filteredOn(b -> b.getName().equals(branchToBeDeleted)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenDeletingDefaultBranch() {
|
||||
String branchToBeDeleted = "master";
|
||||
assertThrows(CannotDeleteDefaultBranchException.class, () -> createCommand().deleteOrClose(branchToBeDeleted));
|
||||
}
|
||||
|
||||
private GitBranchCommand createCommand() {
|
||||
return new GitBranchCommand(createContext(), repository, hookContextFactory, eventBus);
|
||||
}
|
||||
|
||||
private List<Branch> readBranches(GitContext context) throws IOException {
|
||||
return new GitBranchesCommand(context, repository).getBranches();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPostCreateEvents() {
|
||||
ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
|
||||
doNothing().when(eventBus).post(captor.capture());
|
||||
when(hookContextFactory.createContext(any(), any())).thenAnswer(this::createMockedContext);
|
||||
|
||||
BranchRequest branchRequest = new BranchRequest();
|
||||
branchRequest.setParentBranch("mergeable");
|
||||
branchRequest.setNewBranch("new_branch");
|
||||
|
||||
createCommand().branch(branchRequest);
|
||||
|
||||
List<Object> events = captor.getAllValues();
|
||||
assertThat(events.get(0)).isInstanceOf(PreReceiveRepositoryHookEvent.class);
|
||||
assertThat(events.get(1)).isInstanceOf(PostReceiveRepositoryHookEvent.class);
|
||||
|
||||
PreReceiveRepositoryHookEvent event = (PreReceiveRepositoryHookEvent) events.get(0);
|
||||
assertThat(event.getContext().getBranchProvider().getCreatedOrModified()).containsExactly("new_branch");
|
||||
assertThat(event.getContext().getBranchProvider().getDeletedOrClosed()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPostDeleteEvents() {
|
||||
ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
|
||||
doNothing().when(eventBus).post(captor.capture());
|
||||
when(hookContextFactory.createContext(any(), any())).thenAnswer(this::createMockedContext);
|
||||
|
||||
createCommand().deleteOrClose("squash");
|
||||
|
||||
List<Object> events = captor.getAllValues();
|
||||
assertThat(events.get(0)).isInstanceOf(PreReceiveRepositoryHookEvent.class);
|
||||
assertThat(events.get(1)).isInstanceOf(PostReceiveRepositoryHookEvent.class);
|
||||
|
||||
PreReceiveRepositoryHookEvent event = (PreReceiveRepositoryHookEvent) events.get(0);
|
||||
assertThat(event.getContext().getBranchProvider().getDeletedOrClosed()).containsExactly("squash");
|
||||
assertThat(event.getContext().getBranchProvider().getCreatedOrModified()).isEmpty();
|
||||
}
|
||||
|
||||
private HookContext createMockedContext(InvocationOnMock invocation) {
|
||||
HookContext mock = mock(HookContext.class);
|
||||
when(mock.getBranchProvider()).thenReturn(((HookContextProvider) invocation.getArgument(0)).getBranchProvider());
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,9 @@ import com.aragost.javahg.commands.PullCommand;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.repository.Branch;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.BranchRequest;
|
||||
import sonia.scm.repository.util.WorkingCopy;
|
||||
@@ -67,23 +69,46 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand {
|
||||
LOG.debug("Created new branch '{}' in repository {} with changeset {}",
|
||||
request.getNewBranch(), getRepository().getNamespaceAndName(), emptyChangeset.getNode());
|
||||
|
||||
pullNewBranchIntoCentralRepository(request, workingCopy);
|
||||
pullChangesIntoCentralRepository(workingCopy, request.getNewBranch());
|
||||
|
||||
return Branch.normalBranch(request.getNewBranch(), emptyChangeset.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteOrClose(String branchName) {
|
||||
try (WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy = workdirFactory.createWorkingCopy(getContext(), branchName)) {
|
||||
User currentUser = SecurityUtils.getSubject().getPrincipals().oneByType(User.class);
|
||||
|
||||
LOG.debug("Closing branch '{}' in repository {}", branchName, getRepository().getNamespaceAndName());
|
||||
|
||||
com.aragost.javahg.commands.CommitCommand
|
||||
.on(workingCopy.getWorkingRepository())
|
||||
.user(getFormattedUser(currentUser))
|
||||
.message(String.format("Close branch: %s", branchName))
|
||||
.closeBranch()
|
||||
.execute();
|
||||
pullChangesIntoCentralRepository(workingCopy, branchName);
|
||||
} catch (Exception ex) {
|
||||
throw new InternalRepositoryException(ContextEntry.ContextBuilder.entity(getContext().getScmRepository()), String.format("Could not close branch: %s", branchName));
|
||||
}
|
||||
}
|
||||
|
||||
private String getFormattedUser(User currentUser) {
|
||||
return String.format("%s <%s>", currentUser.getDisplayName(), currentUser.getMail());
|
||||
}
|
||||
|
||||
private Changeset createNewBranchWithEmptyCommit(BranchRequest request, com.aragost.javahg.Repository repository) {
|
||||
com.aragost.javahg.commands.BranchCommand.on(repository).set(request.getNewBranch());
|
||||
User currentUser = SecurityUtils.getSubject().getPrincipals().oneByType(User.class);
|
||||
return CommitCommand
|
||||
.on(repository)
|
||||
.user(String.format("%s <%s>", currentUser.getDisplayName(), currentUser.getMail()))
|
||||
.user(getFormattedUser(currentUser))
|
||||
.message("Create new branch " + request.getNewBranch())
|
||||
.execute();
|
||||
}
|
||||
|
||||
private void pullNewBranchIntoCentralRepository(BranchRequest request, WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy) {
|
||||
private void pullChangesIntoCentralRepository(WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy, String branch) {
|
||||
try {
|
||||
PullCommand pullCommand = PullCommand.on(workingCopy.getCentralRepository());
|
||||
workdirFactory.configure(pullCommand);
|
||||
@@ -91,7 +116,7 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand {
|
||||
} catch (Exception e) {
|
||||
// TODO handle failed update
|
||||
throw new IntegrateChangesFromWorkdirException(getRepository(),
|
||||
String.format("Could not pull new branch '%s' into central repository", request.getNewBranch()),
|
||||
String.format("Could not pull changes '%s' into central repository", branch),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider
|
||||
Command.DIFF,
|
||||
Command.LOG,
|
||||
Command.TAGS,
|
||||
Command.BRANCH,
|
||||
Command.BRANCHES,
|
||||
Command.INCOMING,
|
||||
Command.OUTGOING,
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.repository.Branch;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.api.BranchRequest;
|
||||
import sonia.scm.repository.util.WorkdirProvider;
|
||||
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
||||
@@ -13,6 +14,7 @@ import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class HgBranchCommandTest extends AbstractHgCommandTestBase {
|
||||
|
||||
@@ -54,6 +56,22 @@ public class HgBranchCommandTest extends AbstractHgCommandTestBase {
|
||||
assertThat(cmdContext.open().changeset(newBranch.getRevision()).getParent1().getBranch()).isEqualTo("test-branch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCloseBranch() {
|
||||
String branchToBeClosed = "test-branch";
|
||||
|
||||
new HgBranchCommand(cmdContext, repository, workdirFactory).deleteOrClose(branchToBeClosed);
|
||||
assertThat(readBranches()).filteredOn(b -> b.getName().equals(branchToBeClosed)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowInternalRepositoryException() {
|
||||
String branchToBeClosed = "default";
|
||||
|
||||
new HgBranchCommand(cmdContext, repository, workdirFactory).deleteOrClose(branchToBeClosed);
|
||||
assertThrows(InternalRepositoryException.class, () -> new HgBranchCommand(cmdContext, repository, workdirFactory).deleteOrClose(branchToBeClosed));
|
||||
}
|
||||
|
||||
private List<Branch> readBranches() {
|
||||
return new HgBranchesCommand(cmdContext, repository).getBranches();
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@ public class MapperModule extends AbstractModule {
|
||||
bind(ScmViolationExceptionToErrorDtoMapper.class).to(Mappers.getMapper(ScmViolationExceptionToErrorDtoMapper.class).getClass());
|
||||
bind(ExceptionWithContextToErrorDtoMapper.class).to(Mappers.getMapper(ExceptionWithContextToErrorDtoMapper.class).getClass());
|
||||
|
||||
bind(MergeResultToDtoMapper.class).to(Mappers.getMapper(MergeResultToDtoMapper.class).getClass());
|
||||
|
||||
// no mapstruct required
|
||||
bind(MeDtoFactory.class);
|
||||
bind(UIPluginDtoMapper.class);
|
||||
|
||||
@@ -187,6 +187,10 @@
|
||||
"6eRhF9gU41": {
|
||||
"displayName": "Nicht unterstützte Merge-Strategie",
|
||||
"description": "Die gewählte Merge-Strategie wird von dem Repository nicht unterstützt."
|
||||
},
|
||||
"78RhWxTIw1": {
|
||||
"displayName": "Der Default-Branch kann nicht gelöscht werden",
|
||||
"description": "Der Default-Branch kann nicht gelöscht werden. Bitte wählen Sie zuerst einen neuen Default-Branch."
|
||||
}
|
||||
},
|
||||
"namespaceStrategies": {
|
||||
|
||||
@@ -187,6 +187,10 @@
|
||||
"6eRhF9gU41": {
|
||||
"displayName": "Merge strategy not supported",
|
||||
"description": "The selected merge strategy is not supported by the repository."
|
||||
},
|
||||
"78RhWxTIw1": {
|
||||
"displayName": "Default branch cannot be deleted",
|
||||
"description": "The default branch of a repository cannot be deleted. Please select another default branch first."
|
||||
}
|
||||
},
|
||||
"namespaceStrategies": {
|
||||
|
||||
Reference in New Issue
Block a user