{"thread":{"id":"7789","subject":"[PATCH] Fix 'diff=pgm' attribute to consult config","startedAt":"2007-04-23T04:41:59Z","lastAt":"2007-04-23T04:41:59Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"40175","messageId":"11773033192350-git-send-email-junkio@cox.net","threadId":"7789","inReplyTo":null,"subject":"[PATCH] Fix 'diff=pgm' attribute to consult config","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-04-23T04:41:59Z","receivedAt":"2007-04-23T04:41:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This builds on top of the previous 'diff=pgm' attribute\nsupport.  Attributes only name a low-level diff driver, which is\ndefined in the configuration:\n\n\t[lldiff \"drivername\"]\n\t\tcommand = ...\n\nThe earlier one lacked this indirection, which was a mistake.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n diff.c                   |   60 ++++++++++++++++++++++++++++++++++++++++++++-\n t/t4020-diff-external.sh |    4 ++-\n 2 files changed, 61 insertions(+), 3 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex ebc1997..db61a78 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1747,6 +1747,53 @@ static void run_external_diff(const char *pgm,\n \t}\n }\n \n+static struct ll_diff_driver {\n+\tconst char *name;\n+\tstruct ll_diff_driver *next;\n+\tchar *cmd;\n+} *user_diff, **user_diff_tail;\n+\n+static int parse_lldiff_config(const char *var, const char *value)\n+{\n+\tconst char *ep, *name;\n+\tint namelen;\n+\tstruct ll_diff_driver *drv;\n+\n+\tif (prefixcmp(var, \"lldiff.\"))\n+\t\treturn 0;\n+\n+\t/* \"lldiff.<drivername>.<variable>\" */\n+\tif ((ep = strrchr(var, '.')) == var + 6)\n+\t\treturn 0;\n+\tname = var + 7;\n+\tnamelen = ep - name;\n+\tfor (drv = user_diff; drv; drv = drv->next)\n+\t\tif (!strncmp(drv->name, name, namelen) && !drv->name[namelen])\n+\t\t\tbreak;\n+\tif (!drv) {\n+\t\tchar *namebuf;\n+\t\tdrv = xcalloc(1, sizeof(struct ll_diff_driver));\n+\t\tnamebuf = xmalloc(namelen + 1);\n+\t\tmemcpy(namebuf, name, namelen);\n+\t\tnamebuf[namelen] = 0;\n+\t\tdrv->name = namebuf;\n+\t\tdrv->next = NULL;\n+\t\t*user_diff_tail = drv;\n+\t\tuser_diff_tail = &(drv->next);\n+\t}\n+\n+\tep++;\n+\n+\tif (!strcmp(\"command\", ep)) {\n+\t\tif (!value)\n+\t\t\treturn error(\"%s: lacks value\", var);\n+\t\tdrv->cmd = strdup(value);\n+\t\treturn 0;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static const char *external_diff_attr(const char *name)\n {\n \tstruct git_attr_check attr_diff_check;\n@@ -1756,8 +1803,17 @@ static const char *external_diff_attr(const char *name)\n \t\tconst char *value = attr_diff_check.value;\n \t\tif (!ATTR_TRUE(value) &&\n \t\t    !ATTR_FALSE(value) &&\n-\t\t    !ATTR_UNSET(value))\n-\t\t\treturn value;\n+\t\t    !ATTR_UNSET(value)) {\n+\t\t\tstruct ll_diff_driver *drv;\n+\n+\t\t\tif (!user_diff_tail) {\n+\t\t\t\tuser_diff_tail = &user_diff;\n+\t\t\t\tgit_config(parse_lldiff_config);\n+\t\t\t}\n+\t\t\tfor (drv = user_diff; drv; drv = drv->next)\n+\t\t\t\tif (!strcmp(drv->name, value))\n+\t\t\t\t\treturn drv->cmd;\n+\t\t}\n \t}\n \treturn NULL;\n }\ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex 60a93a7..bae9c46 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -45,7 +45,9 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' '\n \n test_expect_success 'diff attribute' '\n \n-\techo >.gitattributes \"file diff=echo\" &&\n+\tgit config lldiff.parrot.command echo &&\n+\n+\techo >.gitattributes \"file diff=parrot\" &&\n \n \tgit diff | {\n \t\tread path oldfile oldhex oldmode newfile newhex newmode &&\n-- \n1.5.1.2.936.ge4dd\n"}]}