X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=convert.c;h=4534e2c2b003998a590637fc43c0549ff23f71b2;hb=a12c6b0149e3dadd0701dac4fd0ba2463d251650;hp=c9ab54ffd2f84b0c501a6582c3837371efd34464;hpb=d5cb31a56aad167360ec60eb5ea2d01f5337488e;p=git.git diff --git a/convert.c b/convert.c index c9ab54ffd..4534e2c2b 100644 --- a/convert.c +++ b/convert.c @@ -2,6 +2,7 @@ #include "attr.h" #include "run-command.h" #include "quote.h" +#include "sigchain.h" /* * convert.c - convert a file when checking it out and checking it in. @@ -195,9 +196,17 @@ static int crlf_to_git(const char *path, const char *src, size_t len, char *dst; if (crlf_action == CRLF_BINARY || - (crlf_action == CRLF_GUESS && auto_crlf == AUTO_CRLF_FALSE) || !len) + (crlf_action == CRLF_GUESS && auto_crlf == AUTO_CRLF_FALSE) || + (src && !len)) return 0; + /* + * If we are doing a dry-run and have no source buffer, there is + * nothing to analyze; we must assume we would convert. + */ + if (!buf && !src) + return 1; + gather_stats(src, len, &stats); if (crlf_action == CRLF_AUTO || crlf_action == CRLF_GUESS) { @@ -231,6 +240,13 @@ static int crlf_to_git(const char *path, const char *src, size_t len, if (!stats.cr) return 0; + /* + * At this point all of our source analysis is done, and we are sure we + * would convert. If we are in dry-run mode, we can give an answer. + */ + if (!buf) + return 1; + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -360,12 +376,16 @@ static int filter_buffer(int in, int out, void *data) if (start_command(&child_process)) return error("cannot fork to run external filter %s", params->cmd); + sigchain_push(SIGPIPE, SIG_IGN); + write_err = (write_in_full(child_process.in, params->src, params->size) < 0); if (close(child_process.in)) write_err = 1; if (write_err) error("cannot feed the input to external filter %s", params->cmd); + sigchain_pop(SIGPIPE); + status = finish_command(&child_process); if (status) error("external filter %s failed %d", params->cmd, status); @@ -391,6 +411,9 @@ static int apply_filter(const char *path, const char *src, size_t len, if (!cmd) return 0; + if (!dst) + return 1; + memset(&async, 0, sizeof(async)); async.proc = filter_buffer; async.data = ¶ms; @@ -522,9 +545,12 @@ static int ident_to_git(const char *path, const char *src, size_t len, { char *dst, *dollar; - if (!ident || !count_ident(src, len)) + if (!ident || (src && !count_ident(src, len))) return 0; + if (!buf) + return 1; + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -754,13 +780,13 @@ int convert_to_git(const char *path, const char *src, size_t len, filter = ca.drv->clean; ret |= apply_filter(path, src, len, dst, filter); - if (ret) { + if (ret && dst) { src = dst->buf; len = dst->len; } ca.crlf_action = input_crlf_action(ca.crlf_action, ca.eol_attr); ret |= crlf_to_git(path, src, len, dst, ca.crlf_action, checksafe); - if (ret) { + if (ret && dst) { src = dst->buf; len = dst->len; } @@ -879,7 +905,8 @@ int is_null_stream_filter(struct stream_filter *filter) struct lf_to_crlf_filter { struct stream_filter filter; - unsigned want_lf:1; + unsigned has_held:1; + char held; }; static int lf_to_crlf_filter_fn(struct stream_filter *filter, @@ -889,10 +916,14 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter, size_t count, o = 0; struct lf_to_crlf_filter *lf_to_crlf = (struct lf_to_crlf_filter *)filter; - /* Output a pending LF if we need to */ - if (lf_to_crlf->want_lf) { - output[o++] = '\n'; - lf_to_crlf->want_lf = 0; + /* + * We may be holding onto the CR to see if it is followed by a + * LF, in which case we would need to go to the main loop. + * Otherwise, just emit it to the output stream. + */ + if (lf_to_crlf->has_held && (lf_to_crlf->held != '\r' || !input)) { + output[o++] = lf_to_crlf->held; + lf_to_crlf->has_held = 0; } /* We are told to drain */ @@ -902,22 +933,57 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter, } count = *isize_p; - if (count) { + if (count || lf_to_crlf->has_held) { size_t i; + int was_cr = 0; + + if (lf_to_crlf->has_held) { + was_cr = 1; + lf_to_crlf->has_held = 0; + } + for (i = 0; o < *osize_p && i < count; i++) { char ch = input[i]; + if (ch == '\n') { output[o++] = '\r'; - if (o >= *osize_p) { - lf_to_crlf->want_lf = 1; - continue; /* We need to increase i */ - } + } else if (was_cr) { + /* + * Previous round saw CR and it is not followed + * by a LF; emit the CR before processing the + * current character. + */ + output[o++] = '\r'; } + + /* + * We may have consumed the last output slot, + * in which case we need to break out of this + * loop; hold the current character before + * returning. + */ + if (*osize_p <= o) { + lf_to_crlf->has_held = 1; + lf_to_crlf->held = ch; + continue; /* break but increment i */ + } + + if (ch == '\r') { + was_cr = 1; + continue; + } + + was_cr = 0; output[o++] = ch; } *osize_p -= o; *isize_p -= i; + + if (!lf_to_crlf->has_held && was_cr) { + lf_to_crlf->has_held = 1; + lf_to_crlf->held = '\r'; + } } return 0; }