Commit 450b40cab39c786bf67e7491755e7d0b3a4dc3ba

Vicent Martí 2012-02-28T01:13:32

filter: Load attributes for file

diff --git a/src/filter.c b/src/filter.c
index b97ac66..1775c09 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -10,6 +10,8 @@
 #include "hash.h"
 #include "filter.h"
 
+#include "git2/attr.h"
+
 /* Fresh from Core Git. I wonder what we could use this for... */
 void git_text__stat(git_text_stats *stats, git_buf *text)
 {
@@ -130,3 +132,89 @@ int git_filter__apply(git_buf *dest, git_buf *source, git_vector *filters, const
 
 	return GIT_SUCCESS;
 }
+
+
+static int check_crlf(const char *value)
+{
+	if (value == git_attr__true)
+		return GIT_CRLF_TEXT;
+
+	if (value == git_attr__false)
+		return GIT_CRLF_BINARY;
+
+	if (value == NULL)
+		return GIT_CRLF_GUESS;
+
+	if (strcmp(value, "input") == 0)
+		return GIT_CRLF_INPUT;
+
+	if (strcmp(value, "auto") == 0)
+		return GIT_CRLF_AUTO;
+
+	return GIT_CRLF_GUESS;
+}
+
+static int check_eol(const char *value)
+{
+	if (value == NULL)
+		return GIT_EOL_UNSET;
+
+	if (strcmp(value, "lf") == 0)
+		return GIT_EOL_LF;
+
+	if (strcmp(value, "crlf") == 0)
+		return GIT_EOL_CRLF;
+
+	return GIT_EOL_UNSET;
+}
+
+static int check_ident(const char *value)
+{
+	return (value == git_attr__true);
+}
+
+#if 0
+static int input_crlf_action(enum crlf_action text_attr, enum eol eol_attr)
+{
+	if (text_attr == CRLF_BINARY)
+		return CRLF_BINARY;
+	if (eol_attr == EOL_LF)
+		return CRLF_INPUT;
+	if (eol_attr == EOL_CRLF)
+		return CRLF_CRLF;
+	return text_attr;
+}
+#endif
+
+int git_filter__load_attrs(git_conv_attrs *ca, git_repository *repo, const char *path)
+{
+#define NUM_CONV_ATTRS 5
+
+	static const char *attr_names[NUM_CONV_ATTRS] = {
+		"crlf", "ident", "filter", "eol", "text",
+	};
+
+	const char *attr_vals[NUM_CONV_ATTRS];
+	int error;
+
+	error = git_attr_get_many(repo, path, NUM_CONV_ATTRS, attr_names, attr_vals);
+
+	if (error == GIT_ENOTFOUND) {
+		ca->crlf_action = GIT_CRLF_GUESS;
+		ca->eol_attr = GIT_EOL_UNSET;
+		ca->ident = 0;
+		return 0;
+	}
+
+	if (error == GIT_SUCCESS) {
+		ca->crlf_action = check_crlf(attr_vals[4]); /* text */
+		if (ca->crlf_action == GIT_CRLF_GUESS)
+			ca->crlf_action = check_crlf(attr_vals[0]); /* clrf */
+
+		ca->ident = check_ident(attr_vals[1]); /* ident */
+		ca->eol_attr = check_eol(attr_vals[3]); /* eol */
+		return 0;
+	}
+
+	return error;
+}
diff --git a/src/filter.h b/src/filter.h
index 9a8f849..2ed9da0 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -19,6 +19,41 @@ typedef enum {
 	GIT_FILTER_TO_ODB
 } git_filter_mode;
 
+typedef enum {
+	GIT_CRLF_GUESS = -1,
+	GIT_CRLF_BINARY = 0,
+	GIT_CRLF_TEXT,
+	GIT_CRLF_INPUT,
+	GIT_CRLF_CRLF,
+	GIT_CRLF_AUTO,
+
+	GIT_SAFE_CRLF_FALSE = 0,
+	GIT_SAFE_CRLF_FAIL = 1,
+	GIT_SAFE_CRLF_WARN = 2,
+
+	GIT_AUTO_CRLF_FALSE = 0,
+	GIT_AUTO_CRLF_TRUE = 1,
+	GIT_AUTO_CRLF_INPUT = -1,
+} git_crlf_t;
+
+typedef enum {
+	GIT_EOL_UNSET,
+	GIT_EOL_CRLF,
+	GIT_EOL_LF,
+#ifdef GIT_WIN32
+	GIT_EOL_NATIVE = GIT_EOL_CRLF
+#else
+	GIT_EOL_NATIVE = GIT_EOL_LF
+#endif
+} git_eol_t;
+
+
+typedef struct {
+	int crlf_action;
+	int eol_attr;
+	int ident;
+} git_conv_attrs;
+
 typedef struct {
 	/* NUL, CR, LF and CRLF counts */
 	unsigned int nul, cr, lf, crlf;
@@ -28,6 +63,7 @@ typedef struct {
 } git_text_stats;
 
 extern int git_filter__load_for_file(git_vector *filters, git_repository *repo, const char *full_path, int mode);
+extern int git_filter__load_attrs(git_conv_attrs *ca, git_repository *repo, const char *path);
 extern int git_filter__apply(git_buf *dest, git_buf *source, git_vector *filters, const char *filename);
 
 /* Gather stats for a piece of text */
diff --git a/src/repository.h b/src/repository.h
index 516fd10..fa19d2e 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -46,6 +46,11 @@ struct git_repository {
 
 	unsigned is_bare:1;
 	unsigned int lru_counter;
+
+	struct {
+		int core_eol;
+		int auto_crlf;
+	} filter_options;
 };
 
 /* fully free the object; internal method, do not