Git fork

Merge branch 'ab/userdiff-tests'

A bit of code clean-up and a lot of test clean-up around userdiff
area.

* ab/userdiff-tests:
blame tests: simplify userdiff driver test
blame tests: don't rely on t/t4018/ directory
userdiff: remove support for "broken" tests
userdiff tests: list builtin drivers via test-tool
userdiff tests: explicitly test "default" pattern
userdiff: add and use for_each_userdiff_driver()
userdiff style: normalize pascal regex declaration
userdiff style: declare patterns with consistent style
userdiff style: re-order drivers in alphabetical order

+213 -109
+1
Makefile
··· 753 TEST_BUILTINS_OBJS += test-subprocess.o 754 TEST_BUILTINS_OBJS += test-trace2.o 755 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o 756 TEST_BUILTINS_OBJS += test-wildmatch.o 757 TEST_BUILTINS_OBJS += test-windows-named-pipe.o 758 TEST_BUILTINS_OBJS += test-write-cache.o
··· 753 TEST_BUILTINS_OBJS += test-subprocess.o 754 TEST_BUILTINS_OBJS += test-trace2.o 755 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o 756 + TEST_BUILTINS_OBJS += test-userdiff.o 757 TEST_BUILTINS_OBJS += test-wildmatch.o 758 TEST_BUILTINS_OBJS += test-windows-named-pipe.o 759 TEST_BUILTINS_OBJS += test-write-cache.o
+19 -15
t/annotate-tests.sh
··· 479 check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1 480 ' 481 482 - test_expect_success 'setup -L :funcname with userdiff driver' ' 483 - echo "fortran-* diff=fortran" >.gitattributes && 484 - fortran_file=fortran-external-function && 485 - orig_file="$TEST_DIRECTORY/t4018/$fortran_file" && 486 - cp "$orig_file" . && 487 - git add "$fortran_file" && 488 - GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \ 489 - git commit -m "add fortran file" && 490 - sed -e "s/ChangeMe/IWasChanged/" <"$orig_file" >"$fortran_file" && 491 - git add "$fortran_file" && 492 - GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \ 493 - git commit -m "change fortran file" 494 - ' 495 - 496 test_expect_success 'blame -L :funcname with userdiff driver' ' 497 - check_count -f fortran-external-function -L:RIGHT A 7 B 1 498 ' 499 500 test_expect_success 'setup incremental' '
··· 479 check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1 480 ' 481 482 test_expect_success 'blame -L :funcname with userdiff driver' ' 483 + cat >file.template <<-\EOF && 484 + DO NOT MATCH THIS LINE 485 + function RIGHT(a, b) result(c) 486 + AS THE DEFAULT DRIVER WOULD 487 + 488 + integer, intent(in) :: ChangeMe 489 + EOF 490 + 491 + fortran_file=file.f03 && 492 + test_when_finished "rm .gitattributes" && 493 + echo "$fortran_file diff=fortran" >.gitattributes && 494 + 495 + test_commit --author "A <A@test.git>" \ 496 + "add" "$fortran_file" \ 497 + "$(cat file.template)" && 498 + test_commit --author "B <B@test.git>" \ 499 + "change" "$fortran_file" \ 500 + "$(cat file.template | sed -e s/ChangeMe/IWasChanged/)" && 501 + check_count -f "$fortran_file" -L:RIGHT A 3 B 1 502 ' 503 504 test_expect_success 'setup incremental' '
+1
t/helper/test-tool.c
··· 73 { "submodule-nested-repo-config", cmd__submodule_nested_repo_config }, 74 { "subprocess", cmd__subprocess }, 75 { "trace2", cmd__trace2 }, 76 { "urlmatch-normalization", cmd__urlmatch_normalization }, 77 { "xml-encode", cmd__xml_encode }, 78 { "wildmatch", cmd__wildmatch },
··· 73 { "submodule-nested-repo-config", cmd__submodule_nested_repo_config }, 74 { "subprocess", cmd__subprocess }, 75 { "trace2", cmd__trace2 }, 76 + { "userdiff", cmd__userdiff }, 77 { "urlmatch-normalization", cmd__urlmatch_normalization }, 78 { "xml-encode", cmd__xml_encode }, 79 { "wildmatch", cmd__wildmatch },
+1
t/helper/test-tool.h
··· 63 int cmd__submodule_nested_repo_config(int argc, const char **argv); 64 int cmd__subprocess(int argc, const char **argv); 65 int cmd__trace2(int argc, const char **argv); 66 int cmd__urlmatch_normalization(int argc, const char **argv); 67 int cmd__xml_encode(int argc, const char **argv); 68 int cmd__wildmatch(int argc, const char **argv);
··· 63 int cmd__submodule_nested_repo_config(int argc, const char **argv); 64 int cmd__subprocess(int argc, const char **argv); 65 int cmd__trace2(int argc, const char **argv); 66 + int cmd__userdiff(int argc, const char **argv); 67 int cmd__urlmatch_normalization(int argc, const char **argv); 68 int cmd__xml_encode(int argc, const char **argv); 69 int cmd__wildmatch(int argc, const char **argv);
+46
t/helper/test-userdiff.c
···
··· 1 + #include "test-tool.h" 2 + #include "cache.h" 3 + #include "userdiff.h" 4 + #include "config.h" 5 + 6 + static int driver_cb(struct userdiff_driver *driver, 7 + enum userdiff_driver_type type, void *priv) 8 + { 9 + enum userdiff_driver_type *want_type = priv; 10 + if (type & *want_type && driver->funcname.pattern) 11 + puts(driver->name); 12 + return 0; 13 + } 14 + 15 + static int cmd__userdiff_config(const char *var, const char *value, void *cb) 16 + { 17 + if (userdiff_config(var, value) < 0) 18 + return -1; 19 + return 0; 20 + } 21 + 22 + int cmd__userdiff(int argc, const char **argv) 23 + { 24 + enum userdiff_driver_type want = 0; 25 + if (argc != 2) 26 + return 1; 27 + 28 + if (!strcmp(argv[1], "list-drivers")) 29 + want = (USERDIFF_DRIVER_TYPE_BUILTIN | 30 + USERDIFF_DRIVER_TYPE_CUSTOM); 31 + else if (!strcmp(argv[1], "list-builtin-drivers")) 32 + want = USERDIFF_DRIVER_TYPE_BUILTIN; 33 + else if (!strcmp(argv[1], "list-custom-drivers")) 34 + want = USERDIFF_DRIVER_TYPE_CUSTOM; 35 + else 36 + return error("unknown argument %s", argv[1]); 37 + 38 + if (want & USERDIFF_DRIVER_TYPE_CUSTOM) { 39 + setup_git_directory(); 40 + git_config(cmd__userdiff_config, NULL); 41 + } 42 + 43 + for_each_userdiff_driver(driver_cb, &want); 44 + 45 + return 0; 46 + }
+20 -34
t/t4018-diff-funcname.sh
··· 25 echo B >B.java 26 ' 27 28 diffpatterns=" 29 - ada 30 - bash 31 - bibtex 32 - cpp 33 - csharp 34 - css 35 - dts 36 - elixir 37 - fortran 38 - fountain 39 - golang 40 - html 41 - java 42 - markdown 43 - matlab 44 - objc 45 - pascal 46 - perl 47 - php 48 - python 49 - ruby 50 - rust 51 - scheme 52 - tex 53 - custom1 54 - custom2 55 - custom3 56 " 57 58 for p in $diffpatterns ··· 102 # check each individual file 103 for i in $(git ls-files) 104 do 105 - if grep broken "$i" >/dev/null 2>&1 106 - then 107 - result=failure 108 - else 109 - result=success 110 - fi 111 - test_expect_$result "hunk header: $i" " 112 git diff -U1 $i >actual && 113 grep '@@ .* @@.*RIGHT' actual 114 "
··· 25 echo B >B.java 26 ' 27 28 + test_expect_success 'setup: test-tool userdiff' ' 29 + # Make sure additions to builtin_drivers are sorted 30 + test_when_finished "rm builtin-drivers.sorted" && 31 + test-tool userdiff list-builtin-drivers >builtin-drivers && 32 + test_file_not_empty builtin-drivers && 33 + sort <builtin-drivers >builtin-drivers.sorted && 34 + test_cmp builtin-drivers.sorted builtin-drivers && 35 + 36 + # Ditto, but "custom" requires the .git directory and config 37 + # to be setup and read. 38 + test_when_finished "rm custom-drivers.sorted" && 39 + test-tool userdiff list-custom-drivers >custom-drivers && 40 + test_file_not_empty custom-drivers && 41 + sort <custom-drivers >custom-drivers.sorted && 42 + test_cmp custom-drivers.sorted custom-drivers 43 + ' 44 + 45 diffpatterns=" 46 + $(cat builtin-drivers) 47 + $(cat custom-drivers) 48 " 49 50 for p in $diffpatterns ··· 94 # check each individual file 95 for i in $(git ls-files) 96 do 97 + test_expect_success "hunk header: $i" " 98 git diff -U1 $i >actual && 99 grep '@@ .* @@.*RIGHT' actual 100 "
-3
t/t4018/README
··· 7 The text that must appear in the hunk header must contain the word 8 "right", but in all upper-case, like in the title above. 9 10 - To mark a test case that highlights a malfunction, insert the word 11 - BROKEN in all lower-case somewhere in the file. 12 - 13 This text is a bit twisted and out of order, but it is itself a 14 test case for the default hunk header pattern. Know what you are doing 15 if you change it.
··· 7 The text that must appear in the hunk header must contain the word 8 "right", but in all upper-case, like in the title above. 9 10 This text is a bit twisted and out of order, but it is itself a 11 test case for the default hunk header pattern. Know what you are doing 12 if you change it.
+112 -57
userdiff.c
··· 44 /* -- */ 45 /* Characters not in the default $IFS value */ 46 "[^ \t]+"), 47 PATTERNS("dts", 48 "!;\n" 49 "!=\n" ··· 83 * they would have been matched above as a variable anyway. */ 84 "|[-+]?[0-9.]+([AaIiDdEeFfLlTtXx][Ss]?[-+]?[0-9.]*)?(_[a-zA-Z0-9][a-zA-Z0-9_]*)?" 85 "|//|\\*\\*|::|[/<>=]="), 86 - IPATTERN("fountain", "^((\\.[^.]|(int|ext|est|int\\.?/ext|i/e)[. ]).*)$", 87 "[^ \t-]+"), 88 PATTERNS("golang", 89 /* Functions */ ··· 94 "[a-zA-Z_][a-zA-Z0-9_]*" 95 "|[-+0-9.eE]+i?|0[xX]?[0-9a-fA-F]+i?" 96 "|[-+*/<>%&^|=!:]=|--|\\+\\+|<<=?|>>=?|&\\^=?|&&|\\|\\||<-|\\.{3}"), 97 - PATTERNS("html", "^[ \t]*(<[Hh][1-6]([ \t].*)?>.*)$", 98 "[^<>= \t]+"), 99 PATTERNS("java", 100 "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" ··· 106 "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"), 107 PATTERNS("markdown", 108 "^ {0,3}#{1,6}[ \t].*", 109 "[^<>= \t]+"), 110 PATTERNS("matlab", 111 /* ··· 114 * that is understood by both. 115 */ 116 "^[[:space:]]*((classdef|function)[[:space:]].*)$|^(%%%?|##)[[:space:]].*$", 117 "[a-zA-Z_][a-zA-Z0-9_]*|[-+0-9.e]+|[=~<>]=|\\.[*/\\^']|\\|\\||&&"), 118 PATTERNS("objc", 119 /* Negate C statements that can look like functions */ ··· 129 "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" 130 "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"), 131 PATTERNS("pascal", 132 - "^(((class[ \t]+)?(procedure|function)|constructor|destructor|interface|" 133 - "implementation|initialization|finalization)[ \t]*.*)$" 134 - "\n" 135 "^(.*=[ \t]*(class|record).*)$", 136 /* -- */ 137 "[a-zA-Z_][a-zA-Z0-9_]*" ··· 174 "[a-zA-Z_][a-zA-Z0-9_]*" 175 "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+" 176 "|[-+*/<>%&^|=!.]=|--|\\+\\+|<<=?|>>=?|===|&&|\\|\\||::|->"), 177 - PATTERNS("python", "^[ \t]*((class|(async[ \t]+)?def)[ \t].*)$", 178 /* -- */ 179 "[a-zA-Z_][a-zA-Z0-9_]*" 180 "|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?" 181 "|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?"), 182 /* -- */ 183 - PATTERNS("ruby", "^[ \t]*((class|module|def)[ \t].*)$", 184 /* -- */ 185 "(@|@@|\\$)?[a-zA-Z_][a-zA-Z0-9_]*" 186 "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?." ··· 200 "\\|([^\\\\]*)\\|" 201 /* All other words should be delimited by spaces or parentheses */ 202 "|([^][)(}{[ \t])+"), 203 - PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", 204 - "[={}\"]|[^={}\" \t]+"), 205 PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", 206 "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"), 207 - PATTERNS("cpp", 208 - /* Jump targets or access declarations */ 209 - "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])\n" 210 - /* functions/methods, variables, and compounds at top level */ 211 - "^((::[[:space:]]*)?[A-Za-z_].*)$", 212 - /* -- */ 213 - "[a-zA-Z_][a-zA-Z0-9_]*" 214 - "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lLuU]*" 215 - "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->\\*?|\\.\\*"), 216 - PATTERNS("csharp", 217 - /* Keywords */ 218 - "!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n" 219 - /* Methods and constructors */ 220 - "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe|async)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n" 221 - /* Properties */ 222 - "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n" 223 - /* Type definitions */ 224 - "^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct)[ \t]+.*)$\n" 225 - /* Namespace */ 226 - "^[ \t]*(namespace[ \t]+.*)$", 227 - /* -- */ 228 - "[a-zA-Z_][a-zA-Z0-9_]*" 229 - "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" 230 - "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"), 231 - IPATTERN("css", 232 - "![:;][[:space:]]*$\n" 233 - "^[:[@.#]?[_a-z0-9].*$", 234 - /* -- */ 235 - /* 236 - * This regex comes from W3C CSS specs. Should theoretically also 237 - * allow ISO 10646 characters U+00A0 and higher, 238 - * but they are not handled in this regex. 239 - */ 240 - "-?[_a-zA-Z][-_a-zA-Z0-9]*" /* identifiers */ 241 - "|-?[0-9]+|\\#[0-9a-fA-F]+" /* numbers */ 242 - ), 243 { "default", NULL, -1, { NULL, 0 } }, 244 }; 245 #undef PATTERNS ··· 259 { NULL, 0 } 260 }; 261 262 - static struct userdiff_driver *userdiff_find_by_namelen(const char *k, size_t len) 263 { 264 - int i; 265 - for (i = 0; i < ndrivers; i++) { 266 - struct userdiff_driver *drv = drivers + i; 267 - if (!strncmp(drv->name, k, len) && !drv->name[len]) 268 - return drv; 269 } 270 - for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) { 271 - struct userdiff_driver *drv = builtin_drivers + i; 272 - if (!strncmp(drv->name, k, len) && !drv->name[len]) 273 - return drv; 274 - } 275 - return NULL; 276 } 277 278 static int parse_funcname(struct userdiff_funcname *f, const char *k, ··· 379 380 return driver; 381 }
··· 44 /* -- */ 45 /* Characters not in the default $IFS value */ 46 "[^ \t]+"), 47 + PATTERNS("bibtex", 48 + "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", 49 + /* -- */ 50 + "[={}\"]|[^={}\" \t]+"), 51 + PATTERNS("cpp", 52 + /* Jump targets or access declarations */ 53 + "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])\n" 54 + /* functions/methods, variables, and compounds at top level */ 55 + "^((::[[:space:]]*)?[A-Za-z_].*)$", 56 + /* -- */ 57 + "[a-zA-Z_][a-zA-Z0-9_]*" 58 + "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lLuU]*" 59 + "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->\\*?|\\.\\*"), 60 + PATTERNS("csharp", 61 + /* Keywords */ 62 + "!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n" 63 + /* Methods and constructors */ 64 + "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe|async)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n" 65 + /* Properties */ 66 + "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n" 67 + /* Type definitions */ 68 + "^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct)[ \t]+.*)$\n" 69 + /* Namespace */ 70 + "^[ \t]*(namespace[ \t]+.*)$", 71 + /* -- */ 72 + "[a-zA-Z_][a-zA-Z0-9_]*" 73 + "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" 74 + "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"), 75 + IPATTERN("css", 76 + "![:;][[:space:]]*$\n" 77 + "^[:[@.#]?[_a-z0-9].*$", 78 + /* -- */ 79 + /* 80 + * This regex comes from W3C CSS specs. Should theoretically also 81 + * allow ISO 10646 characters U+00A0 and higher, 82 + * but they are not handled in this regex. 83 + */ 84 + "-?[_a-zA-Z][-_a-zA-Z0-9]*" /* identifiers */ 85 + "|-?[0-9]+|\\#[0-9a-fA-F]+" /* numbers */ 86 + ), 87 PATTERNS("dts", 88 "!;\n" 89 "!=\n" ··· 123 * they would have been matched above as a variable anyway. */ 124 "|[-+]?[0-9.]+([AaIiDdEeFfLlTtXx][Ss]?[-+]?[0-9.]*)?(_[a-zA-Z0-9][a-zA-Z0-9_]*)?" 125 "|//|\\*\\*|::|[/<>=]="), 126 + IPATTERN("fountain", 127 + "^((\\.[^.]|(int|ext|est|int\\.?/ext|i/e)[. ]).*)$", 128 + /* -- */ 129 "[^ \t-]+"), 130 PATTERNS("golang", 131 /* Functions */ ··· 136 "[a-zA-Z_][a-zA-Z0-9_]*" 137 "|[-+0-9.eE]+i?|0[xX]?[0-9a-fA-F]+i?" 138 "|[-+*/<>%&^|=!:]=|--|\\+\\+|<<=?|>>=?|&\\^=?|&&|\\|\\||<-|\\.{3}"), 139 + PATTERNS("html", 140 + "^[ \t]*(<[Hh][1-6]([ \t].*)?>.*)$", 141 + /* -- */ 142 "[^<>= \t]+"), 143 PATTERNS("java", 144 "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" ··· 150 "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"), 151 PATTERNS("markdown", 152 "^ {0,3}#{1,6}[ \t].*", 153 + /* -- */ 154 "[^<>= \t]+"), 155 PATTERNS("matlab", 156 /* ··· 159 * that is understood by both. 160 */ 161 "^[[:space:]]*((classdef|function)[[:space:]].*)$|^(%%%?|##)[[:space:]].*$", 162 + /* -- */ 163 "[a-zA-Z_][a-zA-Z0-9_]*|[-+0-9.e]+|[=~<>]=|\\.[*/\\^']|\\|\\||&&"), 164 PATTERNS("objc", 165 /* Negate C statements that can look like functions */ ··· 175 "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" 176 "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"), 177 PATTERNS("pascal", 178 + "^(((class[ \t]+)?(procedure|function)|constructor|destructor|interface" 179 + "|implementation|initialization|finalization)[ \t]*.*)$\n" 180 "^(.*=[ \t]*(class|record).*)$", 181 /* -- */ 182 "[a-zA-Z_][a-zA-Z0-9_]*" ··· 219 "[a-zA-Z_][a-zA-Z0-9_]*" 220 "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+" 221 "|[-+*/<>%&^|=!.]=|--|\\+\\+|<<=?|>>=?|===|&&|\\|\\||::|->"), 222 + PATTERNS("python", 223 + "^[ \t]*((class|(async[ \t]+)?def)[ \t].*)$", 224 /* -- */ 225 "[a-zA-Z_][a-zA-Z0-9_]*" 226 "|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?" 227 "|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?"), 228 /* -- */ 229 + PATTERNS("ruby", 230 + "^[ \t]*((class|module|def)[ \t].*)$", 231 /* -- */ 232 "(@|@@|\\$)?[a-zA-Z_][a-zA-Z0-9_]*" 233 "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?." ··· 247 "\\|([^\\\\]*)\\|" 248 /* All other words should be delimited by spaces or parentheses */ 249 "|([^][)(}{[ \t])+"), 250 PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", 251 "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"), 252 { "default", NULL, -1, { NULL, 0 } }, 253 }; 254 #undef PATTERNS ··· 268 { NULL, 0 } 269 }; 270 271 + struct find_by_namelen_data { 272 + const char *name; 273 + size_t len; 274 + struct userdiff_driver *driver; 275 + }; 276 + 277 + static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver, 278 + enum userdiff_driver_type type, void *priv) 279 { 280 + struct find_by_namelen_data *cb_data = priv; 281 + 282 + if (!strncmp(driver->name, cb_data->name, cb_data->len) && 283 + !driver->name[cb_data->len]) { 284 + cb_data->driver = driver; 285 + return 1; /* tell the caller to stop iterating */ 286 } 287 + return 0; 288 + } 289 + 290 + static struct userdiff_driver *userdiff_find_by_namelen(const char *name, size_t len) 291 + { 292 + struct find_by_namelen_data udcbdata = { 293 + .name = name, 294 + .len = len, 295 + }; 296 + for_each_userdiff_driver(userdiff_find_by_namelen_cb, &udcbdata); 297 + return udcbdata.driver; 298 } 299 300 static int parse_funcname(struct userdiff_funcname *f, const char *k, ··· 401 402 return driver; 403 } 404 + 405 + static int for_each_userdiff_driver_list(each_userdiff_driver_fn fn, 406 + enum userdiff_driver_type type, void *cb_data, 407 + struct userdiff_driver *drv, 408 + int drv_size) 409 + { 410 + int i; 411 + int ret; 412 + for (i = 0; i < drv_size; i++) { 413 + struct userdiff_driver *item = drv + i; 414 + if ((ret = fn(item, type, cb_data))) 415 + return ret; 416 + } 417 + return 0; 418 + } 419 + 420 + int for_each_userdiff_driver(each_userdiff_driver_fn fn, void *cb_data) 421 + { 422 + int ret; 423 + 424 + ret = for_each_userdiff_driver_list(fn, USERDIFF_DRIVER_TYPE_CUSTOM, 425 + cb_data, drivers, ndrivers); 426 + if (ret) 427 + return ret; 428 + 429 + ret = for_each_userdiff_driver_list(fn, USERDIFF_DRIVER_TYPE_BUILTIN, 430 + cb_data, builtin_drivers, 431 + ARRAY_SIZE(builtin_drivers)); 432 + if (ret) 433 + return ret; 434 + 435 + return 0; 436 + }
+13
userdiff.h
··· 21 struct notes_cache *textconv_cache; 22 int textconv_want_cache; 23 }; 24 25 int userdiff_config(const char *k, const char *v); 26 struct userdiff_driver *userdiff_find_by_name(const char *name); ··· 33 */ 34 struct userdiff_driver *userdiff_get_textconv(struct repository *r, 35 struct userdiff_driver *driver); 36 37 #endif /* USERDIFF */
··· 21 struct notes_cache *textconv_cache; 22 int textconv_want_cache; 23 }; 24 + enum userdiff_driver_type { 25 + USERDIFF_DRIVER_TYPE_BUILTIN = 1<<0, 26 + USERDIFF_DRIVER_TYPE_CUSTOM = 1<<1, 27 + }; 28 + typedef int (*each_userdiff_driver_fn)(struct userdiff_driver *, 29 + enum userdiff_driver_type, void *); 30 31 int userdiff_config(const char *k, const char *v); 32 struct userdiff_driver *userdiff_find_by_name(const char *name); ··· 39 */ 40 struct userdiff_driver *userdiff_get_textconv(struct repository *r, 41 struct userdiff_driver *driver); 42 + 43 + /* 44 + * Iterate over all userdiff drivers. The userdiff_driver_type 45 + * argument to each_userdiff_driver_fn indicates their type. Return 46 + * non-zero to exit early from the loop. 47 + */ 48 + int for_each_userdiff_driver(each_userdiff_driver_fn, void *); 49 50 #endif /* USERDIFF */