773
interp_set_entry(table, 2, show_date(date, tz, 0));
774
interp_set_entry(table, 3, show_rfc2822_date(date, tz));
775
interp_set_entry(table, 4, show_date(date, tz, 1));
784
interp_set_entry(table, 2, show_date(date, tz, DATE_NORMAL));
785
interp_set_entry(table, 3, show_date(date, tz, DATE_RFC2822));
786
interp_set_entry(table, 4, show_date(date, tz, DATE_RELATIVE));
787
interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601));
778
790
static long format_commit_message(const struct commit *commit,
779
const char *msg, char *buf, unsigned long space)
791
const char *msg, char **buf_p, unsigned long *space_p)
781
793
struct interp table[] = {
782
794
{ "%H" }, /* commit hash */
905
920
if (!table[i].value)
906
921
interp_set_entry(table, i, "<unknown>");
908
interpolate(buf, space, user_format, table, ARRAY_SIZE(table));
925
unsigned long space = *space_p;
927
space = interpolate(buf, space, user_format,
928
table, ARRAY_SIZE(table));
931
buf = xrealloc(buf, space);
909
935
interp_clear_table(table, ARRAY_SIZE(table));
937
return strlen(*buf_p);
940
static void pp_header(enum cmit_fmt fmt,
942
enum date_mode dmode,
943
const char *encoding,
944
const struct commit *commit,
946
unsigned long *len_p,
947
unsigned long *ofs_p,
949
unsigned long *space_p)
951
int parents_shown = 0;
954
const char *line = *msg_p;
956
int linelen = get_one_line(*msg_p, *len_p);
968
ALLOC_GROW(*buf_p, linelen + *ofs_p + 20, *space_p);
969
dst = *buf_p + *ofs_p;
971
if (fmt == CMIT_FMT_RAW) {
972
memcpy(dst, line, linelen);
977
if (!memcmp(line, "parent ", 7)) {
979
die("bad parent line in commit");
983
if (!parents_shown) {
984
struct commit_list *parent;
986
for (parent = commit->parents, num = 0;
988
parent = parent->next, num++)
990
/* with enough slop */
991
num = *ofs_p + num * 50 + 20;
992
ALLOC_GROW(*buf_p, num, *space_p);
993
dst = *buf_p + *ofs_p;
994
*ofs_p += add_merge_info(fmt, dst, commit, abbrev);
999
* MEDIUM == DEFAULT shows only author with dates.
1000
* FULL shows both authors but not dates.
1001
* FULLER shows both authors and dates.
1003
if (!memcmp(line, "author ", 7)) {
1005
if (fmt == CMIT_FMT_EMAIL)
1006
len = bound_rfc2047(linelen, encoding);
1007
ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);
1008
dst = *buf_p + *ofs_p;
1009
*ofs_p += add_user_info("Author", fmt, dst,
1010
line + 7, dmode, encoding);
1013
if (!memcmp(line, "committer ", 10) &&
1014
(fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) {
1016
if (fmt == CMIT_FMT_EMAIL)
1017
len = bound_rfc2047(linelen, encoding);
1018
ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);
1019
dst = *buf_p + *ofs_p;
1020
*ofs_p += add_user_info("Commit", fmt, dst,
1021
line + 10, dmode, encoding);
1026
static void pp_title_line(enum cmit_fmt fmt,
1028
unsigned long *len_p,
1029
unsigned long *ofs_p,
1031
unsigned long *space_p,
1033
const char *subject,
1034
const char *after_subject,
1035
const char *encoding,
1036
int plain_non_ascii)
1039
unsigned long title_alloc, title_len;
1044
title = xmalloc(title_alloc);
1046
const char *line = *msg_p;
1047
int linelen = get_one_line(line, *len_p);
1051
if (!linelen || is_empty_line(line, &linelen))
1054
if (title_alloc <= title_len + linelen + 2) {
1055
title_alloc = title_len + linelen + 80;
1056
title = xrealloc(title, title_alloc);
1060
if (fmt == CMIT_FMT_EMAIL) {
1062
title[title_len++] = '\n';
1065
title[title_len++] = ' ';
1067
memcpy(title + title_len, line, linelen);
1068
title_len += linelen;
1071
/* Enough slop for the MIME header and rfc2047 */
1072
len = bound_rfc2047(title_len, encoding)+ 1000;
1074
len += strlen(subject);
1076
len += strlen(after_subject);
1078
len += strlen(encoding);
1079
ALLOC_GROW(*buf_p, title_len + *ofs_p + len, *space_p);
1082
len = strlen(subject);
1083
memcpy(*buf_p + *ofs_p, subject, len);
1085
*ofs_p += add_rfc2047(*buf_p + *ofs_p,
1086
title, title_len, encoding);
1088
memcpy(*buf_p + *ofs_p, title, title_len);
1089
*ofs_p += title_len;
1091
(*buf_p)[(*ofs_p)++] = '\n';
1092
if (plain_non_ascii) {
1093
const char *header_fmt =
1094
"MIME-Version: 1.0\n"
1095
"Content-Type: text/plain; charset=%s\n"
1096
"Content-Transfer-Encoding: 8bit\n";
1097
*ofs_p += snprintf(*buf_p + *ofs_p,
1099
header_fmt, encoding);
1101
if (after_subject) {
1102
len = strlen(after_subject);
1103
memcpy(*buf_p + *ofs_p, after_subject, len);
1107
if (fmt == CMIT_FMT_EMAIL) {
1108
ALLOC_GROW(*buf_p, *ofs_p + 20, *space_p);
1109
(*buf_p)[(*ofs_p)++] = '\n';
1113
static void pp_remainder(enum cmit_fmt fmt,
1115
unsigned long *len_p,
1116
unsigned long *ofs_p,
1118
unsigned long *space_p,
1123
const char *line = *msg_p;
1124
int linelen = get_one_line(line, *len_p);
1131
if (is_empty_line(line, &linelen)) {
1134
if (fmt == CMIT_FMT_SHORT)
1139
ALLOC_GROW(*buf_p, *ofs_p + linelen + indent + 20, *space_p);
1141
memset(*buf_p + *ofs_p, ' ', indent);
1144
memcpy(*buf_p + *ofs_p, line, linelen);
1146
(*buf_p)[(*ofs_p)++] = '\n';
914
1150
unsigned long pretty_print_commit(enum cmit_fmt fmt,
915
1151
const struct commit *commit,
916
1152
unsigned long len,
917
char *buf, unsigned long space,
1153
char **buf_p, unsigned long *space_p,
918
1154
int abbrev, const char *subject,
919
1155
const char *after_subject,
920
1156
enum date_mode dmode)
922
int hdr = 1, body = 0, seen_title = 0;
923
1158
unsigned long offset = 0;
1159
unsigned long beginning_of_body;
925
int parents_shown = 0;
926
1161
const char *msg = commit->buffer;
927
1162
int plain_non_ascii = 0;
928
1163
char *reencoded;
929
1164
const char *encoding;
931
1167
if (fmt == CMIT_FMT_USERFORMAT)
932
return format_commit_message(commit, msg, buf, space);
1168
return format_commit_message(commit, msg, buf_p, space_p);
934
1170
encoding = (git_log_output_encoding
935
1171
? git_log_output_encoding
1210
pp_header(fmt, abbrev, dmode, encoding,
1212
&offset, buf_p, space_p);
1213
if (fmt != CMIT_FMT_ONELINE && !subject) {
1214
ALLOC_GROW(*buf_p, offset + 20, *space_p);
1215
(*buf_p)[offset++] = '\n';
1218
/* Skip excess blank lines at the beginning of body, if any... */
973
const char *line = msg;
974
1220
int linelen = get_one_line(msg, len);
980
* We want some slop for indentation and a possible
981
* final "...". Thus the "+ 20".
983
if (offset + linelen + 20 > space) {
984
memcpy(buf + offset, " ...\n", 8);
1224
if (!is_empty_line(msg, &ll))
994
if ((fmt != CMIT_FMT_ONELINE) && !subject)
995
buf[offset++] = '\n';
998
if (fmt == CMIT_FMT_RAW) {
999
memcpy(buf + offset, line, linelen);
1003
if (!memcmp(line, "parent ", 7)) {
1005
die("bad parent line in commit");
1009
if (!parents_shown) {
1010
offset += add_merge_info(fmt, buf + offset,
1016
* MEDIUM == DEFAULT shows only author with dates.
1017
* FULL shows both authors but not dates.
1018
* FULLER shows both authors and dates.
1020
if (!memcmp(line, "author ", 7))
1021
offset += add_user_info("Author", fmt,
1026
if (!memcmp(line, "committer ", 10) &&
1027
(fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER))
1028
offset += add_user_info("Commit", fmt,
1039
if (is_empty_line(line, &linelen)) {
1046
if (fmt == CMIT_FMT_SHORT)
1052
int slen = strlen(subject);
1053
memcpy(buf + offset, subject, slen);
1055
offset += add_rfc2047(buf + offset, line, linelen,
1059
memset(buf + offset, ' ', indent);
1060
memcpy(buf + offset + indent, line, linelen);
1061
offset += linelen + indent;
1063
buf[offset++] = '\n';
1064
if (fmt == CMIT_FMT_ONELINE)
1066
if (subject && plain_non_ascii) {
1069
const char *header_fmt =
1070
"MIME-Version: 1.0\n"
1071
"Content-Type: text/plain; charset=%s\n"
1072
"Content-Transfer-Encoding: 8bit\n";
1073
sz = snprintf(header, sizeof(header), header_fmt,
1075
if (sizeof(header) < sz)
1076
die("Encoding name %s too long", encoding);
1077
memcpy(buf + offset, header, sz);
1080
if (after_subject) {
1081
int slen = strlen(after_subject);
1082
if (slen > space - offset - 1)
1083
slen = space - offset - 1;
1084
memcpy(buf + offset, after_subject, slen);
1086
after_subject = NULL;
1090
while (offset && isspace(buf[offset-1]))
1230
/* These formats treat the title line specially. */
1231
if (fmt == CMIT_FMT_ONELINE
1232
|| fmt == CMIT_FMT_EMAIL)
1233
pp_title_line(fmt, &msg, &len, &offset,
1234
buf_p, space_p, indent,
1235
subject, after_subject, encoding,
1238
beginning_of_body = offset;
1239
if (fmt != CMIT_FMT_ONELINE)
1240
pp_remainder(fmt, &msg, &len, &offset,
1241
buf_p, space_p, indent);
1243
while (offset && isspace((*buf_p)[offset-1]))
1246
ALLOC_GROW(*buf_p, offset + 20, *space_p);
1092
1249
/* Make sure there is an EOLN for the non-oneline case */
1093
1250
if (fmt != CMIT_FMT_ONELINE)
1094
1251
buf[offset++] = '\n';
1096
* make sure there is another EOLN to separate the headers from whatever
1097
* body the caller appends if we haven't already written a body
1254
* The caller may append additional body text in e-mail
1255
* format. Make sure we did not strip the blank line
1256
* between the header and the body.
1099
if (fmt == CMIT_FMT_EMAIL && !body)
1258
if (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body)
1100
1259
buf[offset++] = '\n';
1101
1260
buf[offset] = '\0';
1103
1261
free(reencoded);