CommitConfig: add support for core.commentChar

Provide  access to the core.commentChar git config, and provide a
utility method to determine an unused comment character if the setting
is "auto".

Bug: 579325
Change-Id: I1ec7e4deffea6ac5929a8538a624d73bb59e4ecc
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
Thomas Wolf 2022-01-22 17:00:32 +01:00
parent a171360292
commit a187d12dd9
3 changed files with 190 additions and 2 deletions

View File

@ -11,7 +11,10 @@
package org.eclipse.jgit.lib;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitConfig.CleanupMode;
@ -169,6 +172,82 @@ public void testCleanScissorsAtEnd() throws Exception {
CommitConfig.cleanText(message, CleanupMode.SCISSORS, '#'));
}
@Test
public void testCommentCharDefault() throws Exception {
CommitConfig cfg = parse("");
assertEquals('#', cfg.getCommentChar());
assertFalse(cfg.isAutoCommentChar());
}
@Test
public void testCommentCharAuto() throws Exception {
CommitConfig cfg = parse("[core]\n\tcommentChar = auto\n");
assertEquals('#', cfg.getCommentChar());
assertTrue(cfg.isAutoCommentChar());
}
@Test
public void testCommentCharEmpty() throws Exception {
CommitConfig cfg = parse("[core]\n\tcommentChar =\n");
assertEquals('#', cfg.getCommentChar());
}
@Test
public void testCommentCharInvalid() throws Exception {
CommitConfig cfg = parse("[core]\n\tcommentChar = \" \"\n");
assertEquals('#', cfg.getCommentChar());
}
@Test
public void testCommentCharNonAscii() throws Exception {
CommitConfig cfg = parse("[core]\n\tcommentChar = ö\n");
assertEquals('#', cfg.getCommentChar());
}
@Test
public void testCommentChar() throws Exception {
CommitConfig cfg = parse("[core]\n\tcommentChar = _\n");
assertEquals('_', cfg.getCommentChar());
}
@Test
public void testDetermineCommentChar() throws Exception {
String text = "A commit message\n\nBody\n";
assertEquals('#', CommitConfig.determineCommentChar(text));
}
@Test
public void testDetermineCommentChar2() throws Exception {
String text = "A commit message\n\nBody\n\n# Conflicts:\n#\tfoo.txt\n";
char ch = CommitConfig.determineCommentChar(text);
assertNotEquals('#', ch);
assertTrue(ch > ' ' && ch < 127);
}
@Test
public void testDetermineCommentChar3() throws Exception {
String text = "A commit message\n\n;Body\n\n# Conflicts:\n#\tfoo.txt\n";
char ch = CommitConfig.determineCommentChar(text);
assertNotEquals('#', ch);
assertNotEquals(';', ch);
assertTrue(ch > ' ' && ch < 127);
}
@Test
public void testDetermineCommentChar4() throws Exception {
String text = "A commit message\n\nBody\n\n # Conflicts:\n\t #\tfoo.txt\n";
char ch = CommitConfig.determineCommentChar(text);
assertNotEquals('#', ch);
assertTrue(ch > ' ' && ch < 127);
}
@Test
public void testDetermineCommentChar5() throws Exception {
String text = "A commit message\n\nBody\n\n#a\n;b\n@c\n!d\n$\n%\n^\n&\n|\n:";
char ch = CommitConfig.determineCommentChar(text);
assertEquals(0, ch);
}
private static CommitConfig parse(String content)
throws ConfigInvalidException {
Config c = new Config();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Julian Ruppel <julian.ruppel@sap.com>
* Copyright (c) 2020, 2022 Julian Ruppel <julian.ruppel@sap.com> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -29,6 +29,7 @@
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
/**
* The standard "commit" configuration parameters.
@ -44,6 +45,9 @@ public class CommitConfig {
private static final String CUT = " ------------------------ >8 ------------------------\n"; //$NON-NLS-1$
private static final char[] COMMENT_CHARS = { '#', ';', '@', '!', '$', '%',
'^', '&', '|', ':' };
/**
* How to clean up commit messages when committing.
*
@ -99,6 +103,10 @@ public boolean matchConfigValue(String in) {
private CleanupMode cleanupMode;
private char commentCharacter = '#';
private boolean autoCommentChar = false;
private CommitConfig(Config rc) {
commitTemplatePath = rc.getString(ConfigConstants.CONFIG_COMMIT_SECTION,
null, ConfigConstants.CONFIG_KEY_COMMIT_TEMPLATE);
@ -106,6 +114,18 @@ private CommitConfig(Config rc) {
null, ConfigConstants.CONFIG_KEY_COMMIT_ENCODING);
cleanupMode = rc.getEnum(ConfigConstants.CONFIG_COMMIT_SECTION, null,
ConfigConstants.CONFIG_KEY_CLEANUP, CleanupMode.DEFAULT);
String comment = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_COMMENT_CHAR);
if (!StringUtils.isEmptyOrNull(comment)) {
if ("auto".equalsIgnoreCase(comment)) { //$NON-NLS-1$
autoCommentChar = true;
} else {
char first = comment.charAt(0);
if (first > ' ' && first < 127) {
commentCharacter = first;
}
}
}
}
/**
@ -130,6 +150,51 @@ public String getCommitEncoding() {
return i18nCommitEncoding;
}
/**
* Retrieves the comment character set by git config
* {@code core.commentChar}.
*
* @return the character to use for comments in commit messages
* @since 6.2
*/
public char getCommentChar() {
return commentCharacter;
}
/**
* Determines the comment character to use for a particular text. If
* {@code core.commentChar} is "auto", tries to determine an unused
* character; if none is found, falls back to '#'. Otherwise returns the
* character given by {@code core.commentChar}.
*
* @param text
* existing text
*
* @return the character to use
* @since 6.2
*/
public char getCommentChar(String text) {
if (isAutoCommentChar()) {
char toUse = determineCommentChar(text);
if (toUse > 0) {
return toUse;
}
return '#';
}
return getCommentChar();
}
/**
* Tells whether the comment character should be determined by choosing a
* character not occurring in a commit message.
*
* @return {@code true} if git config {@code core.commentChar} is "auto"
* @since 6.2
*/
public boolean isAutoCommentChar() {
return autoCommentChar;
}
/**
* Retrieves the {@link CleanupMode} as given by git config
* {@code commit.cleanup}.
@ -315,4 +380,41 @@ private static boolean isComment(String text, char commentChar) {
}
return false;
}
/**
* Determines a comment character by choosing one from a limited set of
* 7-bit ASCII characters that do not occur in the given text at the
* beginning of any line. If none can be determined, {@code (char) 0} is
* returned.
*
* @param text
* to get a comment character for
* @return the comment character, or {@code (char) 0} if none could be
* determined
* @since 6.2
*/
public static char determineCommentChar(String text) {
if (StringUtils.isEmptyOrNull(text)) {
return '#';
}
final boolean[] inUse = new boolean[127];
for (String line : text.split("\n")) { //$NON-NLS-1$
int len = line.length();
for (int i = 0; i < len; i++) {
char ch = line.charAt(i);
if (!Character.isWhitespace(ch)) {
if (ch >= 0 && ch < inUse.length) {
inUse[ch] = true;
}
break;
}
}
}
for (char candidate : COMMENT_CHARS) {
if (!inUse[candidate]) {
return candidate;
}
}
return (char) 0;
}
}

View File

@ -2,7 +2,7 @@
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
* Copyright (C) 2012-2013, Robin Rosenberg
* Copyright (C) 2018-2021, Andre Bossert <andre.bossert@siemens.com> and others
* Copyright (C) 2018-2022, Andre Bossert <andre.bossert@siemens.com> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -202,6 +202,13 @@ public final class ConfigConstants {
*/
public static final String CONFIG_KEY_FORCE_SIGN_ANNOTATED = "forceSignAnnotated";
/**
* The "commentChar" key.
*
* @since 6.2
*/
public static final String CONFIG_KEY_COMMENT_CHAR = "commentChar";
/**
* The "hooksPath" key.
*