diff: clarify textconv interface

The memory allocation scheme for the textconv interface is a bit tricky, and not well documented. It was originally designed as an internal part of diff.c (matching fill_mmfile), but gradually was made public. Refactoring it is difficult, but we can at least improve the situation by documenting the intended flow and enforcing it with an in-code assertion. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 22, 2016 at 13:28 UTC a64e6a44c63a965c5bc26242ddd3ed049b42e117
3 files changed +24 -1
diff.c
+4 -1
@@ -4996,7 +4996,7 @@ size_t fill_textconv(struct userdiff_driver *driver,
4996 {
4997 size_t size;
4998
4999 - if (!driver || !driver->textconv) {
4999 + if (!driver) {
5000 if (!DIFF_FILE_VALID(df)) {
5001 *outbuf = "";
5002 return 0;
@@ -5007,6 +5007,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
5007 return df->size;
5008 }
5009
5010 + if (!driver->textconv)
5011 + die("BUG: fill_textconv called with non-textconv driver");
5012 +
5013 if (driver->textconv_cache && df->sha1_valid) {
5014 *outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
5015 &size);
diff.h
+16
@@ -342,10 +342,26 @@ extern void diff_no_index(struct rev_info *, int, const char **, const char *);
342
343 extern int index_differs_from(const char *def, int diff_flags);
344
345 +/*
346 + * Fill the contents of the filespec "df", respecting any textconv defined by
347 + * its userdiff driver. The "driver" parameter must come from a
348 + * previous call to get_textconv(), and therefore should either be NULL or have
349 + * textconv enabled.
350 + *
351 + * Note that the memory ownership of the resulting buffer depends on whether
352 + * the driver field is NULL. If it is, then the memory belongs to the filespec
353 + * struct. If it is non-NULL, then "outbuf" points to a newly allocated buffer
354 + * that should be freed by the caller.
355 + */
356 extern size_t fill_textconv(struct userdiff_driver *driver,
357 struct diff_filespec *df,
358 char **outbuf);
359
360 +/*
361 + * Look up the userdiff driver for the given filespec, and return it if
362 + * and only if it has textconv enabled (otherwise return NULL). The result
363 + * can be passed to fill_textconv().
364 + */
365 extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
366
367 extern int parse_rename_score(const char **cp_p);
userdiff.h
+4
@@ -23,6 +23,10 @@ int userdiff_config(const char *k, const char *v);
23 struct userdiff_driver *userdiff_find_by_name(const char *name);
24 struct userdiff_driver *userdiff_find_by_path(const char *path);
25
26 +/*
27 + * Initialize any textconv-related fields in the driver and return it, or NULL
28 + * if it does not have textconv enabled at all.
29 + */
30 struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver);
31
32 #endif /* USERDIFF */