am: make direct call to mailinfo

And finally the endgame. Instead of spawning "git mailinfo" via the run_command() API the same number of times as there are incoming patches, make direct internal call to the libified mailinfo() from "git am" to reduce the spawning overhead, which would matter on some platforms. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Oct 14, 2015 at 17:45 UTC 4b98bae2cbc6bf49a5fd7bab330191d002e6e2fc
1 file changed +23 -19
builtin/am.c
+23 -19
@@ -27,6 +27,7 @@
27 #include "notes-utils.h"
28 #include "rerere.h"
29 #include "prompt.h"
30 +#include "mailinfo.h"
31
32 /**
33 * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -1258,58 +1259,61 @@ static void am_append_signoff(struct am_state *state)
1259 static int parse_mail(struct am_state *state, const char *mail)
1260 {
1261 FILE *fp;
1261 - struct child_process cp = CHILD_PROCESS_INIT;
1262 struct strbuf sb = STRBUF_INIT;
1263 struct strbuf msg = STRBUF_INIT;
1264 struct strbuf author_name = STRBUF_INIT;
1265 struct strbuf author_date = STRBUF_INIT;
1266 struct strbuf author_email = STRBUF_INIT;
1267 int ret = 0;
1268 + struct mailinfo mi;
1269
1269 - cp.git_cmd = 1;
1270 - cp.in = xopen(mail, O_RDONLY, 0);
1271 - cp.out = xopen(am_path(state, "info"), O_WRONLY | O_CREAT, 0777);
1270 + setup_mailinfo(&mi);
1271
1273 - argv_array_push(&cp.args, "mailinfo");
1274 - argv_array_push(&cp.args, state->utf8 ? "-u" : "-n");
1272 + if (state->utf8)
1273 + mi.metainfo_charset = get_commit_output_encoding();
1274 + else
1275 + mi.metainfo_charset = NULL;
1276
1277 switch (state->keep) {
1278 case KEEP_FALSE:
1279 break;
1280 case KEEP_TRUE:
1280 - argv_array_push(&cp.args, "-k");
1281 + mi.keep_subject = 1;
1282 break;
1283 case KEEP_NON_PATCH:
1283 - argv_array_push(&cp.args, "-b");
1284 + mi.keep_non_patch_brackets_in_subject = 1;
1285 break;
1286 default:
1287 die("BUG: invalid value for state->keep");
1288 }
1289
1290 if (state->message_id)
1290 - argv_array_push(&cp.args, "-m");
1291 + mi.add_message_id = 1;
1292
1293 switch (state->scissors) {
1294 case SCISSORS_UNSET:
1295 break;
1296 case SCISSORS_FALSE:
1296 - argv_array_push(&cp.args, "--no-scissors");
1297 + mi.use_scissors = 0;
1298 break;
1299 case SCISSORS_TRUE:
1299 - argv_array_push(&cp.args, "--scissors");
1300 + mi.use_scissors = 1;
1301 break;
1302 default:
1303 die("BUG: invalid value for state->scissors");
1304 }
1305
1305 - argv_array_push(&cp.args, am_path(state, "msg"));
1306 - argv_array_push(&cp.args, am_path(state, "patch"));
1307 -
1308 - if (run_command(&cp) < 0)
1306 + mi.input = fopen(mail, "r");
1307 + if (!mi.input)
1308 + die("could not open input");
1309 + mi.output = fopen(am_path(state, "info"), "w");
1310 + if (!mi.output)
1311 + die("could not open output 'info'");
1312 + if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
1313 die("could not parse patch");
1314
1311 - close(cp.in);
1312 - close(cp.out);
1315 + fclose(mi.input);
1316 + fclose(mi.output);
1317
1318 /* Extract message and author information */
1319 fp = xfopen(am_path(state, "info"), "r");
@@ -1341,8 +1345,7 @@ static int parse_mail(struct am_state *state, const char *mail)
1345 }
1346
1347 strbuf_addstr(&msg, "\n\n");
1344 - if (strbuf_read_file(&msg, am_path(state, "msg"), 0) < 0)
1345 - die_errno(_("could not read '%s'"), am_path(state, "msg"));
1348 + strbuf_addbuf(&msg, &mi.log_message);
1349 stripspace(&msg, 0);
1350
1351 if (state->signoff)
@@ -1366,6 +1369,7 @@ finish:
1369 strbuf_release(&author_email);
1370 strbuf_release(&author_name);
1371 strbuf_release(&sb);
1372 + clear_mailinfo(&mi);
1373 return ret;
1374 }
1375