X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=convert.c;h=d8c94cb3edeceff7a79b2f5e6ba7cad250e6b301;hb=bcbe5a515e837873f24dc9a764fa31e3ade45bb5;hp=4df75595b1f3e689a9685039c372ffb4c8688291;hpb=c4316674c48708ca62876470c615101ab8fee2e0;p=git.git diff --git a/convert.c b/convert.c index 4df75595b..d8c94cb3e 100644 --- a/convert.c +++ b/convert.c @@ -17,8 +17,8 @@ #define CRLF_INPUT 2 struct text_stat { - /* CR, LF and CRLF counts */ - unsigned cr, lf, crlf; + /* NUL, CR, LF and CRLF counts */ + unsigned nul, cr, lf, crlf; /* These are just approximations! */ unsigned printable, nonprintable; @@ -51,6 +51,9 @@ static void gather_stats(const char *buf, unsigned long size, struct text_stat * case '\b': case '\t': case '\033': case '\014': stats->printable++; break; + case 0: + stats->nul++; + /* fall through */ default: stats->nonprintable++; } @@ -66,6 +69,8 @@ static void gather_stats(const char *buf, unsigned long size, struct text_stat * static int is_binary(unsigned long size, struct text_stat *stats) { + if (stats->nul) + return 1; if ((stats->printable >> 7) < stats->nonprintable) return 1; /* @@ -80,8 +85,39 @@ static int is_binary(unsigned long size, struct text_stat *stats) return 0; } +static void check_safe_crlf(const char *path, int action, + struct text_stat *stats, enum safe_crlf checksafe) +{ + if (!checksafe) + return; + + if (action == CRLF_INPUT || auto_crlf <= 0) { + /* + * CRLFs would not be restored by checkout: + * check if we'd remove CRLFs + */ + if (stats->crlf) { + if (checksafe == SAFE_CRLF_WARN) + warning("CRLF will be replaced by LF in %s.", path); + else /* i.e. SAFE_CRLF_FAIL */ + die("CRLF would be replaced by LF in %s.", path); + } + } else if (auto_crlf > 0) { + /* + * CRLFs would be added by checkout: + * check if we have "naked" LFs + */ + if (stats->lf != stats->crlf) { + if (checksafe == SAFE_CRLF_WARN) + warning("LF will be replaced by CRLF in %s", path); + else /* i.e. SAFE_CRLF_FAIL */ + die("LF would be replaced by CRLF in %s", path); + } + } +} + static int crlf_to_git(const char *path, const char *src, size_t len, - struct strbuf *buf, int action) + struct strbuf *buf, int action, enum safe_crlf checksafe) { struct text_stat stats; char *dst; @@ -90,9 +126,6 @@ static int crlf_to_git(const char *path, const char *src, size_t len, return 0; gather_stats(src, len, &stats); - /* No CR? Nothing to convert, regardless. */ - if (!stats.cr) - return 0; if (action == CRLF_GUESS) { /* @@ -110,6 +143,12 @@ static int crlf_to_git(const char *path, const char *src, size_t len, return 0; } + check_safe_crlf(path, action, &stats, checksafe); + + /* Optimization: No CR? Nothing to convert, regardless. */ + if (!stats.cr) + return 0; + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -321,14 +360,14 @@ static int read_convert_config(const char *var, const char *value) if (!strcmp("smudge", ep)) { if (!value) - return error("%s: lacks value", var); + return config_error_nonbool(var); drv->smudge = strdup(value); return 0; } if (!strcmp("clean", ep)) { if (!value) - return error("%s: lacks value", var); + return config_error_nonbool(var); drv->clean = strdup(value); return 0; } @@ -531,7 +570,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check) return !!ATTR_TRUE(value); } -int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst) +int convert_to_git(const char *path, const char *src, size_t len, + struct strbuf *dst, enum safe_crlf checksafe) { struct git_attr_check check[3]; int crlf = CRLF_GUESS; @@ -553,7 +593,7 @@ int convert_to_git(const char *path, const char *src, size_t len, struct strbuf src = dst->buf; len = dst->len; } - ret |= crlf_to_git(path, src, len, dst, crlf); + ret |= crlf_to_git(path, src, len, dst, crlf, checksafe); if (ret) { src = dst->buf; len = dst->len;