From 0e333002dbf43db093d6187f3926950c144d340b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 10 Dec 2018 11:43:27 +0100 Subject: [PATCH] Create local branch for target during merge --- .../scm/repository/spi/GitMergeCommand.java | 24 ++++++++++++---- .../repository/spi/GitMergeCommandTest.java | 28 +++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) 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 1d0e8f768b..072fdff514 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 @@ -97,16 +97,30 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand private void checkOutTargetBranch() throws IOException { try { - ObjectId targetRevision = resolveRevision(target); - clone.checkout().setName(targetRevision.getName()).call(); + clone.checkout().setName(target).call(); } catch (RefNotFoundException e) { - logger.debug("could not checkout target branch {} for merge", target, e); - throw notFound(entity("revision", target).in(context.getRepository())); + logger.trace("could not checkout target branch {} for merge directly; trying to create local branch", target, e); + checkOutTargetAsNewLocalBranch(); } catch (GitAPIException e) { throw new InternalRepositoryException(context.getRepository(), "could not checkout target branch for merge: " + target, e); } } + private void checkOutTargetAsNewLocalBranch() throws IOException { + try { + ObjectId targetRevision = resolveRevision(target); + if (targetRevision == null) { + throw notFound(entity("revision", target).in(context.getRepository())); + } + clone.checkout().setStartPoint(targetRevision.getName()).setName(target).setCreateBranch(true).call(); + } catch (RefNotFoundException e) { + logger.debug("could not checkout target branch {} for merge as local branch", target, e); + throw notFound(entity("revision", target).in(context.getRepository())); + } catch (GitAPIException e) { + throw new InternalRepositoryException(context.getRepository(), "could not checkout target branch for merge as local branch: " + target, e); + } + } + private MergeResult doMergeInClone() throws IOException { MergeResult result; try { @@ -164,7 +178,7 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand try { clone.push().call(); } catch (GitAPIException e) { - throw new InternalRepositoryException(context.getRepository(), "could not push merged branch " + toMerge + " to origin", e); + throw new InternalRepositoryException(context.getRepository(), "could not push merged branch " + target + " to origin", e); } logger.debug("pushed merged branch {}", target); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java index 88942e455f..7e50b48b9a 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java @@ -126,8 +126,6 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { Repository repository = createContext().open(); ObjectId firstMergeCommit = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call().iterator().next().getId(); -// Transport.register(new ScmTransportProtocol(of(hookEventFacade), of(gitRepositoryHandler))); - MergeCommandResult secondMergeCommandResult = command.merge(request); assertThat(secondMergeCommandResult.isSuccess()).isTrue(); @@ -196,6 +194,32 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { assertThat(mergeAuthor.getEmailAddress()).isEqualTo("dirk@holistic.det"); } + @Test + public void shouldMergeIntoNotDefaultBranch() throws IOException, GitAPIException { + GitMergeCommand command = createCommand(); + MergeCommandRequest request = new MergeCommandRequest(); + request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det")); + request.setTargetBranch("mergeable"); + request.setBranchToMerge("master"); + + MergeCommandResult mergeCommandResult = command.merge(request); + + Repository repository = createContext().open(); + assertThat(mergeCommandResult.isSuccess()).isTrue(); + + Iterable commits = new Git(repository).log().add(repository.resolve("mergeable")).setMaxCount(1).call(); + RevCommit mergeCommit = commits.iterator().next(); + PersonIdent mergeAuthor = mergeCommit.getAuthorIdent(); + String message = mergeCommit.getFullMessage(); + assertThat(mergeAuthor.getName()).isEqualTo("Dirk Gently"); + assertThat(mergeAuthor.getEmailAddress()).isEqualTo("dirk@holistic.det"); + assertThat(message).contains("master", "mergeable"); + // We expect the merge result of file b.txt here by looking up the sha hash of its content. + // If the file is missing (aka not merged correctly) this will throw a MissingObjectException: + byte[] contentOfFileB = repository.open(repository.resolve("9513e9c76e73f3e562fd8e4c909d0607113c77c6")).getBytes(); + assertThat(new String(contentOfFileB)).isEqualTo("b\ncontent from branch\n"); + } + private GitMergeCommand createCommand() { return new GitMergeCommand(createContext(), repository, new SimpleGitWorkdirFactory()); }