11
#include "attr.h"
12
#include "run-command.h"
13
#include "utf8.h"
14
+#include "userdiff.h"
15
16
#ifdef NO_FAST_WORKING_DIRECTORY
17
#define FAST_WORKING_DIRECTORY 0
57
die("bad config variable '%s'", var);
58
}
59
59
-static struct ll_diff_driver {
60
- const char *name;
61
- struct ll_diff_driver *next;
62
- const char *cmd;
63
-} *user_diff, **user_diff_tail;
64
-
65
-/*
66
- * Currently there is only "diff.<drivername>.command" variable;
67
- * because there are "diff.color.<slot>" variables, we are parsing
68
- * this in a bit convoluted way to allow low level diff driver
69
- * called "color".
70
- */
71
-static int parse_lldiff_command(const char *var, const char *ep, const char *value)
72
-{
73
- const char *name;
74
- int namelen;
75
- struct ll_diff_driver *drv;
76
-
77
- name = var + 5;
78
- namelen = ep - name;
79
- for (drv = user_diff; drv; drv = drv->next)
80
- if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
81
- break;
82
- if (!drv) {
83
- drv = xcalloc(1, sizeof(struct ll_diff_driver));
84
- drv->name = xmemdupz(name, namelen);
85
- if (!user_diff_tail)
86
- user_diff_tail = &user_diff;
87
- *user_diff_tail = drv;
88
- user_diff_tail = &(drv->next);
89
- }
90
-
91
- return git_config_string(&(drv->cmd), var, value);
92
-}
93
-
94
-/*
95
- * 'diff.<what>.funcname' attribute can be specified in the configuration
96
- * to define a customized regexp to find the beginning of a function to
97
- * be used for hunk header lines of "diff -p" style output.
98
- */
99
-struct funcname_pattern_entry {
100
- char *name;
101
- char *pattern;
102
- int cflags;
103
-};
104
-static struct funcname_pattern_list {
105
- struct funcname_pattern_list *next;
106
- struct funcname_pattern_entry e;
107
-} *funcname_pattern_list;
108
-
109
-static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags)
110
-{
111
- const char *name;
112
- int namelen;
113
- struct funcname_pattern_list *pp;
114
-
115
- name = var + 5; /* "diff." */
116
- namelen = ep - name;
117
-
118
- for (pp = funcname_pattern_list; pp; pp = pp->next)
119
- if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen])
120
- break;
121
- if (!pp) {
122
- pp = xcalloc(1, sizeof(*pp));
123
- pp->e.name = xmemdupz(name, namelen);
124
- pp->next = funcname_pattern_list;
125
- funcname_pattern_list = pp;
126
- }
127
- free(pp->e.pattern);
128
- pp->e.pattern = xstrdup(value);
129
- pp->e.cflags = cflags;
130
- return 0;
131
-}
132
-
60
/*
61
* These are to give UI layer defaults.
62
* The core-level commands such as git-diff-files should
89
}
90
if (!strcmp(var, "diff.external"))
91
return git_config_string(&external_diff_cmd_cfg, var, value);
165
- if (!prefixcmp(var, "diff.")) {
166
- const char *ep = strrchr(var, '.');
92
168
- if (ep != var + 4 && !strcmp(ep, ".command"))
169
- return parse_lldiff_command(var, ep, value);
93
+ switch (userdiff_config_porcelain(var, value)) {
94
+ case 0: break;
95
+ case -1: return -1;
96
+ default: return 0;
97
}
98
99
return git_diff_basic_config(var, value, cb);
120
return 0;
121
}
122
196
- if (!prefixcmp(var, "diff.")) {
197
- const char *ep = strrchr(var, '.');
198
- if (ep != var + 4) {
199
- if (!strcmp(ep, ".funcname")) {
200
- if (!value)
201
- return config_error_nonbool(var);
202
- return parse_funcname_pattern(var, ep, value,
203
- 0);
204
- } else if (!strcmp(ep, ".xfuncname")) {
205
- if (!value)
206
- return config_error_nonbool(var);
207
- return parse_funcname_pattern(var, ep, value,
208
- REG_EXTENDED);
209
- }
210
- }
123
+ switch (userdiff_config_basic(var, value)) {
124
+ case 0: break;
125
+ case -1: return -1;
126
+ default: return 0;
127
}
128
129
return git_color_default_config(var, value, cb);
1268
emit_binary_diff_body(file, two, one);
1269
}
1270
1355
-static void setup_diff_attr_check(struct git_attr_check *check)
1356
-{
1357
- static struct git_attr *attr_diff;
1358
-
1359
- if (!attr_diff) {
1360
- attr_diff = git_attr("diff", 4);
1361
- }
1362
- check[0].attr = attr_diff;
1363
-}
1364
-
1271
static void diff_filespec_check_attr(struct diff_filespec *one)
1272
{
1367
- struct git_attr_check attr_diff_check;
1273
+ struct userdiff_driver *drv;
1274
int check_from_data = 0;
1275
1276
if (one->checked_attr)
1277
return;
1278
1373
- setup_diff_attr_check(&attr_diff_check);
1279
+ drv = userdiff_find_by_path(one->path);
1280
one->is_binary = 0;
1375
- one->funcname_pattern_ident = NULL;
1281
1377
- if (!git_checkattr(one->path, 1, &attr_diff_check)) {
1378
- const char *value;
1379
-
1380
- /* binaryness */
1381
- value = attr_diff_check.value;
1382
- if (ATTR_TRUE(value))
1383
- ;
1384
- else if (ATTR_FALSE(value))
1385
- one->is_binary = 1;
1386
- else
1387
- check_from_data = 1;
1388
-
1389
- /* funcname pattern ident */
1390
- if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value))
1391
- ;
1392
- else
1393
- one->funcname_pattern_ident = value;
1394
- }
1282
+ /* binaryness */
1283
+ if (drv == USERDIFF_ATTR_TRUE)
1284
+ ;
1285
+ else if (drv == USERDIFF_ATTR_FALSE)
1286
+ one->is_binary = 1;
1287
+ else
1288
+ check_from_data = 1;
1289
1290
if (check_from_data) {
1291
if (!one->data && DIFF_FILE_VALID(one))
1302
return one->is_binary;
1303
}
1304
1411
-static const struct funcname_pattern_entry *funcname_pattern(const char *ident)
1412
-{
1413
- struct funcname_pattern_list *pp;
1414
-
1415
- for (pp = funcname_pattern_list; pp; pp = pp->next)
1416
- if (!strcmp(ident, pp->e.name))
1417
- return &pp->e;
1418
- return NULL;
1419
-}
1420
-
1421
-static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
1422
- { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
1423
- REG_EXTENDED },
1424
- { "html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", REG_EXTENDED },
1425
- { "java",
1426
- "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
1427
- "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$",
1428
- REG_EXTENDED },
1429
- { "objc",
1430
- /* Negate C statements that can look like functions */
1431
- "!^[ \t]*(do|for|if|else|return|switch|while)\n"
1432
- /* Objective-C methods */
1433
- "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n"
1434
- /* C functions */
1435
- "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n"
1436
- /* Objective-C class/protocol definitions */
1437
- "^(@(implementation|interface|protocol)[ \t].*)$",
1438
- REG_EXTENDED },
1439
- { "pascal",
1440
- "^((procedure|function|constructor|destructor|interface|"
1441
- "implementation|initialization|finalization)[ \t]*.*)$"
1442
- "\n"
1443
- "^(.*=[ \t]*(class|record).*)$",
1444
- REG_EXTENDED },
1445
- { "php", "^[\t ]*((function|class).*)", REG_EXTENDED },
1446
- { "python", "^[ \t]*((class|def)[ \t].*)$", REG_EXTENDED },
1447
- { "ruby", "^[ \t]*((class|module|def)[ \t].*)$",
1448
- REG_EXTENDED },
1449
- { "tex",
1450
- "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
1451
- REG_EXTENDED },
1452
-};
1453
-
1454
-static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one)
1305
+static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one)
1306
{
1456
- const char *ident;
1457
- const struct funcname_pattern_entry *pe;
1458
- int i;
1459
-
1460
- diff_filespec_check_attr(one);
1461
- ident = one->funcname_pattern_ident;
1462
-
1463
- if (!ident)
1464
- /*
1465
- * If the config file has "funcname.default" defined, that
1466
- * regexp is used; otherwise NULL is returned and xemit uses
1467
- * the built-in default.
1468
- */
1469
- return funcname_pattern("default");
1470
-
1471
- /* Look up custom "funcname.$ident" regexp from config. */
1472
- pe = funcname_pattern(ident);
1473
- if (pe)
1474
- return pe;
1475
-
1476
- /*
1477
- * And define built-in fallback patterns here. Note that
1478
- * these can be overridden by the user's config settings.
1479
- */
1480
- for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++)
1481
- if (!strcmp(ident, builtin_funcname_pattern[i].name))
1482
- return &builtin_funcname_pattern[i];
1483
-
1484
- return NULL;
1307
+ struct userdiff_driver *drv = userdiff_find_by_path(one->path);
1308
+ if (!drv)
1309
+ drv = userdiff_find_by_name("default");
1310
+ return drv && drv->funcname.pattern ? &drv->funcname : NULL;
1311
}
1312
1313
void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
1405
xdemitconf_t xecfg;
1406
xdemitcb_t ecb;
1407
struct emit_callback ecbdata;
1582
- const struct funcname_pattern_entry *pe;
1408
+ const struct userdiff_funcname *pe;
1409
1410
pe = diff_funcname_pattern(one);
1411
if (!pe)
1943
}
1944
}
1945
2120
-static const char *external_diff_attr(const char *name)
2121
-{
2122
- struct git_attr_check attr_diff_check;
2123
-
2124
- if (!name)
2125
- return NULL;
2126
-
2127
- setup_diff_attr_check(&attr_diff_check);
2128
- if (!git_checkattr(name, 1, &attr_diff_check)) {
2129
- const char *value = attr_diff_check.value;
2130
- if (!ATTR_TRUE(value) &&
2131
- !ATTR_FALSE(value) &&
2132
- !ATTR_UNSET(value)) {
2133
- struct ll_diff_driver *drv;
2134
-
2135
- for (drv = user_diff; drv; drv = drv->next)
2136
- if (!strcmp(drv->name, value))
2137
- return drv->cmd;
2138
- }
2139
- }
2140
- return NULL;
2141
-}
2142
-
1946
static void run_diff_cmd(const char *pgm,
1947
const char *name,
1948
const char *other,
1956
if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
1957
pgm = NULL;
1958
else {
2156
- const char *cmd = external_diff_attr(attr_path);
2157
- if (cmd)
2158
- pgm = cmd;
1959
+ struct userdiff_driver *drv = userdiff_find_by_path(attr_path);
1960
+ if (drv && drv->external)
1961
+ pgm = drv->external;
1962
}
1963
1964
if (pgm) {