Re: i18n.logToUTF8: convert commit log message to UTF-8

2 messages, 1 author, 2016-06-15 · open the first message on its own page

Re: i18n.logToUTF8: convert commit log message to UTF-8

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:46

Hi,

I don't like the convention to add the encoding after a trailing NUL. I'd 
rather have it as an "encoding blabl" header like the author and committer 
headers. I.e.

-- snip --
tree 519fba5ec35f25cbac7f46574f214fb5eb95d2c8
parent 41c7c86ccbcb846cacf48c5e283983fa797cf37b
author Johannes Schindelin [off-list ref] 1166969650 +0100
committer Johannes Schindelin [off-list ref] 1166969650 +0100
encoding latin1

    git-commit-tree: add encoding header if commitEncoding != utf-8
-- snap --

Our log routines all grok these commit objects.

And I would prefer commit-tree to fail if we explicitely ask for 
conversion to UTF-8, but NO_ICONV is set, or reencoding fails for other 
reasons.

Ciao,
Dscho

[PATCH] commit encoding: store it in commit header rather than mucking with NUL

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:46

It also fixes a segmentation fault when iconv does not know the
encoding (defaulting to no conversion).

Signed-off-by: Johannes Schindelin <redacted>
---

	On Sun, 24 Dec 2006, Johannes Schindelin wrote:

	> I don't like the convention to add the encoding after a trailing 
	> NUL. I'd rather have it as an "encoding blabl" header like the 
	> author and committer headers.

	This is a patch implementing that, on top of pu.

 builtin-commit-tree.c |   20 ++++++-------
 commit.c              |   70 ++++++++++++++++++++----------------------------
 2 files changed, 38 insertions(+), 52 deletions(-)
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index 9aff980..33c29f7 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -92,6 +92,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 	char comment[1000];
 	char *buffer;
 	unsigned int size;
+	int encoding_is_utf8;
 
 	setup_ident();
 	git_config(git_default_config);
@@ -117,6 +118,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 			parents++;
 	}
 
+	encoding_is_utf8 = !strcmp(git_commit_encoding, "utf-8");
+
 	init_buffer(&buffer, &size);
 	add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
 
@@ -130,7 +133,11 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 
 	/* Person/date information */
 	add_buffer(&buffer, &size, "author %s\n", git_author_info(1));
-	add_buffer(&buffer, &size, "committer %s\n\n", git_committer_info(1));
+	add_buffer(&buffer, &size, "committer %s\n", git_committer_info(1));
+	if (!encoding_is_utf8)
+		add_buffer(&buffer, &size,
+				"encoding %s\n", git_commit_encoding);
+	add_buffer(&buffer, &size, "\n");
 
 	/* And add the comment */
 	while (fgets(comment, sizeof(comment), stdin) != NULL)
@@ -138,16 +145,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 
 	/* And check the encoding */
 	buffer[size] = '\0';
-	if (strcmp(git_commit_encoding, "utf-8")) {
-		/*
-		 * Add trailing section: this is safe because
-		 * add_buffer always allocates one byte more.
-		 */
-		size++;
-		add_buffer(&buffer, &size,
-			   "encoding %s\n", git_commit_encoding);
-	}
-	else if (!is_utf8(buffer))
+	if (encoding_is_utf8 && !is_utf8(buffer))
 		fprintf(stderr, commit_utf8_warn);
 
 	if (!write_sha1_file(buffer, size, commit_type, commit_sha1)) {
diff --git a/commit.c b/commit.c
index 58c4ecb..3132323 100644
--- a/commit.c
+++ b/commit.c
@@ -598,56 +598,43 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com
 	return offset;
 }
 
-const char *commit_trailer(const struct commit *commit)
+static char *get_header(const struct commit *commit, const char *key)
 {
-	unsigned long size, len;
-	char type[10];
+	int key_len = strlen(key);
+	const char *line = commit->buffer;
 
-	if (sha1_object_info(commit->object.sha1, type, &size))
-		return NULL;
-	len = strlen(commit->buffer);
-	if (len == size)
-		return NULL;
-	return commit->buffer + len + 1;
-}
-
-char *find_commit_trailer(const struct commit *commit, const char *key)
-{
-	const char *trailer = commit_trailer(commit);
-	int keylen = strlen(key);
-	if (!trailer)
-		return NULL;
-	while (*trailer) {
-		const char *eol = strchr(trailer, '\n');
-		if (!eol)
-			eol = trailer + strlen(trailer);
-		if (!strncmp(trailer, key, keylen) && trailer[keylen] == ' ') {
-			int valsz = eol - trailer - keylen;
-			char *val = xmalloc(valsz + 1);
-			memcpy(val, trailer + keylen + 1, valsz);
-			val[valsz] = '\0';
-			if (val[valsz-1] == '\n')
-				val[valsz-1] = '\0';
-			return val;
+	for (;;) {
+		const char *eol = strchr(line, '\n'), *next;
+
+		if (line == eol)
+			return NULL;
+		if (!eol) {
+			eol = line + strlen(line);
+			next = NULL;
+		} else
+			next = eol + 1;
+		if (!strncmp(line, key, key_len) && line[key_len] == ' ') {
+			int len = eol - line - key_len;
+			char *ret = xmalloc(len);
+			memcpy(ret, line + key_len + 1, len - 1);
+			ret[len - 1] = '\0';
+			return ret;
 		}
-		if (!eol)
-			break;
-		trailer = eol + 1;
+		line = next;
 	}
-	return NULL;
 }
 
 static char *logmsg_to_utf8(const struct commit *commit)
 {
-	char *encoding = find_commit_trailer(commit, "encoding");
+	char *encoding = get_header(commit, "encoding");
 	char *out;
 
 	if (!encoding)
-		return commit->buffer;
+		return NULL;
 	out = reencode_string(commit->buffer, "utf-8", encoding);
 	free(encoding);
 	if (!out)
-		return commit->buffer;
+		return NULL;
 	return out;
 }
 
@@ -662,11 +649,12 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
 	int parents_shown = 0;
 	const char *msg = commit->buffer;
 	int plain_non_ascii = 0;
-	int msg_reencoded = 0;
+	char *reencoded = NULL;
 
 	if (strcmp(git_commit_encoding, "utf-8") && i18n_log_to_utf8) {
-		msg = logmsg_to_utf8(commit);
-		msg_reencoded = 1;
+		reencoded = logmsg_to_utf8(commit);
+		if (reencoded)
+			msg = reencoded;
 	}
 
 	if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
@@ -816,8 +804,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
 		buf[offset++] = '\n';
 	buf[offset] = '\0';
 
-	if (msg_reencoded)
-		free((char*)msg);
+	if (reencoded)
+		free(reencoded);
 	return offset;
 }
 
-- 
1.4.4.3.g0001f-dirty
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help