From 3dea971e10853b53723e05967466ed2df32beeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Sun, 6 Oct 2019 16:29:50 +0200 Subject: [PATCH 1/5] Checkout target branch while cloning repository This will prevent the checkout of a wrong initial branch and therefore safe some unnecessary io --- .../repository/util/SimpleWorkdirFactory.java | 6 +- .../scm/repository/util/WorkdirFactory.java | 2 +- .../util/SimpleWorkdirFactoryTest.java | 19 ++++- .../repository/spi/AbstractGitCommand.java | 4 +- .../scm/repository/spi/GitBranchCommand.java | 5 +- .../scm/repository/spi/GitMergeCommand.java | 7 +- .../scm/repository/spi/GitModifyCommand.java | 10 +-- .../spi/SimpleGitWorkdirFactory.java | 23 ++++- .../repository/spi/GitModifyCommandTest.java | 4 +- ...ModifyCommand_withEmptyRepositoryTest.java | 84 +++++++++++++++++++ .../spi/SimpleGitWorkdirFactoryTest.java | 28 +++++-- .../scm/repository/spi/HgBranchCommand.java | 18 +--- .../spi/SimpleHgWorkdirFactory.java | 15 +++- .../repository/spi/HgBranchCommandTest.java | 36 ++++++-- 14 files changed, 188 insertions(+), 73 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommand_withEmptyRepositoryTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/util/SimpleWorkdirFactory.java b/scm-core/src/main/java/sonia/scm/repository/util/SimpleWorkdirFactory.java index 7236e0c3fe..a1073e24f2 100644 --- a/scm-core/src/main/java/sonia/scm/repository/util/SimpleWorkdirFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/util/SimpleWorkdirFactory.java @@ -19,10 +19,10 @@ public abstract class SimpleWorkdirFactory implements WorkdirFactory } @Override - public WorkingCopy createWorkingCopy(C context) { + public WorkingCopy createWorkingCopy(C context, String initialBranch) { try { File directory = workdirProvider.createNewWorkdir(); - ParentAndClone parentAndClone = cloneRepository(context, directory); + ParentAndClone parentAndClone = cloneRepository(context, directory, initialBranch); return new WorkingCopy<>(parentAndClone.getClone(), parentAndClone.getParent(), this::close, directory); } catch (IOException e) { throw new InternalRepositoryException(getScmRepository(context), "could not clone repository in temporary directory", e); @@ -35,7 +35,7 @@ public abstract class SimpleWorkdirFactory implements WorkdirFactory // We do allow implementations to throw arbitrary exceptions here, so that we can handle them in close protected abstract void closeRepository(R repository) throws Exception; - protected abstract ParentAndClone cloneRepository(C context, File target) throws IOException; + protected abstract ParentAndClone cloneRepository(C context, File target, String initialBranch) throws IOException; private void close(R repository) { try { diff --git a/scm-core/src/main/java/sonia/scm/repository/util/WorkdirFactory.java b/scm-core/src/main/java/sonia/scm/repository/util/WorkdirFactory.java index 1b67c7f1eb..bddf03adaa 100644 --- a/scm-core/src/main/java/sonia/scm/repository/util/WorkdirFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/util/WorkdirFactory.java @@ -1,5 +1,5 @@ package sonia.scm.repository.util; public interface WorkdirFactory { - WorkingCopy createWorkingCopy(C context); + WorkingCopy createWorkingCopy(C context, String initialBranch); } diff --git a/scm-core/src/test/java/sonia/scm/repository/util/SimpleWorkdirFactoryTest.java b/scm-core/src/test/java/sonia/scm/repository/util/SimpleWorkdirFactoryTest.java index 31aa11c604..4a1a1a4179 100644 --- a/scm-core/src/test/java/sonia/scm/repository/util/SimpleWorkdirFactoryTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/util/SimpleWorkdirFactoryTest.java @@ -26,6 +26,8 @@ public class SimpleWorkdirFactoryTest { public TemporaryFolder temporaryFolder = new TemporaryFolder(); private SimpleWorkdirFactory simpleWorkdirFactory; + private String initialBranchForLastCloneCall; + @Before public void initFactory() throws IOException { WorkdirProvider workdirProvider = new WorkdirProvider(temporaryFolder.newFolder()); @@ -41,7 +43,8 @@ public class SimpleWorkdirFactoryTest { } @Override - protected ParentAndClone cloneRepository(Context context, File target) { + protected ParentAndClone cloneRepository(Context context, File target, String initialBranch) { + initialBranchForLastCloneCall = initialBranch; return new ParentAndClone<>(parent, clone); } }; @@ -50,7 +53,7 @@ public class SimpleWorkdirFactoryTest { @Test public void shouldCreateParentAndClone() { Context context = new Context(); - try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context)) { + try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) { assertThat(workingCopy.getCentralRepository()).isSameAs(parent); assertThat(workingCopy.getWorkingRepository()).isSameAs(clone); } @@ -59,7 +62,7 @@ public class SimpleWorkdirFactoryTest { @Test public void shouldCloseParent() throws IOException { Context context = new Context(); - try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context)) {} + try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {} verify(parent).close(); } @@ -67,10 +70,18 @@ public class SimpleWorkdirFactoryTest { @Test public void shouldCloseClone() throws IOException { Context context = new Context(); - try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context)) {} + try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {} verify(clone).close(); } + @Test + public void shouldPropagateInitialBranch() { + Context context = new Context(); + try (WorkingCopy workingCopy = simpleWorkdirFactory.createWorkingCopy(context, "some")) { + assertThat(initialBranchForLastCloneCall).isEqualTo("some"); + } + } + private static class Context {} } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index bea110766b..bc4d939e91 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -140,8 +140,8 @@ class AbstractGitCommand } } - > R inClone(Function workerSupplier, GitWorkdirFactory workdirFactory) { - try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context)) { + > R inClone(Function workerSupplier, GitWorkdirFactory workdirFactory, String initialBranch) { + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context, initialBranch)) { Repository repository = workingCopy.getWorkingRepository(); logger.debug("cloned repository to folder {}", repository.getWorkTree()); return workerSupplier.apply(new Git(repository)).run(); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchCommand.java index 9796182b04..e8675068b9 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchCommand.java @@ -58,11 +58,8 @@ public class GitBranchCommand extends AbstractGitCommand implements BranchComman @Override public Branch branch(BranchRequest request) { - try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context)) { + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context, request.getParentBranch())) { Git clone = new Git(workingCopy.getWorkingRepository()); - if (request.getParentBranch() != null) { - clone.checkout().setName("origin/" + request.getParentBranch()).call(); - } Ref ref = clone.branchCreate().setName(request.getNewBranch()).call(); Iterable call = clone.push().add(request.getNewBranch()).call(); StreamSupport.stream(call.spliterator(), false) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java index b4a7954b02..5643c858b5 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java @@ -38,7 +38,7 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand @Override public MergeCommandResult merge(MergeCommandRequest request) { - return inClone(clone -> new MergeWorker(clone, request), workdirFactory); + return inClone(clone -> new MergeWorker(clone, request), workdirFactory, request.getTargetBranch()); } @Override @@ -72,7 +72,6 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand @Override MergeCommandResult run() throws IOException { - checkOutTargetBranch(); MergeResult result = doMergeInClone(); if (result.getMergeStatus().isSuccessful()) { doCommit(); @@ -83,10 +82,6 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand } } - private void checkOutTargetBranch() throws IOException { - checkOutBranch(target); - } - private MergeResult doMergeInClone() throws IOException { MergeResult result; try { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java index 0f7c9296a7..3a8ec03a08 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java @@ -3,8 +3,6 @@ package sonia.scm.repository.spi; import org.apache.commons.lang.StringUtils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; import sonia.scm.BadRequestException; import sonia.scm.ConcurrentModificationException; @@ -25,7 +23,6 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static sonia.scm.AlreadyExistsException.alreadyExists; import static sonia.scm.ContextEntry.ContextBuilder.entity; import static sonia.scm.NotFoundException.notFound; -import static sonia.scm.ScmConstraintViolationException.Builder.doThrow; public class GitModifyCommand extends AbstractGitCommand implements ModifyCommand { @@ -38,7 +35,7 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman @Override public String execute(ModifyCommandRequest request) { - return inClone(clone -> new ModifyWorker(clone, request), workdirFactory); + return inClone(clone -> new ModifyWorker(clone, request), workdirFactory, request.getBranch()); } private class ModifyWorker extends GitCloneWorker implements Worker { @@ -54,11 +51,6 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman @Override String run() throws IOException { - if (!StringUtils.isEmpty(request.getBranch())) { - checkOutBranch(request.getBranch()); - } - Ref head = getClone().getRepository().exactRef(Constants.HEAD); - doThrow().violation("branch has to be a valid branch, no revision", "branch", request.getBranch()).when(head == null || !head.isSymbolic()); getClone().getRepository().getFullBranch(); if (!StringUtils.isEmpty(request.getExpectedRevision())) { if (!request.getExpectedRevision().equals(getCurrentRevision().getName())) { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/SimpleGitWorkdirFactory.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/SimpleGitWorkdirFactory.java index 9edcf0c0ea..a0fda7cd3b 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/SimpleGitWorkdirFactory.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/SimpleGitWorkdirFactory.java @@ -2,6 +2,8 @@ package sonia.scm.repository.spi; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.ScmTransportProtocol; import sonia.scm.repository.GitWorkdirFactory; @@ -11,6 +13,10 @@ import sonia.scm.repository.util.WorkdirProvider; import javax.inject.Inject; import java.io.File; +import java.io.IOException; + +import static sonia.scm.ContextEntry.ContextBuilder.entity; +import static sonia.scm.NotFoundException.notFound; public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory implements GitWorkdirFactory { @@ -20,14 +26,23 @@ public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory cloneRepository(GitContext context, File target) { + public ParentAndClone cloneRepository(GitContext context, File target, String initialBranch) { try { - return new ParentAndClone<>(null, Git.cloneRepository() + Repository clone = Git.cloneRepository() .setURI(createScmTransportProtocolUri(context.getDirectory())) .setDirectory(target) + .setBranch(initialBranch) .call() - .getRepository()); - } catch (GitAPIException e) { + .getRepository(); + + Ref head = clone.exactRef(Constants.HEAD); + + if (head == null || !head.isSymbolic() || (initialBranch != null && !head.getTarget().getName().endsWith(initialBranch))) { + throw notFound(entity("Branch", initialBranch).in(context.getRepository())); + } + + return new ParentAndClone<>(null, clone); + } catch (GitAPIException | IOException e) { throw new InternalRepositoryException(context.getRepository(), "could not clone working copy of repository", e); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommandTest.java index 4fbf7eaf02..501134026d 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommandTest.java @@ -263,8 +263,8 @@ public class GitModifyCommandTest extends AbstractGitCommandTestBase { command.execute(request); } - @Test(expected = ScmConstraintViolationException.class) - public void shouldFailWithConstraintViolationIfBranchIsNoBranch() throws IOException { + @Test(expected = NotFoundException.class) + public void shouldFailWithNotFoundExceptionIfBranchIsNoBranch() throws IOException { File newFile = Files.write(temporaryFolder.newFile().toPath(), "irrelevant\n".getBytes()).toFile(); GitModifyCommand command = createCommand(); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommand_withEmptyRepositoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommand_withEmptyRepositoryTest.java new file mode 100644 index 0000000000..ff409e470d --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModifyCommand_withEmptyRepositoryTest.java @@ -0,0 +1,84 @@ +package sonia.scm.repository.spi; + +import com.github.sdorra.shiro.ShiroRule; +import com.github.sdorra.shiro.SubjectAware; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import sonia.scm.ScmConstraintViolationException; +import sonia.scm.repository.Person; +import sonia.scm.repository.util.WorkdirProvider; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.assertj.core.api.Assertions.assertThat; + +@SubjectAware(configuration = "classpath:sonia/scm/configuration/shiro.ini", username = "admin", password = "secret") +public class GitModifyCommand_withEmptyRepositoryTest extends AbstractGitCommandTestBase { + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Rule + public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule(); + @Rule + public ShiroRule shiro = new ShiroRule(); + + @Test + public void shouldCreateNewFileInEmptyRepository() throws IOException, GitAPIException { + File newFile = Files.write(temporaryFolder.newFile().toPath(), "new content".getBytes()).toFile(); + + GitModifyCommand command = createCommand(); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.setCommitMessage("test commit"); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("new_file", newFile, false)); + request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det")); + + command.execute(request); + + TreeAssertions assertions = canonicalTreeParser -> assertThat(canonicalTreeParser.findFile("new_file")).isTrue(); + + assertInTree(assertions); + } + + @Override + protected String getZippedRepositoryResource() { + return "sonia/scm/repository/spi/scm-git-empty-repo.zip"; + } + + private void assertInTree(TreeAssertions assertions) throws IOException, GitAPIException { + try (Git git = new Git(createContext().open())) { + RevCommit lastCommit = getLastCommit(git); + try (RevWalk walk = new RevWalk(git.getRepository())) { + RevCommit commit = walk.parseCommit(lastCommit); + ObjectId treeId = commit.getTree().getId(); + try (ObjectReader reader = git.getRepository().newObjectReader()) { + assertions.checkAssertions(new CanonicalTreeParser(null, reader, treeId)); + } + } + } + } + + private RevCommit getLastCommit(Git git) throws GitAPIException { + return git.log().setMaxCount(1).call().iterator().next(); + } + + private GitModifyCommand createCommand() { + return new GitModifyCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())); + } + + @FunctionalInterface + private interface TreeAssertions { + void checkAssertions(CanonicalTreeParser treeParser) throws CorruptObjectException; + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/SimpleGitWorkdirFactoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/SimpleGitWorkdirFactoryTest.java index 1b3c730ef1..cb2d434f1e 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/SimpleGitWorkdirFactoryTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/SimpleGitWorkdirFactoryTest.java @@ -20,8 +20,6 @@ import java.io.IOException; import static com.google.inject.util.Providers.of; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase { @@ -43,11 +41,11 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase { } @Test - public void emptyPoolShouldCreateNewWorkdir() throws IOException { + public void emptyPoolShouldCreateNewWorkdir() { SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider); File masterRepo = createRepositoryDirectory(); - try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext())) { + try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext(), null)) { assertThat(workingCopy.getDirectory()) .exists() @@ -61,25 +59,37 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase { } @Test - public void cloneFromPoolShouldNotBeReused() throws IOException { + public void shouldCheckoutInitialBranch() { + SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider); + + try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext(), "test-branch")) { + assertThat(new File(workingCopy.getWorkingRepository().getWorkTree(), "a.txt")) + .exists() + .isFile() + .hasContent("a and b"); + } + } + + @Test + public void cloneFromPoolShouldNotBeReused() { SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider); File firstDirectory; - try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext())) { + try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext(), null)) { firstDirectory = workingCopy.getDirectory(); } - try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext())) { + try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext(), null)) { File secondDirectory = workingCopy.getDirectory(); assertThat(secondDirectory).isNotEqualTo(firstDirectory); } } @Test - public void cloneFromPoolShouldBeDeletedOnClose() throws IOException { + public void cloneFromPoolShouldBeDeletedOnClose() { SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider); File directory; - try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext())) { + try (WorkingCopy workingCopy = factory.createWorkingCopy(createContext(), null)) { directory = workingCopy.getWorkingRepository().getWorkTree(); } assertThat(directory).doesNotExist(); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchCommand.java index 750bfc1332..5e9e01c9d8 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchCommand.java @@ -33,19 +33,15 @@ package sonia.scm.repository.spi; import com.aragost.javahg.Changeset; import com.aragost.javahg.commands.CommitCommand; import com.aragost.javahg.commands.PullCommand; -import com.aragost.javahg.commands.UpdateCommand; import org.apache.shiro.SecurityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; import sonia.scm.user.User; -import java.io.IOException; - /** * Mercurial implementation of the {@link BranchCommand}. * Note that this creates an empty commit to "persist" the new branch. @@ -63,11 +59,9 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand { @Override public Branch branch(BranchRequest request) { - try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(getContext())) { + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(getContext(), request.getParentBranch())) { com.aragost.javahg.Repository repository = workingCopy.getWorkingRepository(); - checkoutParentBranchIfSpecified(request, repository); - Changeset emptyChangeset = createNewBranchWithEmptyCommit(request, repository); LOG.debug("Created new branch '{}' in repository {} with changeset {}", @@ -79,16 +73,6 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand { } } - private void checkoutParentBranchIfSpecified(BranchRequest request, com.aragost.javahg.Repository repository) { - if (request.getParentBranch() != null) { - try { - UpdateCommand.on(repository).rev(request.getParentBranch()).execute(); - } catch (IOException e) { - throw new InternalRepositoryException(getRepository(), "Could not check out parent branch " + request.getParentBranch(), e); - } - } - } - 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); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/SimpleHgWorkdirFactory.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/SimpleHgWorkdirFactory.java index b9194145e6..619f8b0892 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/SimpleHgWorkdirFactory.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/SimpleHgWorkdirFactory.java @@ -1,8 +1,10 @@ package sonia.scm.repository.spi; +import com.aragost.javahg.BaseRepository; import com.aragost.javahg.Repository; import com.aragost.javahg.commands.CloneCommand; import com.aragost.javahg.commands.PullCommand; +import com.aragost.javahg.commands.flags.CloneCommandFlags; import sonia.scm.repository.util.SimpleWorkdirFactory; import sonia.scm.repository.util.WorkdirProvider; import sonia.scm.web.HgRepositoryEnvironmentBuilder; @@ -24,12 +26,19 @@ public class SimpleHgWorkdirFactory extends SimpleWorkdirFactory cloneRepository(HgCommandContext context, File target) throws IOException { + public ParentAndClone cloneRepository(HgCommandContext context, File target, String initialBranch) throws IOException { BiConsumer> repositoryMapBiConsumer = (repository, environment) -> hgRepositoryEnvironmentBuilder.get().buildFor(repository, null, environment); Repository centralRepository = context.openWithSpecialEnvironment(repositoryMapBiConsumer); - CloneCommand.on(centralRepository).execute(target.getAbsolutePath()); - return new ParentAndClone<>(centralRepository, Repository.open(target)); + CloneCommand cloneCommand = CloneCommandFlags.on(centralRepository); + if (initialBranch != null) { + cloneCommand.updaterev(initialBranch); + } + cloneCommand.execute(target.getAbsolutePath()); + + BaseRepository clone = Repository.open(target); + + return new ParentAndClone<>(centralRepository, clone); } @Override diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchCommandTest.java index 7976af8b3b..882dab05d0 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchCommandTest.java @@ -2,7 +2,7 @@ package sonia.scm.repository.spi; import com.aragost.javahg.commands.PullCommand; import com.google.inject.util.Providers; -import org.assertj.core.api.Assertions; +import org.junit.Before; import org.junit.Test; import sonia.scm.repository.Branch; import sonia.scm.repository.HgTestUtil; @@ -10,30 +10,48 @@ import sonia.scm.repository.api.BranchRequest; import sonia.scm.repository.util.WorkdirProvider; import sonia.scm.web.HgRepositoryEnvironmentBuilder; -import java.io.IOException; import java.util.List; -public class HgBranchCommandTest extends AbstractHgCommandTestBase { - @Test - public void shouldCreateBranch() throws IOException { - Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isEmpty(); +import static org.assertj.core.api.Assertions.assertThat; +public class HgBranchCommandTest extends AbstractHgCommandTestBase { + + private SimpleHgWorkdirFactory workdirFactory; + + @Before + public void initWorkdirFactory() { HgRepositoryEnvironmentBuilder hgRepositoryEnvironmentBuilder = new HgRepositoryEnvironmentBuilder(handler, HgTestUtil.createHookManager()); - SimpleHgWorkdirFactory workdirFactory = new SimpleHgWorkdirFactory(Providers.of(hgRepositoryEnvironmentBuilder), new WorkdirProvider()) { + workdirFactory = new SimpleHgWorkdirFactory(Providers.of(hgRepositoryEnvironmentBuilder), new WorkdirProvider()) { @Override public void configure(PullCommand pullCommand) { // we do not want to configure http hooks in this unit test } }; + } + @Test + public void shouldCreateBranch() { BranchRequest branchRequest = new BranchRequest(); branchRequest.setNewBranch("new_branch"); - new HgBranchCommand(cmdContext, repository, workdirFactory).branch(branchRequest); + Branch newBranch = new HgBranchCommand(cmdContext, repository, workdirFactory).branch(branchRequest); - Assertions.assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty(); + assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty(); + assertThat(cmdContext.open().changeset(newBranch.getRevision()).getParent1().getBranch()).isEqualTo("default"); + } + + @Test + public void shouldCreateBranchOnSpecificParent() { + BranchRequest branchRequest = new BranchRequest(); + branchRequest.setParentBranch("test-branch"); + branchRequest.setNewBranch("new_branch"); + + Branch newBranch = new HgBranchCommand(cmdContext, repository, workdirFactory).branch(branchRequest); + + assertThat(readBranches()).filteredOn(b -> b.getName().equals("new_branch")).isNotEmpty(); + assertThat(cmdContext.open().changeset(newBranch.getRevision()).getParent1().getBranch()).isEqualTo("test-branch"); } private List readBranches() { From 3ac267c2abb5f9448b6cf8e957b3c175d4d3cb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Sun, 6 Oct 2019 16:57:45 +0200 Subject: [PATCH 2/5] Add missing test repository --- .../scm/repository/spi/scm-git-empty-repo.zip | Bin 0 -> 12739 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-empty-repo.zip diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-empty-repo.zip b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-empty-repo.zip new file mode 100644 index 0000000000000000000000000000000000000000..fdd0af44830136318a9e66ae8b1bb7c1cdb8c2cd GIT binary patch literal 12739 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 E0m8DQ!vFvP literal 0 HcmV?d00001 From 4a4ea1e20df0ad74d3d9d542f107e88e040a7bd2 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 7 Oct 2019 08:47:02 +0000 Subject: [PATCH 3/5] Close branch feature/clone_with_preselected_branch From 51818d8ffb1f934b4cf4c7961fdc5ce3cbbaa991 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Mon, 7 Oct 2019 14:15:27 +0200 Subject: [PATCH 4/5] add label and helpText option for MemberNameTagGroup component --- .../packages/ui-components/src/forms/MemberNameTagGroup.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js b/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js index 20a078619d..89d98e4a7d 100644 --- a/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js +++ b/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js @@ -7,6 +7,8 @@ import TagGroup from "./TagGroup"; type Props = { members: string[], memberListChanged: (string[]) => void, + label?: string, + helpText?: string, t: string => string }; From fbf05a60d825b8da286910b78763fbdb23d2ea11 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Mon, 7 Oct 2019 14:22:49 +0200 Subject: [PATCH 5/5] use new label and helpText prop when given --- .../packages/ui-components/src/forms/MemberNameTagGroup.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js b/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js index 89d98e4a7d..73a5f8c723 100644 --- a/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js +++ b/scm-ui-components/packages/ui-components/src/forms/MemberNameTagGroup.js @@ -14,15 +14,15 @@ type Props = { class MemberNameTagGroup extends React.Component { render() { - const { members, t } = this.props; + const { members, label, helpText, t } = this.props; const membersExtended = members.map(id => { return { id, displayName: id, mail: "" }; }); return ( );