trailer.c 30 KB

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