convert: refactor capabilities negotiation

The code to negotiate long running filter capabilities was very repetitive for new capabilities. Replace the repetitive conditional statements with a table-driven approach. This is useful for the subsequent patch 'convert: add "status=delayed" to filter process protocol'. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Lars Schneider <larsxschneider@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lars Schneider committed Jun 30, 2017 at 22:41 UTC 1514c8edd62d96006cd1de31e906ed5798dd4681
1 file changed +27 -12
convert.c
+27 -12
@@ -507,7 +507,7 @@ static struct hashmap subprocess_map;
507
508 static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
509 {
510 - int err;
510 + int err, i;
511 struct cmd2process *entry = (struct cmd2process *)subprocess;
512 struct string_list cap_list = STRING_LIST_INIT_NODUP;
513 char *cap_buf;
@@ -515,6 +515,14 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
515 struct child_process *process = &subprocess->process;
516 const char *cmd = subprocess->cmd;
517
518 + static const struct {
519 + const char *name;
520 + unsigned int cap;
521 + } known_caps[] = {
522 + { "clean", CAP_CLEAN },
523 + { "smudge", CAP_SMUDGE },
524 + };
525 +
526 sigchain_push(SIGPIPE, SIG_IGN);
527
528 err = packet_writel(process->in, "git-filter-client", "version=2", NULL);
@@ -533,7 +541,15 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
541 if (err)
542 goto done;
543
536 - err = packet_writel(process->in, "capability=clean", "capability=smudge", NULL);
544 + for (i = 0; i < ARRAY_SIZE(known_caps); ++i) {
545 + err = packet_write_fmt_gently(
546 + process->in, "capability=%s\n", known_caps[i].name);
547 + if (err)
548 + goto done;
549 + }
550 + err = packet_flush_gently(process->in);
551 + if (err)
552 + goto done;
553
554 for (;;) {
555 cap_buf = packet_read_line(process->out, NULL);
@@ -545,16 +561,15 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
561 continue;
562
563 cap_name = cap_list.items[1].string;
548 - if (!strcmp(cap_name, "clean")) {
549 - entry->supported_capabilities |= CAP_CLEAN;
550 - } else if (!strcmp(cap_name, "smudge")) {
551 - entry->supported_capabilities |= CAP_SMUDGE;
552 - } else {
553 - warning(
554 - "external filter '%s' requested unsupported filter capability '%s'",
555 - cmd, cap_name
556 - );
557 - }
564 + i = ARRAY_SIZE(known_caps) - 1;
565 + while (i >= 0 && strcmp(cap_name, known_caps[i].name))
566 + i--;
567 +
568 + if (i >= 0)
569 + entry->supported_capabilities |= known_caps[i].cap;
570 + else
571 + warning("external filter '%s' requested unsupported filter capability '%s'",
572 + cmd, cap_name);
573
574 string_list_clear(&cap_list, 0);
575 }