@@ -38,6 +38,7 @@ struct git_diff_driver {
3838 uint32_t other_flags ;
3939 git_array_t (regex_t ) fn_patterns ;
4040 regex_t word_pattern ;
41+ char name [GIT_FLEX_ARRAY ];
4142};
4243
4344struct git_diff_driver_registry {
@@ -132,15 +133,18 @@ static int git_diff_driver_load(
132133 int error = 0 , bval ;
133134 git_diff_driver_registry * reg ;
134135 git_diff_driver * drv ;
136+ size_t namelen = strlen (driver_name );
137+ khiter_t pos ;
135138 git_config * cfg ;
136139 git_buf name = GIT_BUF_INIT ;
137140 const char * val ;
141+ bool found_driver = false;
138142
139143 reg = git_repository_driver_registry (repo );
140144 if (!reg )
141145 return -1 ;
142146 else {
143- khiter_t pos = git_strmap_lookup_index (reg -> drivers , driver_name );
147+ pos = git_strmap_lookup_index (reg -> drivers , driver_name );
144148 if (git_strmap_valid_index (reg -> drivers , pos )) {
145149 * out = git_strmap_value_at (reg -> drivers , pos );
146150 return 0 ;
@@ -153,9 +157,10 @@ static int git_diff_driver_load(
153157 return GIT_ENOTFOUND ;
154158 }
155159
156- drv = git__calloc (1 , sizeof (git_diff_driver ));
160+ drv = git__calloc (1 , sizeof (git_diff_driver ) + namelen + 1 );
157161 GITERR_CHECK_ALLOC (drv );
158162 drv -> type = DIFF_DRIVER_AUTO ;
163+ memcpy (drv -> name , driver_name , namelen );
159164
160165 if ((error = git_buf_printf (& name , "diff.%s.binary" , driver_name )) < 0 )
161166 goto fail ;
@@ -176,51 +181,62 @@ static int git_diff_driver_load(
176181 /* if diff.<driver>.binary is false, force binary checks off */
177182 /* but still may have custom function context patterns, etc. */
178183 drv -> binary_flags = GIT_DIFF_FORCE_TEXT ;
184+ found_driver = true;
179185 }
180186
181187 /* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */
182188
183- if (( error = git_buf_printf ( & name , "diff.%s.xfuncname" , driver_name )) < 0 )
184- goto fail ;
189+ git_buf_truncate ( & name , namelen + strlen ( "diff.." ));
190+ git_buf_put ( & name , "xfuncname" , strlen ( "xfuncname" )) ;
185191 if ((error = git_config_get_multivar (
186192 cfg , name .ptr , NULL , diff_driver_xfuncname , drv )) < 0 ) {
187193 if (error != GIT_ENOTFOUND )
188194 goto fail ;
189- /* no diff.<driver>.xfuncname values, so just continue */
190- giterr_clear ();
195+ giterr_clear (); /* no diff.<driver>.xfuncname, so just continue */
191196 }
192197
193- if (( error = git_buf_printf ( & name , "diff.%s.funcname" , driver_name )) < 0 )
194- goto fail ;
198+ git_buf_truncate ( & name , namelen + strlen ( "diff.." ));
199+ git_buf_put ( & name , "funcname" , strlen ( "funcname" )) ;
195200 if ((error = git_config_get_multivar (
196201 cfg , name .ptr , NULL , diff_driver_funcname , drv )) < 0 ) {
197202 if (error != GIT_ENOTFOUND )
198203 goto fail ;
199- /* no diff.<driver>.funcname values, so just continue */
200- giterr_clear ();
204+ giterr_clear (); /* no diff.<driver>.funcname, so just continue */
201205 }
202206
203207 /* if we found any patterns, set driver type to use correct callback */
204- if (git_array_size (drv -> fn_patterns ) > 0 )
208+ if (git_array_size (drv -> fn_patterns ) > 0 ) {
205209 drv -> type = DIFF_DRIVER_PATTERNLIST ;
210+ found_driver = true;
211+ }
206212
207- if (( error = git_buf_printf ( & name , "diff.%s.wordregex" , driver_name )) < 0 )
208- goto fail ;
213+ git_buf_truncate ( & name , namelen + strlen ( "diff.." ));
214+ git_buf_put ( & name , "wordregex" , strlen ( "wordregex" )) ;
209215 if ((error = git_config_get_string (& val , cfg , name .ptr )) < 0 ) {
210216 if (error != GIT_ENOTFOUND )
211217 goto fail ;
212- /* no diff.<driver>.wordregex, so just continue */
213- giterr_clear ();
218+ giterr_clear (); /* no diff.<driver>.wordregex, so just continue */
214219 } else if ((error = regcomp (& drv -> word_pattern , val , REG_EXTENDED )) != 0 ) {
215220 /* TODO: warning about bad regex instead of failure */
216221 error = giterr_set_regex (& drv -> word_pattern , error );
217222 goto fail ;
223+ } else {
224+ found_driver = true;
218225 }
219226
220227 /* TODO: look up diff.<driver>.algorithm to turn on minimal / patience
221228 * diff in drv->other_flags
222229 */
223230
231+ /* if no driver config found, fall back on AUTO driver */
232+ if (!found_driver )
233+ goto fail ;
234+
235+ /* store driver in registry */
236+ git_strmap_insert (reg -> drivers , drv -> name , drv , error );
237+ if (error < 0 )
238+ goto fail ;
239+
224240 * out = drv ;
225241 return 0 ;
226242
@@ -244,26 +260,25 @@ int git_diff_driver_lookup(
244260 if ((error = git_attr_get (& value , repo , 0 , path , "diff" )) < 0 )
245261 return error ;
246262
247- if (GIT_ATTR_FALSE (value )) {
263+ if (GIT_ATTR_UNSPECIFIED (value ))
264+ /* just use the auto value */ ;
265+ else if (GIT_ATTR_FALSE (value ))
248266 * out = & global_drivers [DIFF_DRIVER_BINARY ];
249- return 0 ;
250- }
251-
252- else if (GIT_ATTR_TRUE (value )) {
267+ else if (GIT_ATTR_TRUE (value ))
253268 * out = & global_drivers [DIFF_DRIVER_TEXT ];
254- return 0 ;
255- }
256269
257270 /* otherwise look for driver information in config and build driver */
258- if ((error = git_diff_driver_load (out , repo , value )) < 0 ) {
271+ else if ((error = git_diff_driver_load (out , repo , value )) < 0 ) {
259272 if (error != GIT_ENOTFOUND )
260273 return error ;
261274 else
262275 giterr_clear ();
263276 }
264277
265278use_auto :
266- * out = & global_drivers [DIFF_DRIVER_AUTO ];
279+ if (!* out )
280+ * out = & global_drivers [DIFF_DRIVER_AUTO ];
281+
267282 return 0 ;
268283}
269284
@@ -326,7 +341,7 @@ static int diff_context_line__pattern_match(
326341
327342 GIT_UNUSED (line_len );
328343
329- for (i = 0 ; i > git_array_size (driver -> fn_patterns ); ++ i ) {
344+ for (i = 0 ; i < git_array_size (driver -> fn_patterns ); ++ i ) {
330345 if (!regexec (git_array_get (driver -> fn_patterns , i ), line , 0 , NULL , 0 ))
331346 return true;
332347 }
0 commit comments