int crlf_action;
int eol;
int auto_crlf;
+ int safe_crlf;
};
struct crlf_filter {
if (!S_ISREG(entry->mode)) /* don't crlf filter non-blobs */
return true;
- if (git_blob_lookup(&blob, repo, &entry->oid) < 0)
+ if (git_blob_lookup(&blob, repo, &entry->id) < 0)
return false;
blobcontent = git_blob_rawcontent(blob);
if (ca->crlf_action == GIT_CRLF_AUTO || ca->crlf_action == GIT_CRLF_GUESS) {
git_buf_text_stats stats;
- /* Check heuristics for binary vs text... */
+ /* Check heuristics for binary vs text - returns true if binary */
if (git_buf_text_gather_stats(&stats, from, false))
- return -1;
+ return GIT_PASSTHROUGH;
+
+ /* If there are no CR characters to filter out, then just pass */
+ if (!stats.cr)
+ return GIT_PASSTHROUGH;
+
+ /* If safecrlf is enabled, sanity-check the result. */
+ if (stats.cr != stats.crlf || stats.lf != stats.crlf) {
+ switch (ca->safe_crlf) {
+ case GIT_SAFE_CRLF_FAIL:
+ giterr_set(
+ GITERR_FILTER, "LF would be replaced by CRLF in '%s'",
+ git_filter_source_path(src));
+ return -1;
+ case GIT_SAFE_CRLF_WARN:
+ /* TODO: issue warning when warning API is available */;
+ break;
+ default:
+ break;
+ }
+ }
/*
* We're currently not going to even try to convert stuff
if (!workdir_ending)
return -1;
- if (!strcmp("\n", workdir_ending)) {
- if (ca->crlf_action == GIT_CRLF_GUESS && ca->auto_crlf)
- return GIT_PASSTHROUGH;
-
- if (git_buf_find(from, '\r') < 0)
- return GIT_PASSTHROUGH;
-
- if (git_buf_text_crlf_to_lf(to, from) < 0)
- return -1;
- } else {
- /* only other supported option is lf->crlf conversion */
- assert(!strcmp("\r\n", workdir_ending));
-
- if (git_buf_text_lf_to_crlf(to, from) < 0)
- return -1;
- }
+ /* only LF->CRLF conversion is supported, do nothing on LF platforms */
+ if (strcmp(workdir_ending, "\r\n") != 0)
+ return GIT_PASSTHROUGH;
- return 0;
+ return git_buf_text_lf_to_crlf(to, from);
}
static int crlf_check(
if (ca.crlf_action == GIT_CRLF_BINARY)
return GIT_PASSTHROUGH;
- if (ca.crlf_action == GIT_CRLF_GUESS) {
+ if (ca.crlf_action == GIT_CRLF_GUESS ||
+ (ca.crlf_action == GIT_CRLF_AUTO &&
+ git_filter_source_mode(src) == GIT_FILTER_SMUDGE)) {
+
error = git_repository__cvar(
&ca.auto_crlf, git_filter_source_repo(src), GIT_CVAR_AUTO_CRLF);
if (error < 0)
return error;
- if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE)
+ if (ca.crlf_action == GIT_CRLF_GUESS &&
+ ca.auto_crlf == GIT_AUTO_CRLF_FALSE)
+ return GIT_PASSTHROUGH;
+
+ if (ca.auto_crlf == GIT_AUTO_CRLF_INPUT &&
+ git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
return GIT_PASSTHROUGH;
}
+ if (git_filter_source_mode(src) == GIT_FILTER_CLEAN) {
+ error = git_repository__cvar(
+ &ca.safe_crlf, git_filter_source_repo(src), GIT_CVAR_SAFE_CRLF);
+ if (error < 0)
+ return error;
+
+ /* downgrade FAIL to WARN if ALLOW_UNSAFE option is used */
+ if ((git_filter_source_options(src) & GIT_FILTER_OPT_ALLOW_UNSAFE) &&
+ ca.safe_crlf == GIT_SAFE_CRLF_FAIL)
+ ca.safe_crlf = GIT_SAFE_CRLF_WARN;
+ }
+
*payload = git__malloc(sizeof(ca));
GITERR_CHECK_ALLOC(*payload);
memcpy(*payload, &ca, sizeof(ca));