THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1981 lines
48KB

  1. #include "cache.h"
  2. #include "config.h"
  3. #include "commit.h"
  4. #include "utf8.h"
  5. #include "diff.h"
  6. #include "revision.h"
  7. #include "string-list.h"
  8. #include "mailmap.h"
  9. #include "log-tree.h"
  10. #include "notes.h"
  11. #include "color.h"
  12. #include "reflog-walk.h"
  13. #include "gpg-interface.h"
  14. #include "trailer.h"
  15. static char *user_format;
  16. static struct cmt_fmt_map {
  17. const char *name;
  18. enum cmit_fmt format;
  19. int is_tformat;
  20. int expand_tabs_in_log;
  21. int is_alias;
  22. const char *user_format;
  23. } *commit_formats;
  24. static size_t builtin_formats_len;
  25. static size_t commit_formats_len;
  26. static size_t commit_formats_alloc;
  27. static struct cmt_fmt_map *find_commit_format(const char *sought);
  28. int commit_format_is_empty(enum cmit_fmt fmt)
  29. {
  30. return fmt == CMIT_FMT_USERFORMAT && !*user_format;
  31. }
  32. static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
  33. {
  34. free(user_format);
  35. user_format = xstrdup(cp);
  36. if (is_tformat)
  37. rev->use_terminator = 1;
  38. rev->commit_format = CMIT_FMT_USERFORMAT;
  39. }
  40. static int git_pretty_formats_config(const char *var, const char *value, void *cb)
  41. {
  42. struct cmt_fmt_map *commit_format = NULL;
  43. const char *name;
  44. const char *fmt;
  45. int i;
  46. if (!skip_prefix(var, "pretty.", &name))
  47. return 0;
  48. for (i = 0; i < builtin_formats_len; i++) {
  49. if (!strcmp(commit_formats[i].name, name))
  50. return 0;
  51. }
  52. for (i = builtin_formats_len; i < commit_formats_len; i++) {
  53. if (!strcmp(commit_formats[i].name, name)) {
  54. commit_format = &commit_formats[i];
  55. break;
  56. }
  57. }
  58. if (!commit_format) {
  59. ALLOC_GROW(commit_formats, commit_formats_len+1,
  60. commit_formats_alloc);
  61. commit_format = &commit_formats[commit_formats_len];
  62. memset(commit_format, 0, sizeof(*commit_format));
  63. commit_formats_len++;
  64. }
  65. commit_format->name = xstrdup(name);
  66. commit_format->format = CMIT_FMT_USERFORMAT;
  67. if (git_config_string(&fmt, var, value))
  68. return -1;
  69. if (skip_prefix(fmt, "format:", &fmt))
  70. commit_format->is_tformat = 0;
  71. else if (skip_prefix(fmt, "tformat:", &fmt) || strchr(fmt, '%'))
  72. commit_format->is_tformat = 1;
  73. else
  74. commit_format->is_alias = 1;
  75. commit_format->user_format = fmt;
  76. return 0;
  77. }
  78. static void setup_commit_formats(void)
  79. {
  80. struct cmt_fmt_map builtin_formats[] = {
  81. { "raw", CMIT_FMT_RAW, 0, 0 },
  82. { "medium", CMIT_FMT_MEDIUM, 0, 8 },
  83. { "short", CMIT_FMT_SHORT, 0, 0 },
  84. { "email", CMIT_FMT_EMAIL, 0, 0 },
  85. { "mboxrd", CMIT_FMT_MBOXRD, 0, 0 },
  86. { "fuller", CMIT_FMT_FULLER, 0, 8 },
  87. { "full", CMIT_FMT_FULL, 0, 8 },
  88. { "oneline", CMIT_FMT_ONELINE, 1, 0 }
  89. /*
  90. * Please update $__git_log_pretty_formats in
  91. * git-completion.bash when you add new formats.
  92. */
  93. };
  94. commit_formats_len = ARRAY_SIZE(builtin_formats);
  95. builtin_formats_len = commit_formats_len;
  96. ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
  97. COPY_ARRAY(commit_formats, builtin_formats,
  98. ARRAY_SIZE(builtin_formats));
  99. git_config(git_pretty_formats_config, NULL);
  100. }
  101. static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
  102. const char *original,
  103. int num_redirections)
  104. {
  105. struct cmt_fmt_map *found = NULL;
  106. size_t found_match_len = 0;
  107. int i;
  108. if (num_redirections >= commit_formats_len)
  109. die("invalid --pretty format: "
  110. "'%s' references an alias which points to itself",
  111. original);
  112. for (i = 0; i < commit_formats_len; i++) {
  113. size_t match_len;
  114. if (!starts_with(commit_formats[i].name, sought))
  115. continue;
  116. match_len = strlen(commit_formats[i].name);
  117. if (found == NULL || found_match_len > match_len) {
  118. found = &commit_formats[i];
  119. found_match_len = match_len;
  120. }
  121. }
  122. if (found && found->is_alias) {
  123. found = find_commit_format_recursive(found->user_format,
  124. original,
  125. num_redirections+1);
  126. }
  127. return found;
  128. }
  129. static struct cmt_fmt_map *find_commit_format(const char *sought)
  130. {
  131. if (!commit_formats)
  132. setup_commit_formats();
  133. return find_commit_format_recursive(sought, sought, 0);
  134. }
  135. void get_commit_format(const char *arg, struct rev_info *rev)
  136. {
  137. struct cmt_fmt_map *commit_format;
  138. rev->use_terminator = 0;
  139. if (!arg) {
  140. rev->commit_format = CMIT_FMT_DEFAULT;
  141. return;
  142. }
  143. if (skip_prefix(arg, "format:", &arg)) {
  144. save_user_format(rev, arg, 0);
  145. return;
  146. }
  147. if (!*arg || skip_prefix(arg, "tformat:", &arg) || strchr(arg, '%')) {
  148. save_user_format(rev, arg, 1);
  149. return;
  150. }
  151. commit_format = find_commit_format(arg);
  152. if (!commit_format)
  153. die("invalid --pretty format: %s", arg);
  154. rev->commit_format = commit_format->format;
  155. rev->use_terminator = commit_format->is_tformat;
  156. rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
  157. if (commit_format->format == CMIT_FMT_USERFORMAT) {
  158. save_user_format(rev, commit_format->user_format,
  159. commit_format->is_tformat);
  160. }
  161. }
  162. /*
  163. * Generic support for pretty-printing the header
  164. */
  165. static int get_one_line(const char *msg)
  166. {
  167. int ret = 0;
  168. for (;;) {
  169. char c = *msg++;
  170. if (!c)
  171. break;
  172. ret++;
  173. if (c == '\n')
  174. break;
  175. }
  176. return ret;
  177. }
  178. /* High bit set, or ISO-2022-INT */
  179. static int non_ascii(int ch)
  180. {
  181. return !isascii(ch) || ch == '\033';
  182. }
  183. int has_non_ascii(const char *s)
  184. {
  185. int ch;
  186. if (!s)
  187. return 0;
  188. while ((ch = *s++) != '\0') {
  189. if (non_ascii(ch))
  190. return 1;
  191. }
  192. return 0;
  193. }
  194. static int is_rfc822_special(char ch)
  195. {
  196. switch (ch) {
  197. case '(':
  198. case ')':
  199. case '<':
  200. case '>':
  201. case '[':
  202. case ']':
  203. case ':':
  204. case ';':
  205. case '@':
  206. case ',':
  207. case '.':
  208. case '"':
  209. case '\\':
  210. return 1;
  211. default:
  212. return 0;
  213. }
  214. }
  215. static int needs_rfc822_quoting(const char *s, int len)
  216. {
  217. int i;
  218. for (i = 0; i < len; i++)
  219. if (is_rfc822_special(s[i]))
  220. return 1;
  221. return 0;
  222. }
  223. static int last_line_length(struct strbuf *sb)
  224. {
  225. int i;
  226. /* How many bytes are already used on the last line? */
  227. for (i = sb->len - 1; i >= 0; i--)
  228. if (sb->buf[i] == '\n')
  229. break;
  230. return sb->len - (i + 1);
  231. }
  232. static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
  233. {
  234. int i;
  235. /* just a guess, we may have to also backslash-quote */
  236. strbuf_grow(out, len + 2);
  237. strbuf_addch(out, '"');
  238. for (i = 0; i < len; i++) {
  239. switch (s[i]) {
  240. case '"':
  241. case '\\':
  242. strbuf_addch(out, '\\');
  243. /* fall through */
  244. default:
  245. strbuf_addch(out, s[i]);
  246. }
  247. }
  248. strbuf_addch(out, '"');
  249. }
  250. enum rfc2047_type {
  251. RFC2047_SUBJECT,
  252. RFC2047_ADDRESS
  253. };
  254. static int is_rfc2047_special(char ch, enum rfc2047_type type)
  255. {
  256. /*
  257. * rfc2047, section 4.2:
  258. *
  259. * 8-bit values which correspond to printable ASCII characters other
  260. * than "=", "?", and "_" (underscore), MAY be represented as those
  261. * characters. (But see section 5 for restrictions.) In
  262. * particular, SPACE and TAB MUST NOT be represented as themselves
  263. * within encoded words.
  264. */
  265. /*
  266. * rule out non-ASCII characters and non-printable characters (the
  267. * non-ASCII check should be redundant as isprint() is not localized
  268. * and only knows about ASCII, but be defensive about that)
  269. */
  270. if (non_ascii(ch) || !isprint(ch))
  271. return 1;
  272. /*
  273. * rule out special printable characters (' ' should be the only
  274. * whitespace character considered printable, but be defensive and use
  275. * isspace())
  276. */
  277. if (isspace(ch) || ch == '=' || ch == '?' || ch == '_')
  278. return 1;
  279. /*
  280. * rfc2047, section 5.3:
  281. *
  282. * As a replacement for a 'word' entity within a 'phrase', for example,
  283. * one that precedes an address in a From, To, or Cc header. The ABNF
  284. * definition for 'phrase' from RFC 822 thus becomes:
  285. *
  286. * phrase = 1*( encoded-word / word )
  287. *
  288. * In this case the set of characters that may be used in a "Q"-encoded
  289. * 'encoded-word' is restricted to: <upper and lower case ASCII
  290. * letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
  291. * (underscore, ASCII 95.)>. An 'encoded-word' that appears within a
  292. * 'phrase' MUST be separated from any adjacent 'word', 'text' or
  293. * 'special' by 'linear-white-space'.
  294. */
  295. if (type != RFC2047_ADDRESS)
  296. return 0;
  297. /* '=' and '_' are special cases and have been checked above */
  298. return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
  299. }
  300. static int needs_rfc2047_encoding(const char *line, int len)
  301. {
  302. int i;
  303. for (i = 0; i < len; i++) {
  304. int ch = line[i];
  305. if (non_ascii(ch) || ch == '\n')
  306. return 1;
  307. if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
  308. return 1;
  309. }
  310. return 0;
  311. }
  312. static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
  313. const char *encoding, enum rfc2047_type type)
  314. {
  315. static const int max_encoded_length = 76; /* per rfc2047 */
  316. int i;
  317. int line_len = last_line_length(sb);
  318. strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
  319. strbuf_addf(sb, "=?%s?q?", encoding);
  320. line_len += strlen(encoding) + 5; /* 5 for =??q? */
  321. while (len) {
  322. /*
  323. * RFC 2047, section 5 (3):
  324. *
  325. * Each 'encoded-word' MUST represent an integral number of
  326. * characters. A multi-octet character may not be split across
  327. * adjacent 'encoded- word's.
  328. */
  329. const unsigned char *p = (const unsigned char *)line;
  330. int chrlen = mbs_chrlen(&line, &len, encoding);
  331. int is_special = (chrlen > 1) || is_rfc2047_special(*p, type);
  332. /* "=%02X" * chrlen, or the byte itself */
  333. const char *encoded_fmt = is_special ? "=%02X" : "%c";
  334. int encoded_len = is_special ? 3 * chrlen : 1;
  335. /*
  336. * According to RFC 2047, we could encode the special character
  337. * ' ' (space) with '_' (underscore) for readability. But many
  338. * programs do not understand this and just leave the
  339. * underscore in place. Thus, we do nothing special here, which
  340. * causes ' ' to be encoded as '=20', avoiding this problem.
  341. */
  342. if (line_len + encoded_len + 2 > max_encoded_length) {
  343. /* It won't fit with trailing "?=" --- break the line */
  344. strbuf_addf(sb, "?=\n =?%s?q?", encoding);
  345. line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
  346. }
  347. for (i = 0; i < chrlen; i++)
  348. strbuf_addf(sb, encoded_fmt, p[i]);
  349. line_len += encoded_len;
  350. }
  351. strbuf_addstr(sb, "?=");
  352. }
  353. const char *show_ident_date(const struct ident_split *ident,
  354. const struct date_mode *mode)
  355. {
  356. timestamp_t date = 0;
  357. long tz = 0;
  358. if (ident->date_begin && ident->date_end)
  359. date = parse_timestamp(ident->date_begin, NULL, 10);
  360. if (date_overflows(date))
  361. date = 0;
  362. else {
  363. if (ident->tz_begin && ident->tz_end)
  364. tz = strtol(ident->tz_begin, NULL, 10);
  365. if (tz >= INT_MAX || tz <= INT_MIN)
  366. tz = 0;
  367. }
  368. return show_date(date, tz, mode);
  369. }
  370. void pp_user_info(struct pretty_print_context *pp,
  371. const char *what, struct strbuf *sb,
  372. const char *line, const char *encoding)
  373. {
  374. struct ident_split ident;
  375. char *line_end;
  376. const char *mailbuf, *namebuf;
  377. size_t namelen, maillen;
  378. int max_length = 78; /* per rfc2822 */
  379. if (pp->fmt == CMIT_FMT_ONELINE)
  380. return;
  381. line_end = strchrnul(line, '\n');
  382. if (split_ident_line(&ident, line, line_end - line))
  383. return;
  384. mailbuf = ident.mail_begin;
  385. maillen = ident.mail_end - ident.mail_begin;
  386. namebuf = ident.name_begin;
  387. namelen = ident.name_end - ident.name_begin;
  388. if (pp->mailmap)
  389. map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
  390. if (cmit_fmt_is_mail(pp->fmt)) {
  391. if (pp->from_ident && ident_cmp(pp->from_ident, &ident)) {
  392. struct strbuf buf = STRBUF_INIT;
  393. strbuf_addstr(&buf, "From: ");
  394. strbuf_add(&buf, namebuf, namelen);
  395. strbuf_addstr(&buf, " <");
  396. strbuf_add(&buf, mailbuf, maillen);
  397. strbuf_addstr(&buf, ">\n");
  398. string_list_append(&pp->in_body_headers,
  399. strbuf_detach(&buf, NULL));
  400. mailbuf = pp->from_ident->mail_begin;
  401. maillen = pp->from_ident->mail_end - mailbuf;
  402. namebuf = pp->from_ident->name_begin;
  403. namelen = pp->from_ident->name_end - namebuf;
  404. }
  405. strbuf_addstr(sb, "From: ");
  406. if (needs_rfc2047_encoding(namebuf, namelen)) {
  407. add_rfc2047(sb, namebuf, namelen,
  408. encoding, RFC2047_ADDRESS);
  409. max_length = 76; /* per rfc2047 */
  410. } else if (needs_rfc822_quoting(namebuf, namelen)) {
  411. struct strbuf quoted = STRBUF_INIT;
  412. add_rfc822_quoted(&quoted, namebuf, namelen);
  413. strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
  414. -6, 1, max_length);
  415. strbuf_release(&quoted);
  416. } else {
  417. strbuf_add_wrapped_bytes(sb, namebuf, namelen,
  418. -6, 1, max_length);
  419. }
  420. if (max_length <
  421. last_line_length(sb) + strlen(" <") + maillen + strlen(">"))
  422. strbuf_addch(sb, '\n');
  423. strbuf_addf(sb, " <%.*s>\n", (int)maillen, mailbuf);
  424. } else {
  425. strbuf_addf(sb, "%s: %.*s%.*s <%.*s>\n", what,
  426. (pp->fmt == CMIT_FMT_FULLER) ? 4 : 0, " ",
  427. (int)namelen, namebuf, (int)maillen, mailbuf);
  428. }
  429. switch (pp->fmt) {
  430. case CMIT_FMT_MEDIUM:
  431. strbuf_addf(sb, "Date: %s\n",
  432. show_ident_date(&ident, &pp->date_mode));
  433. break;
  434. case CMIT_FMT_EMAIL:
  435. case CMIT_FMT_MBOXRD:
  436. strbuf_addf(sb, "Date: %s\n",
  437. show_ident_date(&ident, DATE_MODE(RFC2822)));
  438. break;
  439. case CMIT_FMT_FULLER:
  440. strbuf_addf(sb, "%sDate: %s\n", what,
  441. show_ident_date(&ident, &pp->date_mode));
  442. break;
  443. default:
  444. /* notin' */
  445. break;
  446. }
  447. }
  448. static int is_blank_line(const char *line, int *len_p)
  449. {
  450. int len = *len_p;
  451. while (len && isspace(line[len - 1]))
  452. len--;
  453. *len_p = len;
  454. return !len;
  455. }
  456. const char *skip_blank_lines(const char *msg)
  457. {
  458. for (;;) {
  459. int linelen = get_one_line(msg);
  460. int ll = linelen;
  461. if (!linelen)
  462. break;
  463. if (!is_blank_line(msg, &ll))
  464. break;
  465. msg += linelen;
  466. }
  467. return msg;
  468. }
  469. static void add_merge_info(const struct pretty_print_context *pp,
  470. struct strbuf *sb, const struct commit *commit)
  471. {
  472. struct commit_list *parent = commit->parents;
  473. if ((pp->fmt == CMIT_FMT_ONELINE) || (cmit_fmt_is_mail(pp->fmt)) ||
  474. !parent || !parent->next)
  475. return;
  476. strbuf_addstr(sb, "Merge:");
  477. while (parent) {
  478. struct object_id *oidp = &parent->item->object.oid;
  479. strbuf_addch(sb, ' ');
  480. if (pp->abbrev)
  481. strbuf_add_unique_abbrev(sb, oidp, pp->abbrev);
  482. else
  483. strbuf_addstr(sb, oid_to_hex(oidp));
  484. parent = parent->next;
  485. }
  486. strbuf_addch(sb, '\n');
  487. }
  488. static char *get_header(const char *msg, const char *key)
  489. {
  490. size_t len;
  491. const char *v = find_commit_header(msg, key, &len);
  492. return v ? xmemdupz(v, len) : NULL;
  493. }
  494. static char *replace_encoding_header(char *buf, const char *encoding)
  495. {
  496. struct strbuf tmp = STRBUF_INIT;
  497. size_t start, len;
  498. char *cp = buf;
  499. /* guess if there is an encoding header before a \n\n */
  500. while (!starts_with(cp, "encoding ")) {
  501. cp = strchr(cp, '\n');
  502. if (!cp || *++cp == '\n')
  503. return buf;
  504. }
  505. start = cp - buf;
  506. cp = strchr(cp, '\n');
  507. if (!cp)
  508. return buf; /* should not happen but be defensive */
  509. len = cp + 1 - (buf + start);
  510. strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1);
  511. if (is_encoding_utf8(encoding)) {
  512. /* we have re-coded to UTF-8; drop the header */
  513. strbuf_remove(&tmp, start, len);
  514. } else {
  515. /* just replaces XXXX in 'encoding XXXX\n' */
  516. strbuf_splice(&tmp, start + strlen("encoding "),
  517. len - strlen("encoding \n"),
  518. encoding, strlen(encoding));
  519. }
  520. return strbuf_detach(&tmp, NULL);
  521. }
  522. const char *repo_logmsg_reencode(struct repository *r,
  523. const struct commit *commit,
  524. char **commit_encoding,
  525. const char *output_encoding)
  526. {
  527. static const char *utf8 = "UTF-8";
  528. const char *use_encoding;
  529. char *encoding;
  530. const char *msg = repo_get_commit_buffer(r, commit, NULL);
  531. char *out;
  532. if (!output_encoding || !*output_encoding) {
  533. if (commit_encoding)
  534. *commit_encoding = get_header(msg, "encoding");
  535. return msg;
  536. }
  537. encoding = get_header(msg, "encoding");
  538. if (commit_encoding)
  539. *commit_encoding = encoding;
  540. use_encoding = encoding ? encoding : utf8;
  541. if (same_encoding(use_encoding, output_encoding)) {
  542. /*
  543. * No encoding work to be done. If we have no encoding header
  544. * at all, then there's nothing to do, and we can return the
  545. * message verbatim (whether newly allocated or not).
  546. */
  547. if (!encoding)
  548. return msg;
  549. /*
  550. * Otherwise, we still want to munge the encoding header in the
  551. * result, which will be done by modifying the buffer. If we
  552. * are using a fresh copy, we can reuse it. But if we are using
  553. * the cached copy from get_commit_buffer, we need to duplicate it
  554. * to avoid munging the cached copy.
  555. */
  556. if (msg == get_cached_commit_buffer(r, commit, NULL))
  557. out = xstrdup(msg);
  558. else
  559. out = (char *)msg;
  560. }
  561. else {
  562. /*
  563. * There's actual encoding work to do. Do the reencoding, which
  564. * still leaves the header to be replaced in the next step. At
  565. * this point, we are done with msg. If we allocated a fresh
  566. * copy, we can free it.
  567. */
  568. out = reencode_string(msg, output_encoding, use_encoding);
  569. if (out)
  570. repo_unuse_commit_buffer(r, commit, msg);
  571. }
  572. /*
  573. * This replacement actually consumes the buffer we hand it, so we do
  574. * not have to worry about freeing the old "out" here.
  575. */
  576. if (out)
  577. out = replace_encoding_header(out, output_encoding);
  578. if (!commit_encoding)
  579. free(encoding);
  580. /*
  581. * If the re-encoding failed, out might be NULL here; in that
  582. * case we just return the commit message verbatim.
  583. */
  584. return out ? out : msg;
  585. }
  586. static int mailmap_name(const char **email, size_t *email_len,
  587. const char **name, size_t *name_len)
  588. {
  589. static struct string_list *mail_map;
  590. if (!mail_map) {
  591. mail_map = xcalloc(1, sizeof(*mail_map));
  592. read_mailmap(mail_map, NULL);
  593. }
  594. return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
  595. }
  596. static size_t format_person_part(struct strbuf *sb, char part,
  597. const char *msg, int len,
  598. const struct date_mode *dmode)
  599. {
  600. /* currently all placeholders have same length */
  601. const int placeholder_len = 2;
  602. struct ident_split s;
  603. const char *name, *mail;
  604. size_t maillen, namelen;
  605. if (split_ident_line(&s, msg, len) < 0)
  606. goto skip;
  607. name = s.name_begin;
  608. namelen = s.name_end - s.name_begin;
  609. mail = s.mail_begin;
  610. maillen = s.mail_end - s.mail_begin;
  611. if (part == 'N' || part == 'E' || part == 'L') /* mailmap lookup */
  612. mailmap_name(&mail, &maillen, &name, &namelen);
  613. if (part == 'n' || part == 'N') { /* name */
  614. strbuf_add(sb, name, namelen);
  615. return placeholder_len;
  616. }
  617. if (part == 'e' || part == 'E') { /* email */
  618. strbuf_add(sb, mail, maillen);
  619. return placeholder_len;
  620. }
  621. if (part == 'l' || part == 'L') { /* local-part */
  622. const char *at = memchr(mail, '@', maillen);
  623. if (at)
  624. maillen = at - mail;
  625. strbuf_add(sb, mail, maillen);
  626. return placeholder_len;
  627. }
  628. if (!s.date_begin)
  629. goto skip;
  630. if (part == 't') { /* date, UNIX timestamp */
  631. strbuf_add(sb, s.date_begin, s.date_end - s.date_begin);
  632. return placeholder_len;
  633. }
  634. switch (part) {
  635. case 'd': /* date */
  636. strbuf_addstr(sb, show_ident_date(&s, dmode));
  637. return placeholder_len;
  638. case 'D': /* date, RFC2822 style */
  639. strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RFC2822)));
  640. return placeholder_len;
  641. case 'r': /* date, relative */
  642. strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(RELATIVE)));
  643. return placeholder_len;
  644. case 'i': /* date, ISO 8601-like */
  645. strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601)));
  646. return placeholder_len;
  647. case 'I': /* date, ISO 8601 strict */
  648. strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
  649. return placeholder_len;
  650. }
  651. skip:
  652. /*
  653. * reading from either a bogus commit, or a reflog entry with
  654. * %gn, %ge, etc.; 'sb' cannot be updated, but we still need
  655. * to compute a valid return value.
  656. */
  657. if (part == 'n' || part == 'e' || part == 't' || part == 'd'
  658. || part == 'D' || part == 'r' || part == 'i')
  659. return placeholder_len;
  660. return 0; /* unknown placeholder */
  661. }
  662. struct chunk {
  663. size_t off;
  664. size_t len;
  665. };
  666. enum flush_type {
  667. no_flush,
  668. flush_right,
  669. flush_left,
  670. flush_left_and_steal,
  671. flush_both
  672. };
  673. enum trunc_type {
  674. trunc_none,
  675. trunc_left,
  676. trunc_middle,
  677. trunc_right
  678. };
  679. struct format_commit_context {
  680. const struct commit *commit;
  681. const struct pretty_print_context *pretty_ctx;
  682. unsigned commit_header_parsed:1;
  683. unsigned commit_message_parsed:1;
  684. struct signature_check signature_check;
  685. enum flush_type flush_type;
  686. enum trunc_type truncate;
  687. const char *message;
  688. char *commit_encoding;
  689. size_t width, indent1, indent2;
  690. int auto_color;
  691. int padding;
  692. /* These offsets are relative to the start of the commit message. */
  693. struct chunk author;
  694. struct chunk committer;
  695. size_t message_off;
  696. size_t subject_off;
  697. size_t body_off;
  698. /* The following ones are relative to the result struct strbuf. */
  699. size_t wrap_start;
  700. };
  701. static void parse_commit_header(struct format_commit_context *context)
  702. {
  703. const char *msg = context->message;
  704. int i;
  705. for (i = 0; msg[i]; i++) {
  706. const char *name;
  707. int eol;
  708. for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
  709. ; /* do nothing */
  710. if (i == eol) {
  711. break;
  712. } else if (skip_prefix(msg + i, "author ", &name)) {
  713. context->author.off = name - msg;
  714. context->author.len = msg + eol - name;
  715. } else if (skip_prefix(msg + i, "committer ", &name)) {
  716. context->committer.off = name - msg;
  717. context->committer.len = msg + eol - name;
  718. }
  719. i = eol;
  720. }
  721. context->message_off = i;
  722. context->commit_header_parsed = 1;
  723. }
  724. static int istitlechar(char c)
  725. {
  726. return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
  727. (c >= '0' && c <= '9') || c == '.' || c == '_';
  728. }
  729. static void format_sanitized_subject(struct strbuf *sb, const char *msg)
  730. {
  731. size_t trimlen;
  732. size_t start_len = sb->len;
  733. int space = 2;
  734. for (; *msg && *msg != '\n'; msg++) {
  735. if (istitlechar(*msg)) {
  736. if (space == 1)
  737. strbuf_addch(sb, '-');
  738. space = 0;
  739. strbuf_addch(sb, *msg);
  740. if (*msg == '.')
  741. while (*(msg+1) == '.')
  742. msg++;
  743. } else
  744. space |= 1;
  745. }
  746. /* trim any trailing '.' or '-' characters */
  747. trimlen = 0;
  748. while (sb->len - trimlen > start_len &&
  749. (sb->buf[sb->len - 1 - trimlen] == '.'
  750. || sb->buf[sb->len - 1 - trimlen] == '-'))
  751. trimlen++;
  752. strbuf_remove(sb, sb->len - trimlen, trimlen);
  753. }
  754. const char *format_subject(struct strbuf *sb, const char *msg,
  755. const char *line_separator)
  756. {
  757. int first = 1;
  758. for (;;) {
  759. const char *line = msg;
  760. int linelen = get_one_line(line);
  761. msg += linelen;
  762. if (!linelen || is_blank_line(line, &linelen))
  763. break;
  764. if (!sb)
  765. continue;
  766. strbuf_grow(sb, linelen + 2);
  767. if (!first)
  768. strbuf_addstr(sb, line_separator);
  769. strbuf_add(sb, line, linelen);
  770. first = 0;
  771. }
  772. return msg;
  773. }
  774. static void parse_commit_message(struct format_commit_context *c)
  775. {
  776. const char *msg = c->message + c->message_off;
  777. const char *start = c->message;
  778. msg = skip_blank_lines(msg);
  779. c->subject_off = msg - start;
  780. msg = format_subject(NULL, msg, NULL);
  781. msg = skip_blank_lines(msg);
  782. c->body_off = msg - start;
  783. c->commit_message_parsed = 1;
  784. }
  785. static void strbuf_wrap(struct strbuf *sb, size_t pos,
  786. size_t width, size_t indent1, size_t indent2)
  787. {
  788. struct strbuf tmp = STRBUF_INIT;
  789. if (pos)
  790. strbuf_add(&tmp, sb->buf, pos);
  791. strbuf_add_wrapped_text(&tmp, sb->buf + pos,
  792. (int) indent1, (int) indent2, (int) width);
  793. strbuf_swap(&tmp, sb);
  794. strbuf_release(&tmp);
  795. }
  796. static void rewrap_message_tail(struct strbuf *sb,
  797. struct format_commit_context *c,
  798. size_t new_width, size_t new_indent1,
  799. size_t new_indent2)
  800. {
  801. if (c->width == new_width && c->indent1 == new_indent1 &&
  802. c->indent2 == new_indent2)
  803. return;
  804. if (c->wrap_start < sb->len)
  805. strbuf_wrap(sb, c->wrap_start, c->width, c->indent1, c->indent2);
  806. c->wrap_start = sb->len;
  807. c->width = new_width;
  808. c->indent1 = new_indent1;
  809. c->indent2 = new_indent2;
  810. }
  811. static int format_reflog_person(struct strbuf *sb,
  812. char part,
  813. struct reflog_walk_info *log,
  814. const struct date_mode *dmode)
  815. {
  816. const char *ident;
  817. if (!log)
  818. return 2;
  819. ident = get_reflog_ident(log);
  820. if (!ident)
  821. return 2;
  822. return format_person_part(sb, part, ident, strlen(ident), dmode);
  823. }
  824. static size_t parse_color(struct strbuf *sb, /* in UTF-8 */
  825. const char *placeholder,
  826. struct format_commit_context *c)
  827. {
  828. const char *rest = placeholder;
  829. const char *basic_color = NULL;
  830. if (placeholder[1] == '(') {
  831. const char *begin = placeholder + 2;
  832. const char *end = strchr(begin, ')');
  833. char color[COLOR_MAXLEN];
  834. if (!end)
  835. return 0;
  836. if (skip_prefix(begin, "auto,", &begin)) {
  837. if (!want_color(c->pretty_ctx->color))
  838. return end - placeholder + 1;
  839. } else if (skip_prefix(begin, "always,", &begin)) {
  840. /* nothing to do; we do not respect want_color at all */
  841. } else {
  842. /* the default is the same as "auto" */
  843. if (!want_color(c->pretty_ctx->color))
  844. return end - placeholder + 1;
  845. }
  846. if (color_parse_mem(begin, end - begin, color) < 0)
  847. die(_("unable to parse --pretty format"));
  848. strbuf_addstr(sb, color);
  849. return end - placeholder + 1;
  850. }
  851. /*
  852. * We handle things like "%C(red)" above; for historical reasons, there
  853. * are a few colors that can be specified without parentheses (and
  854. * they cannot support things like "auto" or "always" at all).
  855. */
  856. if (skip_prefix(placeholder + 1, "red", &rest))
  857. basic_color = GIT_COLOR_RED;
  858. else if (skip_prefix(placeholder + 1, "green", &rest))
  859. basic_color = GIT_COLOR_GREEN;
  860. else if (skip_prefix(placeholder + 1, "blue", &rest))
  861. basic_color = GIT_COLOR_BLUE;
  862. else if (skip_prefix(placeholder + 1, "reset", &rest))
  863. basic_color = GIT_COLOR_RESET;
  864. if (basic_color && want_color(c->pretty_ctx->color))
  865. strbuf_addstr(sb, basic_color);
  866. return rest - placeholder;
  867. }
  868. static size_t parse_padding_placeholder(const char *placeholder,
  869. struct format_commit_context *c)
  870. {
  871. const char *ch = placeholder;
  872. enum flush_type flush_type;
  873. int to_column = 0;
  874. switch (*ch++) {
  875. case '<':
  876. flush_type = flush_right;
  877. break;
  878. case '>':
  879. if (*ch == '<') {
  880. flush_type = flush_both;
  881. ch++;
  882. } else if (*ch == '>') {
  883. flush_type = flush_left_and_steal;
  884. ch++;
  885. } else
  886. flush_type = flush_left;
  887. break;
  888. default:
  889. return 0;
  890. }
  891. /* the next value means "wide enough to that column" */
  892. if (*ch == '|') {
  893. to_column = 1;
  894. ch++;
  895. }
  896. if (*ch == '(') {
  897. const char *start = ch + 1;
  898. const char *end = start + strcspn(start, ",)");
  899. char *next;
  900. int width;
  901. if (!end || end == start)
  902. return 0;
  903. width = strtol(start, &next, 10);
  904. if (next == start || width == 0)
  905. return 0;
  906. if (width < 0) {
  907. if (to_column)
  908. width += term_columns();
  909. if (width < 0)
  910. return 0;
  911. }
  912. c->padding = to_column ? -width : width;
  913. c->flush_type = flush_type;
  914. if (*end == ',') {
  915. start = end + 1;
  916. end = strchr(start, ')');
  917. if (!end || end == start)
  918. return 0;
  919. if (starts_with(start, "trunc)"))
  920. c->truncate = trunc_right;
  921. else if (starts_with(start, "ltrunc)"))
  922. c->truncate = trunc_left;
  923. else if (starts_with(start, "mtrunc)"))
  924. c->truncate = trunc_middle;
  925. else
  926. return 0;
  927. } else
  928. c->truncate = trunc_none;
  929. return end - placeholder + 1;
  930. }
  931. return 0;
  932. }
  933. static int match_placeholder_arg_value(const char *to_parse, const char *candidate,
  934. const char **end, const char **valuestart,
  935. size_t *valuelen)
  936. {
  937. const char *p;
  938. if (!(skip_prefix(to_parse, candidate, &p)))
  939. return 0;
  940. if (valuestart) {
  941. if (*p == '=') {
  942. *valuestart = p + 1;
  943. *valuelen = strcspn(*valuestart, ",)");
  944. p = *valuestart + *valuelen;
  945. } else {
  946. if (*p != ',' && *p != ')')
  947. return 0;
  948. *valuestart = NULL;
  949. *valuelen = 0;
  950. }
  951. }
  952. if (*p == ',') {
  953. *end = p + 1;
  954. return 1;
  955. }
  956. if (*p == ')') {
  957. *end = p;
  958. return 1;
  959. }
  960. return 0;
  961. }
  962. static int match_placeholder_bool_arg(const char *to_parse, const char *candidate,
  963. const char **end, int *val)
  964. {
  965. const char *argval;
  966. char *strval;
  967. size_t arglen;
  968. int v;
  969. if (!match_placeholder_arg_value(to_parse, candidate, end, &argval, &arglen))
  970. return 0;
  971. if (!argval) {
  972. *val = 1;
  973. return 1;
  974. }
  975. strval = xstrndup(argval, arglen);
  976. v = git_parse_maybe_bool(strval);
  977. free(strval);
  978. if (v == -1)
  979. return 0;
  980. *val = v;
  981. return 1;
  982. }
  983. static int format_trailer_match_cb(const struct strbuf *key, void *ud)
  984. {
  985. const struct string_list *list = ud;
  986. const struct string_list_item *item;
  987. for_each_string_list_item (item, list) {
  988. if (key->len == (uintptr_t)item->util &&
  989. !strncasecmp(item->string, key->buf, key->len))
  990. return 1;
  991. }
  992. return 0;
  993. }
  994. static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
  995. const char *placeholder,
  996. void *context)
  997. {
  998. struct format_commit_context *c = context;
  999. const struct commit *commit = c->commit;
  1000. const char *msg = c->message;
  1001. struct commit_list *p;
  1002. const char *arg;
  1003. size_t res;
  1004. char **slot;
  1005. /* these are independent of the commit */
  1006. res = strbuf_expand_literal_cb(sb, placeholder, NULL);
  1007. if (res)
  1008. return res;
  1009. switch (placeholder[0]) {
  1010. case 'C':
  1011. if (starts_with(placeholder + 1, "(auto)")) {
  1012. c->auto_color = want_color(c->pretty_ctx->color);
  1013. if (c->auto_color && sb->len)
  1014. strbuf_addstr(sb, GIT_COLOR_RESET);
  1015. return 7; /* consumed 7 bytes, "C(auto)" */
  1016. } else {
  1017. int ret = parse_color(sb, placeholder, c);
  1018. if (ret)
  1019. c->auto_color = 0;
  1020. /*
  1021. * Otherwise, we decided to treat %C<unknown>
  1022. * as a literal string, and the previous
  1023. * %C(auto) is still valid.
  1024. */
  1025. return ret;
  1026. }
  1027. case 'w':
  1028. if (placeholder[1] == '(') {
  1029. unsigned long width = 0, indent1 = 0, indent2 = 0;
  1030. char *next;
  1031. const char *start = placeholder + 2;
  1032. const char *end = strchr(start, ')');
  1033. if (!end)
  1034. return 0;
  1035. if (end > start) {
  1036. width = strtoul(start, &next, 10);
  1037. if (*next == ',') {
  1038. indent1 = strtoul(next + 1, &next, 10);
  1039. if (*next == ',') {
  1040. indent2 = strtoul(next + 1,
  1041. &next, 10);
  1042. }
  1043. }
  1044. if (*next != ')')
  1045. return 0;
  1046. }
  1047. rewrap_message_tail(sb, c, width, indent1, indent2);
  1048. return end - placeholder + 1;
  1049. } else
  1050. return 0;
  1051. case '<':
  1052. case '>':
  1053. return parse_padding_placeholder(placeholder, c);
  1054. }
  1055. /* these depend on the commit */
  1056. if (!commit->object.parsed)
  1057. parse_object(the_repository, &commit->object.oid);
  1058. switch (placeholder[0]) {
  1059. case 'H': /* commit hash */
  1060. strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
  1061. strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
  1062. strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
  1063. return 1;
  1064. case 'h': /* abbreviated commit hash */
  1065. strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
  1066. strbuf_add_unique_abbrev(sb, &commit->object.oid,
  1067. c->pretty_ctx->abbrev);
  1068. strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
  1069. return 1;
  1070. case 'T': /* tree hash */
  1071. strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit)));
  1072. return 1;
  1073. case 't': /* abbreviated tree hash */
  1074. strbuf_add_unique_abbrev(sb,
  1075. get_commit_tree_oid(commit),
  1076. c->pretty_ctx->abbrev);
  1077. return 1;
  1078. case 'P': /* parent hashes */
  1079. for (p = commit->parents; p; p = p->next) {
  1080. if (p != commit->parents)
  1081. strbuf_addch(sb, ' ');
  1082. strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
  1083. }
  1084. return 1;
  1085. case 'p': /* abbreviated parent hashes */
  1086. for (p = commit->parents; p; p = p->next) {
  1087. if (p != commit->parents)
  1088. strbuf_addch(sb, ' ');
  1089. strbuf_add_unique_abbrev(sb, &p->item->object.oid,
  1090. c->pretty_ctx->abbrev);
  1091. }
  1092. return 1;
  1093. case 'm': /* left/right/bottom */
  1094. strbuf_addstr(sb, get_revision_mark(NULL, commit));
  1095. return 1;
  1096. case 'd':
  1097. format_decorations(sb, commit, c->auto_color);
  1098. return 1;
  1099. case 'D':
  1100. format_decorations_extended(sb, commit, c->auto_color, "", ", ", "");
  1101. return 1;
  1102. case 'S': /* tag/branch like --source */
  1103. if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
  1104. return 0;
  1105. slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
  1106. if (!(slot && *slot))
  1107. return 0;
  1108. strbuf_addstr(sb, *slot);
  1109. return 1;
  1110. case 'g': /* reflog info */
  1111. switch(placeholder[1]) {
  1112. case 'd': /* reflog selector */
  1113. case 'D':
  1114. if (c->pretty_ctx->reflog_info)
  1115. get_reflog_selector(sb,
  1116. c->pretty_ctx->reflog_info,
  1117. &c->pretty_ctx->date_mode,
  1118. c->pretty_ctx->date_mode_explicit,
  1119. (placeholder[1] == 'd'));
  1120. return 2;
  1121. case 's': /* reflog message */
  1122. if (c->pretty_ctx->reflog_info)
  1123. get_reflog_message(sb, c->pretty_ctx->reflog_info);
  1124. return 2;
  1125. case 'n':
  1126. case 'N':
  1127. case 'e':
  1128. case 'E':
  1129. return format_reflog_person(sb,
  1130. placeholder[1],
  1131. c->pretty_ctx->reflog_info,
  1132. &c->pretty_ctx->date_mode);
  1133. }
  1134. return 0; /* unknown %g placeholder */
  1135. case 'N':
  1136. if (c->pretty_ctx->notes_message) {
  1137. strbuf_addstr(sb, c->pretty_ctx->notes_message);
  1138. return 1;
  1139. }
  1140. return 0;
  1141. }
  1142. if (placeholder[0] == 'G') {
  1143. if (!c->signature_check.result)
  1144. check_commit_signature(c->commit, &(c->signature_check));
  1145. switch (placeholder[1]) {
  1146. case 'G':
  1147. if (c->signature_check.gpg_output)
  1148. strbuf_addstr(sb, c->signature_check.gpg_output);
  1149. break;
  1150. case '?':
  1151. switch (c->signature_check.result) {
  1152. case 'G':
  1153. case 'B':
  1154. case 'E':
  1155. case 'U':
  1156. case 'N':
  1157. case 'X':
  1158. case 'Y':
  1159. case 'R':
  1160. strbuf_addch(sb, c->signature_check.result);
  1161. }
  1162. break;
  1163. case 'S':
  1164. if (c->signature_check.signer)
  1165. strbuf_addstr(sb, c->signature_check.signer);
  1166. break;
  1167. case 'K':
  1168. if (c->signature_check.key)
  1169. strbuf_addstr(sb, c->signature_check.key);
  1170. break;
  1171. case 'F':
  1172. if (c->signature_check.fingerprint)
  1173. strbuf_addstr(sb, c->signature_check.fingerprint);
  1174. break;
  1175. case 'P':
  1176. if (c->signature_check.primary_key_fingerprint)
  1177. strbuf_addstr(sb, c->signature_check.primary_key_fingerprint);
  1178. break;
  1179. default:
  1180. return 0;
  1181. }
  1182. return 2;
  1183. }
  1184. /* For the rest we have to parse the commit header. */
  1185. if (!c->commit_header_parsed)
  1186. parse_commit_header(c);
  1187. switch (placeholder[0]) {
  1188. case 'a': /* author ... */
  1189. return format_person_part(sb, placeholder[1],
  1190. msg + c->author.off, c->author.len,
  1191. &c->pretty_ctx->date_mode);
  1192. case 'c': /* committer ... */
  1193. return format_person_part(sb, placeholder[1],
  1194. msg + c->committer.off, c->committer.len,
  1195. &c->pretty_ctx->date_mode);
  1196. case 'e': /* encoding */
  1197. if (c->commit_encoding)
  1198. strbuf_addstr(sb, c->commit_encoding);
  1199. return 1;
  1200. case 'B': /* raw body */
  1201. /* message_off is always left at the initial newline */
  1202. strbuf_addstr(sb, msg + c->message_off + 1);
  1203. return 1;
  1204. }
  1205. /* Now we need to parse the commit message. */
  1206. if (!c->commit_message_parsed)
  1207. parse_commit_message(c);
  1208. switch (placeholder[0]) {
  1209. case 's': /* subject */
  1210. format_subject(sb, msg + c->subject_off, " ");
  1211. return 1;
  1212. case 'f': /* sanitized subject */
  1213. format_sanitized_subject(sb, msg + c->subject_off);
  1214. return 1;
  1215. case 'b': /* body */
  1216. strbuf_addstr(sb, msg + c->body_off);
  1217. return 1;
  1218. }
  1219. if (skip_prefix(placeholder, "(trailers", &arg)) {
  1220. struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
  1221. struct string_list filter_list = STRING_LIST_INIT_NODUP;
  1222. struct strbuf sepbuf = STRBUF_INIT;
  1223. size_t ret = 0;
  1224. opts.no_divider = 1;
  1225. if (*arg == ':') {
  1226. arg++;
  1227. for (;;) {
  1228. const char *argval;
  1229. size_t arglen;
  1230. if (match_placeholder_arg_value(arg, "key", &arg, &argval, &arglen)) {
  1231. uintptr_t len = arglen;
  1232. if (!argval)
  1233. goto trailer_out;
  1234. if (len && argval[len - 1] == ':')
  1235. len--;
  1236. string_list_append(&filter_list, argval)->util = (char *)len;
  1237. opts.filter = format_trailer_match_cb;
  1238. opts.filter_data = &filter_list;
  1239. opts.only_trailers = 1;
  1240. } else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) {
  1241. char *fmt;
  1242. strbuf_reset(&sepbuf);
  1243. fmt = xstrndup(argval, arglen);
  1244. strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL);
  1245. free(fmt);
  1246. opts.separator = &sepbuf;
  1247. } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
  1248. !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
  1249. !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
  1250. break;
  1251. }
  1252. }
  1253. if (*arg == ')') {
  1254. format_trailers_from_commit(sb, msg + c->subject_off, &opts);
  1255. ret = arg - placeholder + 1;
  1256. }
  1257. trailer_out:
  1258. string_list_clear(&filter_list, 0);
  1259. strbuf_release(&sepbuf);
  1260. return ret;
  1261. }
  1262. return 0; /* unknown placeholder */
  1263. }
  1264. static size_t format_and_pad_commit(struct strbuf *sb, /* in UTF-8 */
  1265. const char *placeholder,
  1266. struct format_commit_context *c)
  1267. {
  1268. struct strbuf local_sb = STRBUF_INIT;
  1269. int total_consumed = 0, len, padding = c->padding;
  1270. if (padding < 0) {
  1271. const char *start = strrchr(sb->buf, '\n');
  1272. int occupied;
  1273. if (!start)
  1274. start = sb->buf;
  1275. occupied = utf8_strnwidth(start, -1, 1);
  1276. occupied += c->pretty_ctx->graph_width;
  1277. padding = (-padding) - occupied;
  1278. }
  1279. while (1) {
  1280. int modifier = *placeholder == 'C';
  1281. int consumed = format_commit_one(&local_sb, placeholder, c);
  1282. total_consumed += consumed;
  1283. if (!modifier)
  1284. break;
  1285. placeholder += consumed;
  1286. if (*placeholder != '%')
  1287. break;
  1288. placeholder++;
  1289. total_consumed++;
  1290. }
  1291. len = utf8_strnwidth(local_sb.buf, -1, 1);
  1292. if (c->flush_type == flush_left_and_steal) {
  1293. const char *ch = sb->buf + sb->len - 1;
  1294. while (len > padding && ch > sb->buf) {
  1295. const char *p;
  1296. if (*ch == ' ') {
  1297. ch--;
  1298. padding++;
  1299. continue;
  1300. }
  1301. /* check for trailing ansi sequences */
  1302. if (*ch != 'm')
  1303. break;
  1304. p = ch - 1;
  1305. while (ch - p < 10 && *p != '\033')
  1306. p--;
  1307. if (*p != '\033' ||
  1308. ch + 1 - p != display_mode_esc_sequence_len(p))
  1309. break;
  1310. /*
  1311. * got a good ansi sequence, put it back to
  1312. * local_sb as we're cutting sb
  1313. */
  1314. strbuf_insert(&local_sb, 0, p, ch + 1 - p);
  1315. ch = p - 1;
  1316. }
  1317. strbuf_setlen(sb, ch + 1 - sb->buf);
  1318. c->flush_type = flush_left;
  1319. }
  1320. if (len > padding) {
  1321. switch (c->truncate) {
  1322. case trunc_left:
  1323. strbuf_utf8_replace(&local_sb,
  1324. 0, len - (padding - 2),
  1325. "..");
  1326. break;
  1327. case trunc_middle:
  1328. strbuf_utf8_replace(&local_sb,
  1329. padding / 2 - 1,
  1330. len - (padding - 2),
  1331. "..");
  1332. break;
  1333. case trunc_right:
  1334. strbuf_utf8_replace(&local_sb,
  1335. padding - 2, len - (padding - 2),
  1336. "..");
  1337. break;
  1338. case trunc_none:
  1339. break;
  1340. }
  1341. strbuf_addbuf(sb, &local_sb);
  1342. } else {
  1343. int sb_len = sb->len, offset = 0;
  1344. if (c->flush_type == flush_left)
  1345. offset = padding - len;
  1346. else if (c->flush_type == flush_both)
  1347. offset = (padding - len) / 2;
  1348. /*
  1349. * we calculate padding in columns, now
  1350. * convert it back to chars
  1351. */
  1352. padding = padding - len + local_sb.len;
  1353. strbuf_addchars(sb, ' ', padding);
  1354. memcpy(sb->buf + sb_len + offset, local_sb.buf,
  1355. local_sb.len);
  1356. }
  1357. strbuf_release(&local_sb);
  1358. c->flush_type = no_flush;
  1359. return total_consumed;
  1360. }
  1361. static size_t format_commit_item(struct strbuf *sb, /* in UTF-8 */
  1362. const char *placeholder,
  1363. void *context)
  1364. {
  1365. int consumed;
  1366. size_t orig_len;
  1367. enum {
  1368. NO_MAGIC,
  1369. ADD_LF_BEFORE_NON_EMPTY,
  1370. DEL_LF_BEFORE_EMPTY,
  1371. ADD_SP_BEFORE_NON_EMPTY
  1372. } magic = NO_MAGIC;
  1373. switch (placeholder[0]) {
  1374. case '-':
  1375. magic = DEL_LF_BEFORE_EMPTY;
  1376. break;
  1377. case '+':
  1378. magic = ADD_LF_BEFORE_NON_EMPTY;
  1379. break;
  1380. case ' ':
  1381. magic = ADD_SP_BEFORE_NON_EMPTY;
  1382. break;
  1383. default:
  1384. break;
  1385. }
  1386. if (magic != NO_MAGIC)
  1387. placeholder++;
  1388. orig_len = sb->len;
  1389. if (((struct format_commit_context *)context)->flush_type != no_flush)
  1390. consumed = format_and_pad_commit(sb, placeholder, context);
  1391. else
  1392. consumed = format_commit_one(sb, placeholder, context);
  1393. if (magic == NO_MAGIC)
  1394. return consumed;
  1395. if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
  1396. while (sb->len && sb->buf[sb->len - 1] == '\n')
  1397. strbuf_setlen(sb, sb->len - 1);
  1398. } else if (orig_len != sb->len) {
  1399. if (magic == ADD_LF_BEFORE_NON_EMPTY)
  1400. strbuf_insert(sb, orig_len, "\n", 1);
  1401. else if (magic == ADD_SP_BEFORE_NON_EMPTY)
  1402. strbuf_insert(sb, orig_len, " ", 1);
  1403. }
  1404. return consumed + 1;
  1405. }
  1406. static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
  1407. void *context)
  1408. {
  1409. struct userformat_want *w = context;
  1410. if (*placeholder == '+' || *placeholder == '-' || *placeholder == ' ')
  1411. placeholder++;
  1412. switch (*placeholder) {
  1413. case 'N':
  1414. w->notes = 1;
  1415. break;
  1416. case 'S':
  1417. w->source = 1;
  1418. break;
  1419. }
  1420. return 0;
  1421. }
  1422. void userformat_find_requirements(const char *fmt, struct userformat_want *w)
  1423. {
  1424. struct strbuf dummy = STRBUF_INIT;
  1425. if (!fmt) {
  1426. if (!user_format)
  1427. return;
  1428. fmt = user_format;
  1429. }
  1430. strbuf_expand(&dummy, fmt, userformat_want_item, w);
  1431. strbuf_release(&dummy);
  1432. }
  1433. void repo_format_commit_message(struct repository *r,
  1434. const struct commit *commit,
  1435. const char *format, struct strbuf *sb,
  1436. const struct pretty_print_context *pretty_ctx)
  1437. {
  1438. struct format_commit_context context;
  1439. const char *output_enc = pretty_ctx->output_encoding;
  1440. const char *utf8 = "UTF-8";
  1441. memset(&context, 0, sizeof(context));
  1442. context.commit = commit;
  1443. context.pretty_ctx = pretty_ctx;
  1444. context.wrap_start = sb->len;
  1445. /*
  1446. * convert a commit message to UTF-8 first
  1447. * as far as 'format_commit_item' assumes it in UTF-8
  1448. */
  1449. context.message = repo_logmsg_reencode(r, commit,
  1450. &context.commit_encoding,
  1451. utf8);
  1452. strbuf_expand(sb, format, format_commit_item, &context);
  1453. rewrap_message_tail(sb, &context, 0, 0, 0);
  1454. /* then convert a commit message to an actual output encoding */
  1455. if (output_enc) {
  1456. if (same_encoding(utf8, output_enc))
  1457. output_enc = NULL;
  1458. } else {
  1459. if (context.commit_encoding &&
  1460. !same_encoding(context.commit_encoding, utf8))
  1461. output_enc = context.commit_encoding;
  1462. }
  1463. if (output_enc) {
  1464. size_t outsz;
  1465. char *out = reencode_string_len(sb->buf, sb->len,
  1466. output_enc, utf8, &outsz);
  1467. if (out)
  1468. strbuf_attach(sb, out, outsz, outsz + 1);
  1469. }
  1470. free(context.commit_encoding);
  1471. repo_unuse_commit_buffer(r, commit, context.message);
  1472. }
  1473. static void pp_header(struct pretty_print_context *pp,
  1474. const char *encoding,
  1475. const struct commit *commit,
  1476. const char **msg_p,
  1477. struct strbuf *sb)
  1478. {
  1479. int parents_shown = 0;
  1480. for (;;) {
  1481. const char *name, *line = *msg_p;
  1482. int linelen = get_one_line(*msg_p);
  1483. if (!linelen)
  1484. return;
  1485. *msg_p += linelen;
  1486. if (linelen == 1)
  1487. /* End of header */
  1488. return;
  1489. if (pp->fmt == CMIT_FMT_RAW) {
  1490. strbuf_add(sb, line, linelen);
  1491. continue;
  1492. }
  1493. if (starts_with(line, "parent ")) {
  1494. if (linelen != the_hash_algo->hexsz + 8)
  1495. die("bad parent line in commit");
  1496. continue;
  1497. }
  1498. if (!parents_shown) {
  1499. unsigned num = commit_list_count(commit->parents);
  1500. /* with enough slop */
  1501. strbuf_grow(sb, num * (GIT_MAX_HEXSZ + 10) + 20);
  1502. add_merge_info(pp, sb, commit);
  1503. parents_shown = 1;
  1504. }
  1505. /*
  1506. * MEDIUM == DEFAULT shows only author with dates.
  1507. * FULL shows both authors but not dates.
  1508. * FULLER shows both authors and dates.
  1509. */
  1510. if (skip_prefix(line, "author ", &name)) {
  1511. strbuf_grow(sb, linelen + 80);
  1512. pp_user_info(pp, "Author", sb, name, encoding);
  1513. }
  1514. if (skip_prefix(line, "committer ", &name) &&
  1515. (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
  1516. strbuf_grow(sb, linelen + 80);
  1517. pp_user_info(pp, "Commit", sb, name, encoding);
  1518. }
  1519. }
  1520. }
  1521. void pp_title_line(struct pretty_print_context *pp,
  1522. const char **msg_p,
  1523. struct strbuf *sb,
  1524. const char *encoding,
  1525. int need_8bit_cte)
  1526. {
  1527. static const int max_length = 78; /* per rfc2047 */
  1528. struct strbuf title;
  1529. strbuf_init(&title, 80);
  1530. *msg_p = format_subject(&title, *msg_p,
  1531. pp->preserve_subject ? "\n" : " ");
  1532. strbuf_grow(sb, title.len + 1024);
  1533. if (pp->print_email_subject) {
  1534. if (pp->rev)
  1535. fmt_output_email_subject(sb, pp->rev);
  1536. if (needs_rfc2047_encoding(title.buf, title.len))
  1537. add_rfc2047(sb, title.buf, title.len,
  1538. encoding, RFC2047_SUBJECT);
  1539. else
  1540. strbuf_add_wrapped_bytes(sb, title.buf, title.len,
  1541. -last_line_length(sb), 1, max_length);
  1542. } else {
  1543. strbuf_addbuf(sb, &title);
  1544. }
  1545. strbuf_addch(sb, '\n');
  1546. if (need_8bit_cte == 0) {
  1547. int i;
  1548. for (i = 0; i < pp->in_body_headers.nr; i++) {
  1549. if (has_non_ascii(pp->in_body_headers.items[i].string)) {
  1550. need_8bit_cte = 1;
  1551. break;
  1552. }
  1553. }
  1554. }
  1555. if (need_8bit_cte > 0) {
  1556. const char *header_fmt =
  1557. "MIME-Version: 1.0\n"
  1558. "Content-Type: text/plain; charset=%s\n"
  1559. "Content-Transfer-Encoding: 8bit\n";
  1560. strbuf_addf(sb, header_fmt, encoding);
  1561. }
  1562. if (pp->after_subject) {
  1563. strbuf_addstr(sb, pp->after_subject);
  1564. }
  1565. if (cmit_fmt_is_mail(pp->fmt)) {
  1566. strbuf_addch(sb, '\n');
  1567. }
  1568. if (pp->in_body_headers.nr) {
  1569. int i;
  1570. for (i = 0; i < pp->in_body_headers.nr; i++) {
  1571. strbuf_addstr(sb, pp->in_body_headers.items[i].string);
  1572. free(pp->in_body_headers.items[i].string);
  1573. }
  1574. string_list_clear(&pp->in_body_headers, 0);
  1575. strbuf_addch(sb, '\n');
  1576. }
  1577. strbuf_release(&title);
  1578. }
  1579. static int pp_utf8_width(const char *start, const char *end)
  1580. {
  1581. int width = 0;
  1582. size_t remain = end - start;
  1583. while (remain) {
  1584. int n = utf8_width(&start, &remain);
  1585. if (n < 0 || !start)
  1586. return -1;
  1587. width += n;
  1588. }
  1589. return width;
  1590. }
  1591. static void strbuf_add_tabexpand(struct strbuf *sb, int tabwidth,
  1592. const char *line, int linelen)
  1593. {
  1594. const char *tab;
  1595. while ((tab = memchr(line, '\t', linelen)) != NULL) {
  1596. int width = pp_utf8_width(line, tab);
  1597. /*
  1598. * If it wasn't well-formed utf8, or it
  1599. * had characters with badly defined
  1600. * width (control characters etc), just
  1601. * give up on trying to align things.
  1602. */
  1603. if (width < 0)
  1604. break;
  1605. /* Output the data .. */
  1606. strbuf_add(sb, line, tab - line);
  1607. /* .. and the de-tabified tab */
  1608. strbuf_addchars(sb, ' ', tabwidth - (width % tabwidth));
  1609. /* Skip over the printed part .. */
  1610. linelen -= tab + 1 - line;
  1611. line = tab + 1;
  1612. }
  1613. /*
  1614. * Print out everything after the last tab without
  1615. * worrying about width - there's nothing more to
  1616. * align.
  1617. */
  1618. strbuf_add(sb, line, linelen);
  1619. }
  1620. /*
  1621. * pp_handle_indent() prints out the intendation, and
  1622. * the whole line (without the final newline), after
  1623. * de-tabifying.
  1624. */
  1625. static void pp_handle_indent(struct pretty_print_context *pp,
  1626. struct strbuf *sb, int indent,
  1627. const char *line, int linelen)
  1628. {
  1629. strbuf_addchars(sb, ' ', indent);
  1630. if (pp->expand_tabs_in_log)
  1631. strbuf_add_tabexpand(sb, pp->expand_tabs_in_log, line, linelen);
  1632. else
  1633. strbuf_add(sb, line, linelen);
  1634. }
  1635. static int is_mboxrd_from(const char *line, int len)
  1636. {
  1637. /*
  1638. * a line matching /^From $/ here would only have len == 4
  1639. * at this point because is_empty_line would've trimmed all
  1640. * trailing space
  1641. */
  1642. return len > 4 && starts_with(line + strspn(line, ">"), "From ");
  1643. }
  1644. void pp_remainder(struct pretty_print_context *pp,
  1645. const char **msg_p,
  1646. struct strbuf *sb,
  1647. int indent)
  1648. {
  1649. int first = 1;
  1650. for (;;) {
  1651. const char *line = *msg_p;
  1652. int linelen = get_one_line(line);
  1653. *msg_p += linelen;
  1654. if (!linelen)
  1655. break;
  1656. if (is_blank_line(line, &linelen)) {
  1657. if (first)
  1658. continue;
  1659. if (pp->fmt == CMIT_FMT_SHORT)
  1660. break;
  1661. }
  1662. first = 0;
  1663. strbuf_grow(sb, linelen + indent + 20);
  1664. if (indent)
  1665. pp_handle_indent(pp, sb, indent, line, linelen);
  1666. else if (pp->expand_tabs_in_log)
  1667. strbuf_add_tabexpand(sb, pp->expand_tabs_in_log,
  1668. line, linelen);
  1669. else {
  1670. if (pp->fmt == CMIT_FMT_MBOXRD &&
  1671. is_mboxrd_from(line, linelen))
  1672. strbuf_addch(sb, '>');
  1673. strbuf_add(sb, line, linelen);
  1674. }
  1675. strbuf_addch(sb, '\n');
  1676. }
  1677. }
  1678. void pretty_print_commit(struct pretty_print_context *pp,
  1679. const struct commit *commit,
  1680. struct strbuf *sb)
  1681. {
  1682. unsigned long beginning_of_body;
  1683. int indent = 4;
  1684. const char *msg;
  1685. const char *reencoded;
  1686. const char *encoding;
  1687. int need_8bit_cte = pp->need_8bit_cte;
  1688. if (pp->fmt == CMIT_FMT_USERFORMAT) {
  1689. format_commit_message(commit, user_format, sb, pp);
  1690. return;
  1691. }
  1692. encoding = get_log_output_encoding();
  1693. msg = reencoded = logmsg_reencode(commit, NULL, encoding);
  1694. if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
  1695. indent = 0;
  1696. /*
  1697. * We need to check and emit Content-type: to mark it
  1698. * as 8-bit if we haven't done so.
  1699. */
  1700. if (cmit_fmt_is_mail(pp->fmt) && need_8bit_cte == 0) {
  1701. int i, ch, in_body;
  1702. for (in_body = i = 0; (ch = msg[i]); i++) {
  1703. if (!in_body) {
  1704. /* author could be non 7-bit ASCII but
  1705. * the log may be so; skip over the
  1706. * header part first.
  1707. */
  1708. if (ch == '\n' && msg[i+1] == '\n')
  1709. in_body = 1;
  1710. }
  1711. else if (non_ascii(ch)) {
  1712. need_8bit_cte = 1;
  1713. break;
  1714. }
  1715. }
  1716. }
  1717. pp_header(pp, encoding, commit, &msg, sb);
  1718. if (pp->fmt != CMIT_FMT_ONELINE && !pp->print_email_subject) {
  1719. strbuf_addch(sb, '\n');
  1720. }
  1721. /* Skip excess blank lines at the beginning of body, if any... */
  1722. msg = skip_blank_lines(msg);
  1723. /* These formats treat the title line specially. */
  1724. if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))
  1725. pp_title_line(pp, &msg, sb, encoding, need_8bit_cte);
  1726. beginning_of_body = sb->len;
  1727. if (pp->fmt != CMIT_FMT_ONELINE)
  1728. pp_remainder(pp, &msg, sb, indent);
  1729. strbuf_rtrim(sb);
  1730. /* Make sure there is an EOLN for the non-oneline case */
  1731. if (pp->fmt != CMIT_FMT_ONELINE)
  1732. strbuf_addch(sb, '\n');
  1733. /*
  1734. * The caller may append additional body text in e-mail
  1735. * format. Make sure we did not strip the blank line
  1736. * between the header and the body.
  1737. */
  1738. if (cmit_fmt_is_mail(pp->fmt) && sb->len <= beginning_of_body)
  1739. strbuf_addch(sb, '\n');
  1740. unuse_commit_buffer(commit, reencoded);
  1741. }
  1742. void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
  1743. struct strbuf *sb)
  1744. {
  1745. struct pretty_print_context pp = {0};
  1746. pp.fmt = fmt;
  1747. pretty_print_commit(&pp, commit, sb);
  1748. }