mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 15:35:49 +01:00
Make commit message configurable
This commit is contained in:
@@ -10,8 +10,8 @@ import sonia.scm.repository.spi.MergeCommandRequest;
|
|||||||
* the branches could be merged without conflicts ({@link #dryRun()}). To do so, you have to specify the name of
|
* the branches could be merged without conflicts ({@link #dryRun()}). To do so, you have to specify the name of
|
||||||
* the target branch ({@link #setTargetBranch(String)}) and the name of the branch that should be merged
|
* the target branch ({@link #setTargetBranch(String)}) and the name of the branch that should be merged
|
||||||
* ({@link #setBranchToMerge(String)}). Additionally you can specify an author that should be used for the commit
|
* ({@link #setBranchToMerge(String)}). Additionally you can specify an author that should be used for the commit
|
||||||
* ({@link #setAuthor(Person)}) if you are not doing a dry run only. If no author is specified, the logged in user
|
* ({@link #setAuthor(Person)}) and a message template ({@link #setMessageTemplate(String)}) if you are not doing a dry
|
||||||
* will be used instead.
|
* run only. If no author is specified, the logged in user and a default message will be used instead.
|
||||||
*
|
*
|
||||||
* To actually merge <code>feature_branch</code> into <code>integration_branch</code> do this:
|
* To actually merge <code>feature_branch</code> into <code>integration_branch</code> do this:
|
||||||
* <pre><code>
|
* <pre><code>
|
||||||
@@ -91,6 +91,25 @@ public class MergeCommandBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to set a template for the commit message. If no message is set, a default message will be used.
|
||||||
|
*
|
||||||
|
* You can use the placeholder <code>{0}</code> for the branch to be merged and <code>{1}</code> for the target
|
||||||
|
* branch, eg.:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* ...setMessageTemplate("Merge of {0} into {1}")...
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* This is optional and for {@link #executeMerge()} only.
|
||||||
|
*
|
||||||
|
* @return This builder instance.
|
||||||
|
*/
|
||||||
|
public MergeCommandBuilder setMessageTemplate(String messageTemplate) {
|
||||||
|
request.setMessageTemplate(messageTemplate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this to reset the command.
|
* Use this to reset the command.
|
||||||
* @return This builder instance.
|
* @return This builder instance.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public class MergeCommandRequest implements Validateable, Resetable, Serializabl
|
|||||||
private String branchToMerge;
|
private String branchToMerge;
|
||||||
private String targetBranch;
|
private String targetBranch;
|
||||||
private Person author;
|
private Person author;
|
||||||
|
private String messageTemplate;
|
||||||
|
|
||||||
public String getBranchToMerge() {
|
public String getBranchToMerge() {
|
||||||
return branchToMerge;
|
return branchToMerge;
|
||||||
@@ -41,6 +42,14 @@ public class MergeCommandRequest implements Validateable, Resetable, Serializabl
|
|||||||
this.author = author;
|
this.author = author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessageTemplate() {
|
||||||
|
return messageTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageTemplate(String messageTemplate) {
|
||||||
|
this.messageTemplate = messageTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return !Strings.isNullOrEmpty(getBranchToMerge())
|
return !Strings.isNullOrEmpty(getBranchToMerge())
|
||||||
&& !Strings.isNullOrEmpty(getTargetBranch());
|
&& !Strings.isNullOrEmpty(getTargetBranch());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package sonia.scm.repository.spi;
|
package sonia.scm.repository.spi;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
@@ -19,15 +20,16 @@ import sonia.scm.repository.api.MergeDryRunCommandResult;
|
|||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
public class GitMergeCommand extends AbstractGitCommand implements MergeCommand {
|
public class GitMergeCommand extends AbstractGitCommand implements MergeCommand {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(GitMergeCommand.class);
|
private static final Logger logger = LoggerFactory.getLogger(GitMergeCommand.class);
|
||||||
|
|
||||||
private static final String MERGE_COMMIT_MESSAGE_TEMPLATE =
|
private static final String MERGE_COMMIT_MESSAGE_TEMPLATE = String.join("\n",
|
||||||
"Merge of branch %s into %s\n" +
|
"Merge of branch {0} into {1}",
|
||||||
"\n" +
|
"",
|
||||||
"Automatic merge by SCM-Manager.";
|
"Automatic merge by SCM-Manager.");
|
||||||
|
|
||||||
private final GitWorkdirFactory workdirFactory;
|
private final GitWorkdirFactory workdirFactory;
|
||||||
|
|
||||||
@@ -64,11 +66,13 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
|
|||||||
private final String toMerge;
|
private final String toMerge;
|
||||||
private final Person author;
|
private final Person author;
|
||||||
private final Git clone;
|
private final Git clone;
|
||||||
|
private final String messageTemplate;
|
||||||
|
|
||||||
private MergeWorker(Repository clone, MergeCommandRequest request) {
|
private MergeWorker(Repository clone, MergeCommandRequest request) {
|
||||||
this.target = request.getTargetBranch();
|
this.target = request.getTargetBranch();
|
||||||
this.toMerge = request.getBranchToMerge();
|
this.toMerge = request.getBranchToMerge();
|
||||||
this.author = request.getAuthor();
|
this.author = request.getAuthor();
|
||||||
|
this.messageTemplate = request.getMessageTemplate();
|
||||||
this.clone = new Git(clone);
|
this.clone = new Git(clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +115,21 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
|
|||||||
try {
|
try {
|
||||||
clone.commit()
|
clone.commit()
|
||||||
.setAuthor(authorToUse.getName(), authorToUse.getMail())
|
.setAuthor(authorToUse.getName(), authorToUse.getMail())
|
||||||
.setMessage(String.format(MERGE_COMMIT_MESSAGE_TEMPLATE, toMerge, target))
|
.setMessage(MessageFormat.format(determineMessageTemplate(), toMerge, target))
|
||||||
.call();
|
.call();
|
||||||
} catch (GitAPIException e) {
|
} catch (GitAPIException e) {
|
||||||
throw new InternalRepositoryException("could not commit merge between branch " + toMerge + " and " + target, e);
|
throw new InternalRepositoryException("could not commit merge between branch " + toMerge + " and " + target, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String determineMessageTemplate() {
|
||||||
|
if (Strings.isNullOrEmpty(messageTemplate)) {
|
||||||
|
return MERGE_COMMIT_MESSAGE_TEMPLATE;
|
||||||
|
} else {
|
||||||
|
return messageTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Person determineAuthor() {
|
private Person determineAuthor() {
|
||||||
if (author == null) {
|
if (author == null) {
|
||||||
Subject subject = SecurityUtils.getSubject();
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
|||||||
@@ -67,14 +67,36 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
|
|||||||
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
|
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
|
||||||
RevCommit mergeCommit = commits.iterator().next();
|
RevCommit mergeCommit = commits.iterator().next();
|
||||||
PersonIdent mergeAuthor = mergeCommit.getAuthorIdent();
|
PersonIdent mergeAuthor = mergeCommit.getAuthorIdent();
|
||||||
|
String message = mergeCommit.getFullMessage();
|
||||||
assertThat(mergeAuthor.getName()).isEqualTo("Dirk Gently");
|
assertThat(mergeAuthor.getName()).isEqualTo("Dirk Gently");
|
||||||
assertThat(mergeAuthor.getEmailAddress()).isEqualTo("dirk@holistic.det");
|
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.
|
// 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:
|
// If the file is missing (aka not merged correctly) this will throw a MissingObjectException:
|
||||||
byte[] contentOfFileB = repository.open(repository.resolve("9513e9c76e73f3e562fd8e4c909d0607113c77c6")).getBytes();
|
byte[] contentOfFileB = repository.open(repository.resolve("9513e9c76e73f3e562fd8e4c909d0607113c77c6")).getBytes();
|
||||||
assertThat(new String(contentOfFileB)).isEqualTo("b\ncontent from branch\n");
|
assertThat(new String(contentOfFileB)).isEqualTo("b\ncontent from branch\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldUseConfiguredCommitMessageTemplate() throws IOException, GitAPIException {
|
||||||
|
GitMergeCommand command = createCommand();
|
||||||
|
MergeCommandRequest request = new MergeCommandRequest();
|
||||||
|
request.setTargetBranch("master");
|
||||||
|
request.setBranchToMerge("mergeable");
|
||||||
|
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||||
|
request.setMessageTemplate("simple");
|
||||||
|
|
||||||
|
MergeCommandResult mergeCommandResult = command.merge(request);
|
||||||
|
|
||||||
|
assertThat(mergeCommandResult.isSuccess()).isTrue();
|
||||||
|
|
||||||
|
Repository repository = createContext().open();
|
||||||
|
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
|
||||||
|
RevCommit mergeCommit = commits.iterator().next();
|
||||||
|
String message = mergeCommit.getFullMessage();
|
||||||
|
assertThat(message).isEqualTo("simple");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldNotMergeConflictingBranches() {
|
public void shouldNotMergeConflictingBranches() {
|
||||||
GitMergeCommand command = createCommand();
|
GitMergeCommand command = createCommand();
|
||||||
|
|||||||
Reference in New Issue
Block a user