summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-03-27 16:34:20 -0700
committerEdward Thomson <ethomson@microsoft.com>2014-04-07 21:09:09 -0700
commit855c66de66fe39fe219c6dab9d614c6e9d633d9c (patch)
tree32ff163e05a034f270e71cbc8b4f7d6dfb838ce9 /src
parent5f74c476939894c4512262ec11188a44bfe4f50a (diff)
downloadlibgit2-855c66de66fe39fe219c6dab9d614c6e9d633d9c.tar.gz
Introduce core.safecrlf handling
Diffstat (limited to 'src')
-rw-r--r--src/config_cache.c1
-rw-r--r--src/crlf.c34
-rw-r--r--src/repository.h4
3 files changed, 36 insertions, 3 deletions
diff --git a/src/config_cache.c b/src/config_cache.c
index ec75d1501..4bcbf02bf 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -68,6 +68,7 @@ static struct map_data _cvar_maps[] = {
{"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT },
{"core.abbrev", _cvar_map_int, 1, GIT_ABBREV_DEFAULT },
{"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT },
+ {"core.safecrlf", NULL, 0, GIT_SAFE_CRLF_DEFAULT},
};
int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar)
diff --git a/src/crlf.c b/src/crlf.c
index 2480cc918..645ada2c6 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -21,6 +21,7 @@ struct crlf_attrs {
int crlf_action;
int eol;
int auto_crlf;
+ int safe_crlf;
};
struct crlf_filter {
@@ -123,6 +124,9 @@ static int crlf_apply_to_odb(
const git_buf *from,
const git_filter_source *src)
{
+ git_buf safe = GIT_BUF_INIT;
+ int error = 0;
+
/* Empty file? Nothing to do */
if (!git_buf_len(from))
return 0;
@@ -154,12 +158,31 @@ static int crlf_apply_to_odb(
return GIT_PASSTHROUGH;
}
- if (!stats.cr)
+ if (!stats.cr && !ca->safe_crlf)
return GIT_PASSTHROUGH;
}
/* Actually drop the carriage returns */
- return git_buf_text_crlf_to_lf(to, from);
+ if ((error = git_buf_text_crlf_to_lf(to, from)) < 0)
+ return error;
+
+ /* If safecrlf is enabled, sanity-check the result. */
+ if (ca->safe_crlf) {
+ if ((error = git_buf_grow(&safe, max(from->size, to->size))) < 0 ||
+ (error = git_buf_text_lf_to_crlf(&safe, to)) < 0)
+ goto done;
+
+ if (git_buf_cmp(from, &safe) != 0) {
+ giterr_set(GITERR_FILTER, "LF would be replaced by CRLF in '%s'",
+ git_filter_source_path(src));
+ error = -1;
+ }
+ }
+
+done:
+ git_buf_free(&safe);
+
+ return error;
}
static const char *line_ending(struct crlf_attrs *ca)
@@ -272,6 +295,13 @@ static int crlf_check(
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;
+ }
+
*payload = git__malloc(sizeof(ca));
GITERR_CHECK_ALLOC(*payload);
memcpy(*payload, &ca, sizeof(ca));
diff --git a/src/repository.h b/src/repository.h
index 99923b63b..e401a82b8 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -38,6 +38,7 @@ typedef enum {
GIT_CVAR_TRUSTCTIME, /* core.trustctime */
GIT_CVAR_ABBREV, /* core.abbrev */
GIT_CVAR_PRECOMPOSE, /* core.precomposeunicode */
+ GIT_CVAR_SAFE_CRLF, /* core.safecrlf */
GIT_CVAR_CACHE_MAX
} git_cvar_cached;
@@ -89,7 +90,8 @@ typedef enum {
GIT_ABBREV_DEFAULT = 7,
/* core.precomposeunicode */
GIT_PRECOMPOSE_DEFAULT = GIT_CVAR_FALSE,
-
+ /* core.safecrlf */
+ GIT_SAFE_CRLF_DEFAULT = GIT_CVAR_FALSE,
} git_cvar_value;
/* internal repository init flags */