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.

1188 lines
29KB

  1. #include "cache.h"
  2. #include "config.h"
  3. #include "string-list.h"
  4. #include "run-command.h"
  5. #include "commit.h"
  6. #include "tempfile.h"
  7. #include "trailer.h"
  8. #include "list.h"
  9. /*
  10. * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
  11. */
  12. struct conf_info {
  13. char *name;
  14. char *key;
  15. char *command;
  16. enum trailer_where where;
  17. enum trailer_if_exists if_exists;
  18. enum trailer_if_missing if_missing;
  19. };
  20. static struct conf_info default_conf_info;
  21. struct trailer_item {
  22. struct list_head list;
  23. /*
  24. * If this is not a trailer line, the line is stored in value
  25. * (excluding the terminating newline) and token is NULL.
  26. */
  27. char *token;
  28. char *value;
  29. };
  30. struct arg_item {
  31. struct list_head list;
  32. char *token;
  33. char *value;
  34. struct conf_info conf;
  35. };
  36. static LIST_HEAD(conf_head);
  37. static char *separators = ":";
  38. static int configured;
  39. #define TRAILER_ARG_STRING "$ARG"
  40. static const char *git_generated_prefixes[] = {
  41. "Signed-off-by: ",
  42. "(cherry picked from commit ",
  43. NULL
  44. };
  45. /* Iterate over the elements of the list. */
  46. #define list_for_each_dir(pos, head, is_reverse) \
  47. for (pos = is_reverse ? (head)->prev : (head)->next; \
  48. pos != (head); \
  49. pos = is_reverse ? pos->prev : pos->next)
  50. static int after_or_end(enum trailer_where where)
  51. {
  52. return (where == WHERE_AFTER) || (where == WHERE_END);
  53. }
  54. /*
  55. * Return the length of the string not including any final
  56. * punctuation. E.g., the input "Signed-off-by:" would return
  57. * 13, stripping the trailing punctuation but retaining
  58. * internal punctuation.
  59. */
  60. static size_t token_len_without_separator(const char *token, size_t len)
  61. {
  62. while (len > 0 && !isalnum(token[len - 1]))
  63. len--;
  64. return len;
  65. }
  66. static int same_token(struct trailer_item *a, struct arg_item *b)
  67. {
  68. size_t a_len, b_len, min_len;
  69. if (!a->token)
  70. return 0;
  71. a_len = token_len_without_separator(a->token, strlen(a->token));
  72. b_len = token_len_without_separator(b->token, strlen(b->token));
  73. min_len = (a_len > b_len) ? b_len : a_len;
  74. return !strncasecmp(a->token, b->token, min_len);
  75. }
  76. static int same_value(struct trailer_item *a, struct arg_item *b)
  77. {
  78. return !strcasecmp(a->value, b->value);
  79. }
  80. static int same_trailer(struct trailer_item *a, struct arg_item *b)
  81. {
  82. return same_token(a, b) && same_value(a, b);
  83. }
  84. static inline int is_blank_line(const char *str)
  85. {
  86. const char *s = str;
  87. while (*s && *s != '\n' && isspace(*s))
  88. s++;
  89. return !*s || *s == '\n';
  90. }
  91. static inline void strbuf_replace(struct strbuf *sb, const char *a, const char *b)
  92. {
  93. const char *ptr = strstr(sb->buf, a);
  94. if (ptr)
  95. strbuf_splice(sb, ptr - sb->buf, strlen(a), b, strlen(b));
  96. }
  97. static void free_trailer_item(struct trailer_item *item)
  98. {
  99. free(item->token);
  100. free(item->value);
  101. free(item);
  102. }
  103. static void free_arg_item(struct arg_item *item)
  104. {
  105. free(item->conf.name);
  106. free(item->conf.key);
  107. free(item->conf.command);
  108. free(item->token);
  109. free(item->value);
  110. free(item);
  111. }
  112. static char last_non_space_char(const char *s)
  113. {
  114. int i;
  115. for (i = strlen(s) - 1; i >= 0; i--)
  116. if (!isspace(s[i]))
  117. return s[i];
  118. return '\0';
  119. }
  120. static void print_tok_val(FILE *outfile, const char *tok, const char *val)
  121. {
  122. char c;
  123. if (!tok) {
  124. fprintf(outfile, "%s\n", val);
  125. return;
  126. }
  127. c = last_non_space_char(tok);
  128. if (!c)
  129. return;
  130. if (strchr(separators, c))
  131. fprintf(outfile, "%s%s\n", tok, val);
  132. else
  133. fprintf(outfile, "%s%c %s\n", tok, separators[0], val);
  134. }
  135. static void print_all(FILE *outfile, struct list_head *head,
  136. const struct process_trailer_options *opts)
  137. {
  138. struct list_head *pos;
  139. struct trailer_item *item;
  140. list_for_each(pos, head) {
  141. item = list_entry(pos, struct trailer_item, list);
  142. if ((!opts->trim_empty || strlen(item->value) > 0) &&
  143. (!opts->only_trailers || item->token))
  144. print_tok_val(outfile, item->token, item->value);
  145. }
  146. }
  147. static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok)
  148. {
  149. struct trailer_item *new_item = xcalloc(sizeof(*new_item), 1);
  150. new_item->token = arg_tok->token;
  151. new_item->value = arg_tok->value;
  152. arg_tok->token = arg_tok->value = NULL;
  153. free_arg_item(arg_tok);
  154. return new_item;
  155. }
  156. static void add_arg_to_input_list(struct trailer_item *on_tok,
  157. struct arg_item *arg_tok)
  158. {
  159. int aoe = after_or_end(arg_tok->conf.where);
  160. struct trailer_item *to_add = trailer_from_arg(arg_tok);
  161. if (aoe)
  162. list_add(&to_add->list, &on_tok->list);
  163. else
  164. list_add_tail(&to_add->list, &on_tok->list);
  165. }
  166. static int check_if_different(struct trailer_item *in_tok,
  167. struct arg_item *arg_tok,
  168. int check_all,
  169. struct list_head *head)
  170. {
  171. enum trailer_where where = arg_tok->conf.where;
  172. struct list_head *next_head;
  173. do {
  174. if (same_trailer(in_tok, arg_tok))
  175. return 0;
  176. /*
  177. * if we want to add a trailer after another one,
  178. * we have to check those before this one
  179. */
  180. next_head = after_or_end(where) ? in_tok->list.prev
  181. : in_tok->list.next;
  182. if (next_head == head)
  183. break;
  184. in_tok = list_entry(next_head, struct trailer_item, list);
  185. } while (check_all);
  186. return 1;
  187. }
  188. static char *apply_command(const char *command, const char *arg)
  189. {
  190. struct strbuf cmd = STRBUF_INIT;
  191. struct strbuf buf = STRBUF_INIT;
  192. struct child_process cp = CHILD_PROCESS_INIT;
  193. const char *argv[] = {NULL, NULL};
  194. char *result;
  195. strbuf_addstr(&cmd, command);
  196. if (arg)
  197. strbuf_replace(&cmd, TRAILER_ARG_STRING, arg);
  198. argv[0] = cmd.buf;
  199. cp.argv = argv;
  200. cp.env = local_repo_env;
  201. cp.no_stdin = 1;
  202. cp.use_shell = 1;
  203. if (capture_command(&cp, &buf, 1024)) {
  204. error(_("running trailer command '%s' failed"), cmd.buf);
  205. strbuf_release(&buf);
  206. result = xstrdup("");
  207. } else {
  208. strbuf_trim(&buf);
  209. result = strbuf_detach(&buf, NULL);
  210. }
  211. strbuf_release(&cmd);
  212. return result;
  213. }
  214. static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
  215. {
  216. if (arg_tok->conf.command) {
  217. const char *arg;
  218. if (arg_tok->value && arg_tok->value[0]) {
  219. arg = arg_tok->value;
  220. } else {
  221. if (in_tok && in_tok->value)
  222. arg = xstrdup(in_tok->value);
  223. else
  224. arg = xstrdup("");
  225. }
  226. arg_tok->value = apply_command(arg_tok->conf.command, arg);
  227. free((char *)arg);
  228. }
  229. }
  230. static void apply_arg_if_exists(struct trailer_item *in_tok,
  231. struct arg_item *arg_tok,
  232. struct trailer_item *on_tok,
  233. struct list_head *head)
  234. {
  235. switch (arg_tok->conf.if_exists) {
  236. case EXISTS_DO_NOTHING:
  237. free_arg_item(arg_tok);
  238. break;
  239. case EXISTS_REPLACE:
  240. apply_item_command(in_tok, arg_tok);
  241. add_arg_to_input_list(on_tok, arg_tok);
  242. list_del(&in_tok->list);
  243. free_trailer_item(in_tok);
  244. break;
  245. case EXISTS_ADD:
  246. apply_item_command(in_tok, arg_tok);
  247. add_arg_to_input_list(on_tok, arg_tok);
  248. break;
  249. case EXISTS_ADD_IF_DIFFERENT:
  250. apply_item_command(in_tok, arg_tok);
  251. if (check_if_different(in_tok, arg_tok, 1, head))
  252. add_arg_to_input_list(on_tok, arg_tok);
  253. else
  254. free_arg_item(arg_tok);
  255. break;
  256. case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR:
  257. apply_item_command(in_tok, arg_tok);
  258. if (check_if_different(on_tok, arg_tok, 0, head))
  259. add_arg_to_input_list(on_tok, arg_tok);
  260. else
  261. free_arg_item(arg_tok);
  262. break;
  263. default:
  264. BUG("trailer.c: unhandled value %d",
  265. arg_tok->conf.if_exists);
  266. }
  267. }
  268. static void apply_arg_if_missing(struct list_head *head,
  269. struct arg_item *arg_tok)
  270. {
  271. enum trailer_where where;
  272. struct trailer_item *to_add;
  273. switch (arg_tok->conf.if_missing) {
  274. case MISSING_DO_NOTHING:
  275. free_arg_item(arg_tok);
  276. break;
  277. case MISSING_ADD:
  278. where = arg_tok->conf.where;
  279. apply_item_command(NULL, arg_tok);
  280. to_add = trailer_from_arg(arg_tok);
  281. if (after_or_end(where))
  282. list_add_tail(&to_add->list, head);
  283. else
  284. list_add(&to_add->list, head);
  285. break;
  286. default:
  287. BUG("trailer.c: unhandled value %d",
  288. arg_tok->conf.if_missing);
  289. }
  290. }
  291. static int find_same_and_apply_arg(struct list_head *head,
  292. struct arg_item *arg_tok)
  293. {
  294. struct list_head *pos;
  295. struct trailer_item *in_tok;
  296. struct trailer_item *on_tok;
  297. enum trailer_where where = arg_tok->conf.where;
  298. int middle = (where == WHERE_AFTER) || (where == WHERE_BEFORE);
  299. int backwards = after_or_end(where);
  300. struct trailer_item *start_tok;
  301. if (list_empty(head))
  302. return 0;
  303. start_tok = list_entry(backwards ? head->prev : head->next,
  304. struct trailer_item,
  305. list);
  306. list_for_each_dir(pos, head, backwards) {
  307. in_tok = list_entry(pos, struct trailer_item, list);
  308. if (!same_token(in_tok, arg_tok))
  309. continue;
  310. on_tok = middle ? in_tok : start_tok;
  311. apply_arg_if_exists(in_tok, arg_tok, on_tok, head);
  312. return 1;
  313. }
  314. return 0;
  315. }
  316. static void process_trailers_lists(struct list_head *head,
  317. struct list_head *arg_head)
  318. {
  319. struct list_head *pos, *p;
  320. struct arg_item *arg_tok;
  321. list_for_each_safe(pos, p, arg_head) {
  322. int applied = 0;
  323. arg_tok = list_entry(pos, struct arg_item, list);
  324. list_del(pos);
  325. applied = find_same_and_apply_arg(head, arg_tok);
  326. if (!applied)
  327. apply_arg_if_missing(head, arg_tok);
  328. }
  329. }
  330. int trailer_set_where(enum trailer_where *item, const char *value)
  331. {
  332. if (!value)
  333. *item = WHERE_DEFAULT;
  334. else if (!strcasecmp("after", value))
  335. *item = WHERE_AFTER;
  336. else if (!strcasecmp("before", value))
  337. *item = WHERE_BEFORE;
  338. else if (!strcasecmp("end", value))
  339. *item = WHERE_END;
  340. else if (!strcasecmp("start", value))
  341. *item = WHERE_START;
  342. else
  343. return -1;
  344. return 0;
  345. }
  346. int trailer_set_if_exists(enum trailer_if_exists *item, const char *value)
  347. {
  348. if (!value)
  349. *item = EXISTS_DEFAULT;
  350. else if (!strcasecmp("addIfDifferent", value))
  351. *item = EXISTS_ADD_IF_DIFFERENT;
  352. else if (!strcasecmp("addIfDifferentNeighbor", value))
  353. *item = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
  354. else if (!strcasecmp("add", value))
  355. *item = EXISTS_ADD;
  356. else if (!strcasecmp("replace", value))
  357. *item = EXISTS_REPLACE;
  358. else if (!strcasecmp("doNothing", value))
  359. *item = EXISTS_DO_NOTHING;
  360. else
  361. return -1;
  362. return 0;
  363. }
  364. int trailer_set_if_missing(enum trailer_if_missing *item, const char *value)
  365. {
  366. if (!value)
  367. *item = MISSING_DEFAULT;
  368. else if (!strcasecmp("doNothing", value))
  369. *item = MISSING_DO_NOTHING;
  370. else if (!strcasecmp("add", value))
  371. *item = MISSING_ADD;
  372. else
  373. return -1;
  374. return 0;
  375. }
  376. static void duplicate_conf(struct conf_info *dst, const struct conf_info *src)
  377. {
  378. *dst = *src;
  379. dst->name = xstrdup_or_null(src->name);
  380. dst->key = xstrdup_or_null(src->key);
  381. dst->command = xstrdup_or_null(src->command);
  382. }
  383. static struct arg_item *get_conf_item(const char *name)
  384. {
  385. struct list_head *pos;
  386. struct arg_item *item;
  387. /* Look up item with same name */
  388. list_for_each(pos, &conf_head) {
  389. item = list_entry(pos, struct arg_item, list);
  390. if (!strcasecmp(item->conf.name, name))
  391. return item;
  392. }
  393. /* Item does not already exists, create it */
  394. item = xcalloc(sizeof(*item), 1);
  395. duplicate_conf(&item->conf, &default_conf_info);
  396. item->conf.name = xstrdup(name);
  397. list_add_tail(&item->list, &conf_head);
  398. return item;
  399. }
  400. enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
  401. TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
  402. static struct {
  403. const char *name;
  404. enum trailer_info_type type;
  405. } trailer_config_items[] = {
  406. { "key", TRAILER_KEY },
  407. { "command", TRAILER_COMMAND },
  408. { "where", TRAILER_WHERE },
  409. { "ifexists", TRAILER_IF_EXISTS },
  410. { "ifmissing", TRAILER_IF_MISSING }
  411. };
  412. static int git_trailer_default_config(const char *conf_key, const char *value, void *cb)
  413. {
  414. const char *trailer_item, *variable_name;
  415. if (!skip_prefix(conf_key, "trailer.", &trailer_item))
  416. return 0;
  417. variable_name = strrchr(trailer_item, '.');
  418. if (!variable_name) {
  419. if (!strcmp(trailer_item, "where")) {
  420. if (trailer_set_where(&default_conf_info.where,
  421. value) < 0)
  422. warning(_("unknown value '%s' for key '%s'"),
  423. value, conf_key);
  424. } else if (!strcmp(trailer_item, "ifexists")) {
  425. if (trailer_set_if_exists(&default_conf_info.if_exists,
  426. value) < 0)
  427. warning(_("unknown value '%s' for key '%s'"),
  428. value, conf_key);
  429. } else if (!strcmp(trailer_item, "ifmissing")) {
  430. if (trailer_set_if_missing(&default_conf_info.if_missing,
  431. value) < 0)
  432. warning(_("unknown value '%s' for key '%s'"),
  433. value, conf_key);
  434. } else if (!strcmp(trailer_item, "separators")) {
  435. separators = xstrdup(value);
  436. }
  437. }
  438. return 0;
  439. }
  440. static int git_trailer_config(const char *conf_key, const char *value, void *cb)
  441. {
  442. const char *trailer_item, *variable_name;
  443. struct arg_item *item;
  444. struct conf_info *conf;
  445. char *name = NULL;
  446. enum trailer_info_type type;
  447. int i;
  448. if (!skip_prefix(conf_key, "trailer.", &trailer_item))
  449. return 0;
  450. variable_name = strrchr(trailer_item, '.');
  451. if (!variable_name)
  452. return 0;
  453. variable_name++;
  454. for (i = 0; i < ARRAY_SIZE(trailer_config_items); i++) {
  455. if (strcmp(trailer_config_items[i].name, variable_name))
  456. continue;
  457. name = xstrndup(trailer_item, variable_name - trailer_item - 1);
  458. type = trailer_config_items[i].type;
  459. break;
  460. }
  461. if (!name)
  462. return 0;
  463. item = get_conf_item(name);
  464. conf = &item->conf;
  465. free(name);
  466. switch (type) {
  467. case TRAILER_KEY:
  468. if (conf->key)
  469. warning(_("more than one %s"), conf_key);
  470. conf->key = xstrdup(value);
  471. break;
  472. case TRAILER_COMMAND:
  473. if (conf->command)
  474. warning(_("more than one %s"), conf_key);
  475. conf->command = xstrdup(value);
  476. break;
  477. case TRAILER_WHERE:
  478. if (trailer_set_where(&conf->where, value))
  479. warning(_("unknown value '%s' for key '%s'"), value, conf_key);
  480. break;
  481. case TRAILER_IF_EXISTS:
  482. if (trailer_set_if_exists(&conf->if_exists, value))
  483. warning(_("unknown value '%s' for key '%s'"), value, conf_key);
  484. break;
  485. case TRAILER_IF_MISSING:
  486. if (trailer_set_if_missing(&conf->if_missing, value))
  487. warning(_("unknown value '%s' for key '%s'"), value, conf_key);
  488. break;
  489. default:
  490. BUG("trailer.c: unhandled type %d", type);
  491. }
  492. return 0;
  493. }
  494. static void ensure_configured(void)
  495. {
  496. if (configured)
  497. return;
  498. /* Default config must be setup first */
  499. default_conf_info.where = WHERE_END;
  500. default_conf_info.if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
  501. default_conf_info.if_missing = MISSING_ADD;
  502. git_config(git_trailer_default_config, NULL);
  503. git_config(git_trailer_config, NULL);
  504. configured = 1;
  505. }
  506. static const char *token_from_item(struct arg_item *item, char *tok)
  507. {
  508. if (item->conf.key)
  509. return item->conf.key;
  510. if (tok)
  511. return tok;
  512. return item->conf.name;
  513. }
  514. static int token_matches_item(const char *tok, struct arg_item *item, size_t tok_len)
  515. {
  516. if (!strncasecmp(tok, item->conf.name, tok_len))
  517. return 1;
  518. return item->conf.key ? !strncasecmp(tok, item->conf.key, tok_len) : 0;
  519. }
  520. /*
  521. * If the given line is of the form
  522. * "<token><optional whitespace><separator>..." or "<separator>...", return the
  523. * location of the separator. Otherwise, return -1. The optional whitespace
  524. * is allowed there primarily to allow things like "Bug #43" where <token> is
  525. * "Bug" and <separator> is "#".
  526. *
  527. * The separator-starts-line case (in which this function returns 0) is
  528. * distinguished from the non-well-formed-line case (in which this function
  529. * returns -1) because some callers of this function need such a distinction.
  530. */
  531. static ssize_t find_separator(const char *line, const char *separators)
  532. {
  533. int whitespace_found = 0;
  534. const char *c;
  535. for (c = line; *c; c++) {
  536. if (strchr(separators, *c))
  537. return c - line;
  538. if (!whitespace_found && (isalnum(*c) || *c == '-'))
  539. continue;
  540. if (c != line && (*c == ' ' || *c == '\t')) {
  541. whitespace_found = 1;
  542. continue;
  543. }
  544. break;
  545. }
  546. return -1;
  547. }
  548. /*
  549. * Obtain the token, value, and conf from the given trailer.
  550. *
  551. * separator_pos must not be 0, since the token cannot be an empty string.
  552. *
  553. * If separator_pos is -1, interpret the whole trailer as a token.
  554. */
  555. static void parse_trailer(struct strbuf *tok, struct strbuf *val,
  556. const struct conf_info **conf, const char *trailer,
  557. ssize_t separator_pos)
  558. {
  559. struct arg_item *item;
  560. size_t tok_len;
  561. struct list_head *pos;
  562. if (separator_pos != -1) {
  563. strbuf_add(tok, trailer, separator_pos);
  564. strbuf_trim(tok);
  565. strbuf_addstr(val, trailer + separator_pos + 1);
  566. strbuf_trim(val);
  567. } else {
  568. strbuf_addstr(tok, trailer);
  569. strbuf_trim(tok);
  570. }
  571. /* Lookup if the token matches something in the config */
  572. tok_len = token_len_without_separator(tok->buf, tok->len);
  573. if (conf)
  574. *conf = &default_conf_info;
  575. list_for_each(pos, &conf_head) {
  576. item = list_entry(pos, struct arg_item, list);
  577. if (token_matches_item(tok->buf, item, tok_len)) {
  578. char *tok_buf = strbuf_detach(tok, NULL);
  579. if (conf)
  580. *conf = &item->conf;
  581. strbuf_addstr(tok, token_from_item(item, tok_buf));
  582. free(tok_buf);
  583. break;
  584. }
  585. }
  586. }
  587. static struct trailer_item *add_trailer_item(struct list_head *head, char *tok,
  588. char *val)
  589. {
  590. struct trailer_item *new_item = xcalloc(sizeof(*new_item), 1);
  591. new_item->token = tok;
  592. new_item->value = val;
  593. list_add_tail(&new_item->list, head);
  594. return new_item;
  595. }
  596. static void add_arg_item(struct list_head *arg_head, char *tok, char *val,
  597. const struct conf_info *conf,
  598. const struct new_trailer_item *new_trailer_item)
  599. {
  600. struct arg_item *new_item = xcalloc(sizeof(*new_item), 1);
  601. new_item->token = tok;
  602. new_item->value = val;
  603. duplicate_conf(&new_item->conf, conf);
  604. if (new_trailer_item) {
  605. if (new_trailer_item->where != WHERE_DEFAULT)
  606. new_item->conf.where = new_trailer_item->where;
  607. if (new_trailer_item->if_exists != EXISTS_DEFAULT)
  608. new_item->conf.if_exists = new_trailer_item->if_exists;
  609. if (new_trailer_item->if_missing != MISSING_DEFAULT)
  610. new_item->conf.if_missing = new_trailer_item->if_missing;
  611. }
  612. list_add_tail(&new_item->list, arg_head);
  613. }
  614. static void process_command_line_args(struct list_head *arg_head,
  615. struct list_head *new_trailer_head)
  616. {
  617. struct arg_item *item;
  618. struct strbuf tok = STRBUF_INIT;
  619. struct strbuf val = STRBUF_INIT;
  620. const struct conf_info *conf;
  621. struct list_head *pos;
  622. /*
  623. * In command-line arguments, '=' is accepted (in addition to the
  624. * separators that are defined).
  625. */
  626. char *cl_separators = xstrfmt("=%s", separators);
  627. /* Add an arg item for each configured trailer with a command */
  628. list_for_each(pos, &conf_head) {
  629. item = list_entry(pos, struct arg_item, list);
  630. if (item->conf.command)
  631. add_arg_item(arg_head,
  632. xstrdup(token_from_item(item, NULL)),
  633. xstrdup(""),
  634. &item->conf, NULL);
  635. }
  636. /* Add an arg item for each trailer on the command line */
  637. list_for_each(pos, new_trailer_head) {
  638. struct new_trailer_item *tr =
  639. list_entry(pos, struct new_trailer_item, list);
  640. ssize_t separator_pos = find_separator(tr->text, cl_separators);
  641. if (separator_pos == 0) {
  642. struct strbuf sb = STRBUF_INIT;
  643. strbuf_addstr(&sb, tr->text);
  644. strbuf_trim(&sb);
  645. error(_("empty trailer token in trailer '%.*s'"),
  646. (int) sb.len, sb.buf);
  647. strbuf_release(&sb);
  648. } else {
  649. parse_trailer(&tok, &val, &conf, tr->text,
  650. separator_pos);
  651. add_arg_item(arg_head,
  652. strbuf_detach(&tok, NULL),
  653. strbuf_detach(&val, NULL),
  654. conf, tr);
  655. }
  656. }
  657. free(cl_separators);
  658. }
  659. static void read_input_file(struct strbuf *sb, const char *file)
  660. {
  661. if (file) {
  662. if (strbuf_read_file(sb, file, 0) < 0)
  663. die_errno(_("could not read input file '%s'"), file);
  664. } else {
  665. if (strbuf_read(sb, fileno(stdin), 0) < 0)
  666. die_errno(_("could not read from stdin"));
  667. }
  668. }
  669. static const char *next_line(const char *str)
  670. {
  671. const char *nl = strchrnul(str, '\n');
  672. return nl + !!*nl;
  673. }
  674. /*
  675. * Return the position of the start of the last line. If len is 0, return -1.
  676. */
  677. static ssize_t last_line(const char *buf, size_t len)
  678. {
  679. ssize_t i;
  680. if (len == 0)
  681. return -1;
  682. if (len == 1)
  683. return 0;
  684. /*
  685. * Skip the last character (in addition to the null terminator),
  686. * because if the last character is a newline, it is considered as part
  687. * of the last line anyway.
  688. */
  689. i = len - 2;
  690. for (; i >= 0; i--) {
  691. if (buf[i] == '\n')
  692. return i + 1;
  693. }
  694. return 0;
  695. }
  696. /*
  697. * Return the position of the start of the patch or the length of str if there
  698. * is no patch in the message.
  699. */
  700. static size_t find_patch_start(const char *str)
  701. {
  702. const char *s;
  703. for (s = str; *s; s = next_line(s)) {
  704. const char *v;
  705. if (skip_prefix(s, "---", &v) && isspace(*v))
  706. return s - str;
  707. }
  708. return s - str;
  709. }
  710. /*
  711. * Return the position of the first trailer line or len if there are no
  712. * trailers.
  713. */
  714. static size_t find_trailer_start(const char *buf, size_t len)
  715. {
  716. const char *s;
  717. ssize_t end_of_title, l;
  718. int only_spaces = 1;
  719. int recognized_prefix = 0, trailer_lines = 0, non_trailer_lines = 0;
  720. /*
  721. * Number of possible continuation lines encountered. This will be
  722. * reset to 0 if we encounter a trailer (since those lines are to be
  723. * considered continuations of that trailer), and added to
  724. * non_trailer_lines if we encounter a non-trailer (since those lines
  725. * are to be considered non-trailers).
  726. */
  727. int possible_continuation_lines = 0;
  728. /* The first paragraph is the title and cannot be trailers */
  729. for (s = buf; s < buf + len; s = next_line(s)) {
  730. if (s[0] == comment_line_char)
  731. continue;
  732. if (is_blank_line(s))
  733. break;
  734. }
  735. end_of_title = s - buf;
  736. /*
  737. * Get the start of the trailers by looking starting from the end for a
  738. * blank line before a set of non-blank lines that (i) are all
  739. * trailers, or (ii) contains at least one Git-generated trailer and
  740. * consists of at least 25% trailers.
  741. */
  742. for (l = last_line(buf, len);
  743. l >= end_of_title;
  744. l = last_line(buf, l)) {
  745. const char *bol = buf + l;
  746. const char **p;
  747. ssize_t separator_pos;
  748. if (bol[0] == comment_line_char) {
  749. non_trailer_lines += possible_continuation_lines;
  750. possible_continuation_lines = 0;
  751. continue;
  752. }
  753. if (is_blank_line(bol)) {
  754. if (only_spaces)
  755. continue;
  756. non_trailer_lines += possible_continuation_lines;
  757. if (recognized_prefix &&
  758. trailer_lines * 3 >= non_trailer_lines)
  759. return next_line(bol) - buf;
  760. else if (trailer_lines && !non_trailer_lines)
  761. return next_line(bol) - buf;
  762. return len;
  763. }
  764. only_spaces = 0;
  765. for (p = git_generated_prefixes; *p; p++) {
  766. if (starts_with(bol, *p)) {
  767. trailer_lines++;
  768. possible_continuation_lines = 0;
  769. recognized_prefix = 1;
  770. goto continue_outer_loop;
  771. }
  772. }
  773. separator_pos = find_separator(bol, separators);
  774. if (separator_pos >= 1 && !isspace(bol[0])) {
  775. struct list_head *pos;
  776. trailer_lines++;
  777. possible_continuation_lines = 0;
  778. if (recognized_prefix)
  779. continue;
  780. list_for_each(pos, &conf_head) {
  781. struct arg_item *item;
  782. item = list_entry(pos, struct arg_item, list);
  783. if (token_matches_item(bol, item,
  784. separator_pos)) {
  785. recognized_prefix = 1;
  786. break;
  787. }
  788. }
  789. } else if (isspace(bol[0]))
  790. possible_continuation_lines++;
  791. else {
  792. non_trailer_lines++;
  793. non_trailer_lines += possible_continuation_lines;
  794. possible_continuation_lines = 0;
  795. }
  796. continue_outer_loop:
  797. ;
  798. }
  799. return len;
  800. }
  801. /* Return the position of the end of the trailers. */
  802. static size_t find_trailer_end(const char *buf, size_t len)
  803. {
  804. return len - ignore_non_trailer(buf, len);
  805. }
  806. static int ends_with_blank_line(const char *buf, size_t len)
  807. {
  808. ssize_t ll = last_line(buf, len);
  809. if (ll < 0)
  810. return 0;
  811. return is_blank_line(buf + ll);
  812. }
  813. static void unfold_value(struct strbuf *val)
  814. {
  815. struct strbuf out = STRBUF_INIT;
  816. size_t i;
  817. strbuf_grow(&out, val->len);
  818. i = 0;
  819. while (i < val->len) {
  820. char c = val->buf[i++];
  821. if (c == '\n') {
  822. /* Collapse continuation down to a single space. */
  823. while (i < val->len && isspace(val->buf[i]))
  824. i++;
  825. strbuf_addch(&out, ' ');
  826. } else {
  827. strbuf_addch(&out, c);
  828. }
  829. }
  830. /* Empty lines may have left us with whitespace cruft at the edges */
  831. strbuf_trim(&out);
  832. /* output goes back to val as if we modified it in-place */
  833. strbuf_swap(&out, val);
  834. strbuf_release(&out);
  835. }
  836. static size_t process_input_file(FILE *outfile,
  837. const char *str,
  838. struct list_head *head,
  839. const struct process_trailer_options *opts)
  840. {
  841. struct trailer_info info;
  842. struct strbuf tok = STRBUF_INIT;
  843. struct strbuf val = STRBUF_INIT;
  844. size_t i;
  845. trailer_info_get(&info, str, opts);
  846. /* Print lines before the trailers as is */
  847. if (!opts->only_trailers)
  848. fwrite(str, 1, info.trailer_start - str, outfile);
  849. if (!opts->only_trailers && !info.blank_line_before_trailer)
  850. fprintf(outfile, "\n");
  851. for (i = 0; i < info.trailer_nr; i++) {
  852. int separator_pos;
  853. char *trailer = info.trailers[i];
  854. if (trailer[0] == comment_line_char)
  855. continue;
  856. separator_pos = find_separator(trailer, separators);
  857. if (separator_pos >= 1) {
  858. parse_trailer(&tok, &val, NULL, trailer,
  859. separator_pos);
  860. if (opts->unfold)
  861. unfold_value(&val);
  862. add_trailer_item(head,
  863. strbuf_detach(&tok, NULL),
  864. strbuf_detach(&val, NULL));
  865. } else if (!opts->only_trailers) {
  866. strbuf_addstr(&val, trailer);
  867. strbuf_strip_suffix(&val, "\n");
  868. add_trailer_item(head,
  869. NULL,
  870. strbuf_detach(&val, NULL));
  871. }
  872. }
  873. trailer_info_release(&info);
  874. return info.trailer_end - str;
  875. }
  876. static void free_all(struct list_head *head)
  877. {
  878. struct list_head *pos, *p;
  879. list_for_each_safe(pos, p, head) {
  880. list_del(pos);
  881. free_trailer_item(list_entry(pos, struct trailer_item, list));
  882. }
  883. }
  884. static struct tempfile *trailers_tempfile;
  885. static FILE *create_in_place_tempfile(const char *file)
  886. {
  887. struct stat st;
  888. struct strbuf filename_template = STRBUF_INIT;
  889. const char *tail;
  890. FILE *outfile;
  891. if (stat(file, &st))
  892. die_errno(_("could not stat %s"), file);
  893. if (!S_ISREG(st.st_mode))
  894. die(_("file %s is not a regular file"), file);
  895. if (!(st.st_mode & S_IWUSR))
  896. die(_("file %s is not writable by user"), file);
  897. /* Create temporary file in the same directory as the original */
  898. tail = strrchr(file, '/');
  899. if (tail != NULL)
  900. strbuf_add(&filename_template, file, tail - file + 1);
  901. strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
  902. trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);
  903. strbuf_release(&filename_template);
  904. outfile = fdopen_tempfile(trailers_tempfile, "w");
  905. if (!outfile)
  906. die_errno(_("could not open temporary file"));
  907. return outfile;
  908. }
  909. void process_trailers(const char *file,
  910. const struct process_trailer_options *opts,
  911. struct list_head *new_trailer_head)
  912. {
  913. LIST_HEAD(head);
  914. struct strbuf sb = STRBUF_INIT;
  915. size_t trailer_end;
  916. FILE *outfile = stdout;
  917. ensure_configured();
  918. read_input_file(&sb, file);
  919. if (opts->in_place)
  920. outfile = create_in_place_tempfile(file);
  921. /* Print the lines before the trailers */
  922. trailer_end = process_input_file(outfile, sb.buf, &head, opts);
  923. if (!opts->only_input) {
  924. LIST_HEAD(arg_head);
  925. process_command_line_args(&arg_head, new_trailer_head);
  926. process_trailers_lists(&head, &arg_head);
  927. }
  928. print_all(outfile, &head, opts);
  929. free_all(&head);
  930. /* Print the lines after the trailers as is */
  931. if (!opts->only_trailers)
  932. fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
  933. if (opts->in_place)
  934. if (rename_tempfile(&trailers_tempfile, file))
  935. die_errno(_("could not rename temporary file to %s"), file);
  936. strbuf_release(&sb);
  937. }
  938. void trailer_info_get(struct trailer_info *info, const char *str,
  939. const struct process_trailer_options *opts)
  940. {
  941. int patch_start, trailer_end, trailer_start;
  942. struct strbuf **trailer_lines, **ptr;
  943. char **trailer_strings = NULL;
  944. size_t nr = 0, alloc = 0;
  945. char **last = NULL;
  946. ensure_configured();
  947. if (opts->no_divider)
  948. patch_start = strlen(str);
  949. else
  950. patch_start = find_patch_start(str);
  951. trailer_end = find_trailer_end(str, patch_start);
  952. trailer_start = find_trailer_start(str, trailer_end);
  953. trailer_lines = strbuf_split_buf(str + trailer_start,
  954. trailer_end - trailer_start,
  955. '\n',
  956. 0);
  957. for (ptr = trailer_lines; *ptr; ptr++) {
  958. if (last && isspace((*ptr)->buf[0])) {
  959. struct strbuf sb = STRBUF_INIT;
  960. strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
  961. strbuf_addbuf(&sb, *ptr);
  962. *last = strbuf_detach(&sb, NULL);
  963. continue;
  964. }
  965. ALLOC_GROW(trailer_strings, nr + 1, alloc);
  966. trailer_strings[nr] = strbuf_detach(*ptr, NULL);
  967. last = find_separator(trailer_strings[nr], separators) >= 1
  968. ? &trailer_strings[nr]
  969. : NULL;
  970. nr++;
  971. }
  972. strbuf_list_free(trailer_lines);
  973. info->blank_line_before_trailer = ends_with_blank_line(str,
  974. trailer_start);
  975. info->trailer_start = str + trailer_start;
  976. info->trailer_end = str + trailer_end;
  977. info->trailers = trailer_strings;
  978. info->trailer_nr = nr;
  979. }
  980. void trailer_info_release(struct trailer_info *info)
  981. {
  982. size_t i;
  983. for (i = 0; i < info->trailer_nr; i++)
  984. free(info->trailers[i]);
  985. free(info->trailers);
  986. }
  987. static void format_trailer_info(struct strbuf *out,
  988. const struct trailer_info *info,
  989. const struct process_trailer_options *opts)
  990. {
  991. size_t origlen = out->len;
  992. size_t i;
  993. /* If we want the whole block untouched, we can take the fast path. */
  994. if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator) {
  995. strbuf_add(out, info->trailer_start,
  996. info->trailer_end - info->trailer_start);
  997. return;
  998. }
  999. for (i = 0; i < info->trailer_nr; i++) {
  1000. char *trailer = info->trailers[i];
  1001. ssize_t separator_pos = find_separator(trailer, separators);
  1002. if (separator_pos >= 1) {
  1003. struct strbuf tok = STRBUF_INIT;
  1004. struct strbuf val = STRBUF_INIT;
  1005. parse_trailer(&tok, &val, NULL, trailer, separator_pos);
  1006. if (!opts->filter || opts->filter(&tok, opts->filter_data)) {
  1007. if (opts->unfold)
  1008. unfold_value(&val);
  1009. if (opts->separator && out->len != origlen)
  1010. strbuf_addbuf(out, opts->separator);
  1011. if (!opts->value_only)
  1012. strbuf_addf(out, "%s: ", tok.buf);
  1013. strbuf_addbuf(out, &val);
  1014. if (!opts->separator)
  1015. strbuf_addch(out, '\n');
  1016. }
  1017. strbuf_release(&tok);
  1018. strbuf_release(&val);
  1019. } else if (!opts->only_trailers) {
  1020. if (opts->separator && out->len != origlen) {
  1021. strbuf_addbuf(out, opts->separator);
  1022. }
  1023. strbuf_addstr(out, trailer);
  1024. if (opts->separator) {
  1025. strbuf_rtrim(out);
  1026. }
  1027. }
  1028. }
  1029. }
  1030. void format_trailers_from_commit(struct strbuf *out, const char *msg,
  1031. const struct process_trailer_options *opts)
  1032. {
  1033. struct trailer_info info;
  1034. trailer_info_get(&info, msg, opts);
  1035. format_trailer_info(out, &info, opts);
  1036. trailer_info_release(&info);
  1037. }