Merge branch 'hn/string-list-doc'
[gitweb.git] / convert.c
index dbdbb24e4d37e1f4d4db8e479d48125c90a071a4..20d7ab67bdf889feb255e01a9b18cf4efa6107a3 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -423,8 +423,10 @@ static int filter_buffer_or_fd(int in, int out, void *data)
        child_process.in = -1;
        child_process.out = out;
 
-       if (start_command(&child_process))
+       if (start_command(&child_process)) {
+               strbuf_release(&cmd);
                return error("cannot fork to run external filter '%s'", params->cmd);
+       }
 
        sigchain_push(SIGPIPE, SIG_IGN);
 
@@ -513,78 +515,17 @@ static struct hashmap subprocess_map;
 
 static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
 {
-       int err, i;
-       struct cmd2process *entry = (struct cmd2process *)subprocess;
-       struct string_list cap_list = STRING_LIST_INIT_NODUP;
-       char *cap_buf;
-       const char *cap_name;
-       struct child_process *process = &subprocess->process;
-       const char *cmd = subprocess->cmd;
-
-       static const struct {
-               const char *name;
-               unsigned int cap;
-       } known_caps[] = {
+       static int versions[] = {2, 0};
+       static struct subprocess_capability capabilities[] = {
                { "clean",  CAP_CLEAN  },
                { "smudge", CAP_SMUDGE },
                { "delay",  CAP_DELAY  },
+               { NULL, 0 }
        };
-
-       sigchain_push(SIGPIPE, SIG_IGN);
-
-       err = packet_writel(process->in, "git-filter-client", "version=2", NULL);
-       if (err)
-               goto done;
-
-       err = strcmp(packet_read_line(process->out, NULL), "git-filter-server");
-       if (err) {
-               error("external filter '%s' does not support filter protocol version 2", cmd);
-               goto done;
-       }
-       err = strcmp(packet_read_line(process->out, NULL), "version=2");
-       if (err)
-               goto done;
-       err = packet_read_line(process->out, NULL) != NULL;
-       if (err)
-               goto done;
-
-       for (i = 0; i < ARRAY_SIZE(known_caps); ++i) {
-               err = packet_write_fmt_gently(
-                       process->in, "capability=%s\n", known_caps[i].name);
-               if (err)
-                       goto done;
-       }
-       err = packet_flush_gently(process->in);
-       if (err)
-               goto done;
-
-       for (;;) {
-               cap_buf = packet_read_line(process->out, NULL);
-               if (!cap_buf)
-                       break;
-               string_list_split_in_place(&cap_list, cap_buf, '=', 1);
-
-               if (cap_list.nr != 2 || strcmp(cap_list.items[0].string, "capability"))
-                       continue;
-
-               cap_name = cap_list.items[1].string;
-               i = ARRAY_SIZE(known_caps) - 1;
-               while (i >= 0 && strcmp(cap_name, known_caps[i].name))
-                       i--;
-
-               if (i >= 0)
-                       entry->supported_capabilities |= known_caps[i].cap;
-               else
-                       warning("external filter '%s' requested unsupported filter capability '%s'",
-                       cmd, cap_name);
-
-               string_list_clear(&cap_list, 0);
-       }
-
-done:
-       sigchain_pop(SIGPIPE);
-
-       return err;
+       struct cmd2process *entry = (struct cmd2process *)subprocess;
+       return subprocess_handshake(subprocess, "git-filter", versions, NULL,
+                                   capabilities,
+                                   &entry->supported_capabilities);
 }
 
 static void handle_filter_error(const struct strbuf *filter_status,
@@ -1101,7 +1042,6 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                ca->crlf_action = git_path_check_crlf(ccheck + 4);
                if (ca->crlf_action == CRLF_UNDEFINED)
                        ca->crlf_action = git_path_check_crlf(ccheck + 0);
-               ca->attr_action = ca->crlf_action;
                ca->ident = git_path_check_ident(ccheck + 1);
                ca->drv = git_path_check_convert(ccheck + 2);
                if (ca->crlf_action != CRLF_BINARY) {
@@ -1115,12 +1055,14 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                        else if (eol_attr == EOL_CRLF)
                                ca->crlf_action = CRLF_TEXT_CRLF;
                }
-               ca->attr_action = ca->crlf_action;
        } else {
                ca->drv = NULL;
                ca->crlf_action = CRLF_UNDEFINED;
                ca->ident = 0;
        }
+
+       /* Save attr and make a decision for action */
+       ca->attr_action = ca->crlf_action;
        if (ca->crlf_action == CRLF_TEXT)
                ca->crlf_action = text_eol_is_crlf() ? CRLF_TEXT_CRLF : CRLF_TEXT_INPUT;
        if (ca->crlf_action == CRLF_UNDEFINED && auto_crlf == AUTO_CRLF_FALSE)
@@ -1193,10 +1135,12 @@ int convert_to_git(const struct index_state *istate,
                src = dst->buf;
                len = dst->len;
        }
-       ret |= crlf_to_git(istate, path, src, len, dst, ca.crlf_action, checksafe);
-       if (ret && dst) {
-               src = dst->buf;
-               len = dst->len;
+       if (checksafe != SAFE_CRLF_KEEP_CRLF) {
+               ret |= crlf_to_git(istate, path, src, len, dst, ca.crlf_action, checksafe);
+               if (ret && dst) {
+                       src = dst->buf;
+                       len = dst->len;
+               }
        }
        return ret | ident_to_git(path, src, len, dst, ca.ident);
 }
@@ -1601,8 +1545,9 @@ static int ident_filter_fn(struct stream_filter *filter,
                switch (ident->state) {
                default:
                        strbuf_add(&ident->left, head, ident->state);
+                       /* fallthrough */
                case IDENT_SKIPPING:
-                       /* fallthru */
+                       /* fallthrough */
                case IDENT_DRAINING:
                        ident_drain(ident, &output, osize_p);
                }