* translation when the "auto_crlf" option is set.
*/
+#define CRLF_GUESS (-1)
+#define CRLF_BINARY 0
+#define CRLF_TEXT 1
+#define CRLF_INPUT 2
+
struct text_stat {
/* CR, LF and CRLF counts */
unsigned cr, lf, crlf;
return 0;
}
-static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int guess)
+static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int action)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
- if (guess && !auto_crlf)
+ if ((action == CRLF_BINARY) || (action == CRLF_GUESS && !auto_crlf))
return 0;
size = *sizep;
if (!stats.cr)
return 0;
- if (guess) {
+ if (action == CRLF_GUESS) {
/*
* We're currently not going to even try to convert stuff
* that has bare CR characters. Does anybody do that crazy
*bufp = nbuf;
*sizep = nsize;
- if (guess) {
+ if (action == CRLF_GUESS) {
+ /*
+ * If we guessed, we already know we rejected a file with
+ * lone CR, and we can strip a CR without looking at what
+ * follow it.
+ */
do {
unsigned char c = *buffer++;
if (c != '\r')
return 1;
}
-static int autocrlf_to_git(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_git(path, bufp, sizep, 1);
-}
-
-static int forcecrlf_to_git(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_git(path, bufp, sizep, 0);
-}
-
-static int crlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep, int guess)
+static int crlf_to_worktree(const char *path, char **bufp, unsigned long *sizep, int action)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
unsigned char last;
- if (guess && auto_crlf <= 0)
+ if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
+ (action == CRLF_GUESS && auto_crlf <= 0))
return 0;
size = *sizep;
if (stats.lf == stats.crlf)
return 0;
- if (guess) {
+ if (action == CRLF_GUESS) {
/* If we have any bare CR characters, we're not going to touch it */
if (stats.cr != stats.crlf)
return 0;
return 1;
}
-static int autocrlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_working_tree(path, bufp, sizep, 1);
-}
-
-static int forcecrlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_working_tree(path, bufp, sizep, 0);
-}
-
static void setup_crlf_check(struct git_attr_check *check)
{
static struct git_attr *attr_crlf;
setup_crlf_check(&attr_crlf_check);
- if (git_checkattr(path, 1, &attr_crlf_check))
- return -1;
- return attr_crlf_check.isset;
+ if (!git_checkattr(path, 1, &attr_crlf_check)) {
+ const char *value = attr_crlf_check.value;
+ if (ATTR_TRUE(value))
+ return CRLF_TEXT;
+ else if (ATTR_FALSE(value))
+ return CRLF_BINARY;
+ else if (ATTR_UNSET(value))
+ ;
+ else if (!strcmp(value, "input"))
+ return CRLF_INPUT;
+ /* fallthru */
+ }
+ return CRLF_GUESS;
}
int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
{
- switch (git_path_check_crlf(path)) {
- case 0:
- return 0;
- case 1:
- return forcecrlf_to_git(path, bufp, sizep);
- default:
- return autocrlf_to_git(path, bufp, sizep);
- }
+ return crlf_to_git(path, bufp, sizep, git_path_check_crlf(path));
}
int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
{
- switch (git_path_check_crlf(path)) {
- case 0:
- return 0;
- case 1:
- return forcecrlf_to_working_tree(path, bufp, sizep);
- default:
- return autocrlf_to_working_tree(path, bufp, sizep);
- }
+ return crlf_to_worktree(path, bufp, sizep, git_path_check_crlf(path));
}