aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--diff.c52
-rw-r--r--diffcore.h8
-rw-r--r--userdiff.c19
-rw-r--r--userdiff.h4
4 files changed, 45 insertions, 38 deletions
diff --git a/diff.c b/diff.c
index d50355e84..dabd7f50e 100644
--- a/diff.c
+++ b/diff.c
@@ -1268,46 +1268,37 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two)
emit_binary_diff_body(file, two, one);
}
-static void diff_filespec_check_attr(struct diff_filespec *one)
+void diff_filespec_load_driver(struct diff_filespec *one)
{
- struct userdiff_driver *drv;
- int check_from_data = 0;
-
- if (one->checked_attr)
- return;
-
- drv = userdiff_find_by_path(one->path);
- one->is_binary = 0;
-
- /* binaryness */
- if (drv == USERDIFF_ATTR_TRUE)
- ;
- else if (drv == USERDIFF_ATTR_FALSE)
- one->is_binary = 1;
- else
- check_from_data = 1;
-
- if (check_from_data) {
- if (!one->data && DIFF_FILE_VALID(one))
- diff_populate_filespec(one, 0);
-
- if (one->data)
- one->is_binary = buffer_is_binary(one->data, one->size);
- }
+ if (!one->driver)
+ one->driver = userdiff_find_by_path(one->path);
+ if (!one->driver)
+ one->driver = userdiff_find_by_name("default");
}
int diff_filespec_is_binary(struct diff_filespec *one)
{
- diff_filespec_check_attr(one);
+ if (one->is_binary == -1) {
+ diff_filespec_load_driver(one);
+ if (one->driver->binary != -1)
+ one->is_binary = one->driver->binary;
+ else {
+ if (!one->data && DIFF_FILE_VALID(one))
+ diff_populate_filespec(one, 0);
+ if (one->data)
+ one->is_binary = buffer_is_binary(one->data,
+ one->size);
+ if (one->is_binary == -1)
+ one->is_binary = 0;
+ }
+ }
return one->is_binary;
}
static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one)
{
- struct userdiff_driver *drv = userdiff_find_by_path(one->path);
- if (!drv)
- drv = userdiff_find_by_name("default");
- return drv && drv->funcname.pattern ? &drv->funcname : NULL;
+ diff_filespec_load_driver(one);
+ return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
}
void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
@@ -1559,6 +1550,7 @@ struct diff_filespec *alloc_filespec(const char *path)
spec->path = (char *)(spec + 1);
memcpy(spec->path, path, namelen+1);
spec->count = 1;
+ spec->is_binary = -1;
return spec;
}
diff --git a/diffcore.h b/diffcore.h
index 8ae35785f..713cca785 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -22,6 +22,8 @@
#define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */
+struct userdiff_driver;
+
struct diff_filespec {
unsigned char sha1[20];
char *path;
@@ -40,8 +42,10 @@ struct diff_filespec {
#define DIFF_FILE_VALID(spec) (((spec)->mode) != 0)
unsigned should_free : 1; /* data should be free()'ed */
unsigned should_munmap : 1; /* data should be munmap()'ed */
- unsigned checked_attr : 1;
- unsigned is_binary : 1; /* data should be considered "binary" */
+
+ struct userdiff_driver *driver;
+ /* data should be considered "binary"; -1 means "don't know yet" */
+ int is_binary;
};
extern struct diff_filespec *alloc_filespec(const char *);
diff --git a/userdiff.c b/userdiff.c
index 80e2857ab..58478a691 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -7,7 +7,7 @@ static int ndrivers;
static int drivers_alloc;
#define FUNCNAME(name, pattern) \
- { name, NULL, { pattern, REG_EXTENDED } }
+ { name, NULL, -1, { pattern, REG_EXTENDED } }
static struct userdiff_driver builtin_drivers[] = {
FUNCNAME("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$"),
FUNCNAME("java",
@@ -32,22 +32,23 @@ FUNCNAME("python", "^[ \t]*((class|def)[ \t].*)$"),
FUNCNAME("ruby", "^[ \t]*((class|module|def)[ \t].*)$"),
FUNCNAME("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$"),
FUNCNAME("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$"),
+{ "default", NULL, -1, { NULL, 0 } },
};
#undef FUNCNAME
static struct userdiff_driver driver_true = {
"diff=true",
NULL,
+ 0,
{ NULL, 0 }
};
-struct userdiff_driver *USERDIFF_ATTR_TRUE = &driver_true;
static struct userdiff_driver driver_false = {
"!diff",
NULL,
+ 1,
{ NULL, 0 }
};
-struct userdiff_driver *USERDIFF_ATTR_FALSE = &driver_false;
static struct userdiff_driver *userdiff_find_by_namelen(const char *k, int len)
{
@@ -89,6 +90,7 @@ static struct userdiff_driver *parse_driver(const char *var,
drv = &drivers[ndrivers++];
memset(drv, 0, sizeof(*drv));
drv->name = xmemdupz(name, namelen);
+ drv->binary = -1;
}
return drv;
}
@@ -109,6 +111,15 @@ static int parse_string(const char **d, const char *k, const char *v)
return 1;
}
+static int parse_tristate(int *b, const char *k, const char *v)
+{
+ if (v && !strcasecmp(v, "auto"))
+ *b = -1;
+ else
+ *b = git_config_bool(k, v);
+ return 1;
+}
+
int userdiff_config_basic(const char *k, const char *v)
{
struct userdiff_driver *drv;
@@ -117,6 +128,8 @@ int userdiff_config_basic(const char *k, const char *v)
return parse_funcname(&drv->funcname, k, v, 0);
if ((drv = parse_driver(k, v, "xfuncname")))
return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
+ if ((drv = parse_driver(k, v, "binary")))
+ return parse_tristate(&drv->binary, k, v);
return 0;
}
diff --git a/userdiff.h b/userdiff.h
index c64c5f566..1c1eb042b 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -9,12 +9,10 @@ struct userdiff_funcname {
struct userdiff_driver {
const char *name;
const char *external;
+ int binary;
struct userdiff_funcname funcname;
};
-extern struct userdiff_driver *USERDIFF_ATTR_TRUE;
-extern struct userdiff_driver *USERDIFF_ATTR_FALSE;
-
int userdiff_config_basic(const char *k, const char *v);
int userdiff_config_porcelain(const char *k, const char *v);
struct userdiff_driver *userdiff_find_by_name(const char *name);