summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-log.c19
-rw-r--r--commit.c61
-rw-r--r--revision.h1
3 files changed, 76 insertions, 5 deletions
diff --git a/builtin-log.c b/builtin-log.c
index 8df3c1394a..b7e47cb5fe 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -20,6 +20,8 @@ void add_head(struct rev_info *revs);
static void cmd_log_init(int argc, const char **argv, const char *prefix,
struct rev_info *rev)
{
+ int i;
+
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
rev->verbose_header = 1;
@@ -27,8 +29,21 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
argc = setup_revisions(argc, argv, rev, "HEAD");
if (rev->diffopt.pickaxe || rev->diffopt.filter)
rev->always_show_header = 0;
- if (argc > 1)
- die("unrecognized argument: %s", argv[1]);
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (!strncmp(arg, "--encoding=", 11)) {
+ arg += 11;
+ if (MAX_ENCODING_LENGTH <= strlen(arg))
+ die(" Value of output encoding '%s' too long",
+ arg);
+ if (strcmp(arg, "none"))
+ strcpy(git_commit_encoding, arg);
+ else
+ git_commit_encoding[0] = 0;
+ }
+ else
+ die("unrecognized argument: %s", arg);
+ }
}
static int cmd_log_walk(struct rev_info *rev)
diff --git a/commit.c b/commit.c
index 289ef65eb1..df4bc0775a 100644
--- a/commit.c
+++ b/commit.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "tag.h"
#include "commit.h"
+#include "utf8.h"
int save_commit_buffer = 1;
@@ -563,10 +564,53 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com
return offset;
}
-unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
- unsigned long len, char *buf, unsigned long space,
+static char *get_header(const struct commit *commit, const char *key)
+{
+ int key_len = strlen(key);
+ const char *line = commit->buffer;
+
+ 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;
+ }
+ line = next;
+ }
+}
+
+static char *logmsg_reencode(const struct commit *commit)
+{
+ char *encoding = get_header(commit, "encoding");
+ char *out;
+
+ if (!encoding || !strcmp(encoding, git_commit_encoding))
+ return NULL;
+ out = reencode_string(commit->buffer, git_commit_encoding, encoding);
+ free(encoding);
+ if (!out)
+ return NULL;
+ return out;
+}
+
+unsigned long pretty_print_commit(enum cmit_fmt fmt,
+ const struct commit *commit,
+ unsigned long len,
+ char *buf, unsigned long space,
int abbrev, const char *subject,
- const char *after_subject, int relative_date)
+ const char *after_subject,
+ int relative_date)
{
int hdr = 1, body = 0;
unsigned long offset = 0;
@@ -574,6 +618,15 @@ 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;
+ char *reencoded = NULL;
+
+ if (*git_commit_encoding) {
+ reencoded = logmsg_reencode(commit);
+ if (reencoded) {
+ msg = reencoded;
+ len = strlen(msg);
+ }
+ }
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
indent = 0;
@@ -721,6 +774,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
if (fmt == CMIT_FMT_EMAIL && !body)
buf[offset++] = '\n';
buf[offset] = '\0';
+
+ free(reencoded);
return offset;
}
diff --git a/revision.h b/revision.h
index ec991e5c57..8f7907d7ab 100644
--- a/revision.h
+++ b/revision.h
@@ -72,6 +72,7 @@ struct rev_info {
const char *ref_message_id;
const char *add_signoff;
const char *extra_headers;
+ const char *log_reencode;
/* Filter by commit log message */
struct grep_opt *grep_filter;