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>
This commit is contained in:
Jeff King 2016-02-22 13:28:54 -05:00 committed by Junio C Hamano
parent a2558fb8e1
commit a64e6a44c6
3 changed files with 24 additions and 1 deletions

5
diff.c
View File

@ -4996,7 +4996,7 @@ size_t fill_textconv(struct userdiff_driver *driver,
{ {
size_t size; size_t size;
if (!driver || !driver->textconv) { if (!driver) {
if (!DIFF_FILE_VALID(df)) { if (!DIFF_FILE_VALID(df)) {
*outbuf = ""; *outbuf = "";
return 0; return 0;
@ -5007,6 +5007,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
return df->size; return df->size;
} }
if (!driver->textconv)
die("BUG: fill_textconv called with non-textconv driver");
if (driver->textconv_cache && df->sha1_valid) { if (driver->textconv_cache && df->sha1_valid) {
*outbuf = notes_cache_get(driver->textconv_cache, df->sha1, *outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
&size); &size);

16
diff.h
View File

@ -342,10 +342,26 @@ extern void diff_no_index(struct rev_info *, int, const char **, const char *);
extern int index_differs_from(const char *def, int diff_flags); extern int index_differs_from(const char *def, int diff_flags);
/*
* Fill the contents of the filespec "df", respecting any textconv defined by
* its userdiff driver. The "driver" parameter must come from a
* previous call to get_textconv(), and therefore should either be NULL or have
* textconv enabled.
*
* Note that the memory ownership of the resulting buffer depends on whether
* the driver field is NULL. If it is, then the memory belongs to the filespec
* struct. If it is non-NULL, then "outbuf" points to a newly allocated buffer
* that should be freed by the caller.
*/
extern size_t fill_textconv(struct userdiff_driver *driver, extern size_t fill_textconv(struct userdiff_driver *driver,
struct diff_filespec *df, struct diff_filespec *df,
char **outbuf); char **outbuf);
/*
* Look up the userdiff driver for the given filespec, and return it if
* and only if it has textconv enabled (otherwise return NULL). The result
* can be passed to fill_textconv().
*/
extern struct userdiff_driver *get_textconv(struct diff_filespec *one); extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
extern int parse_rename_score(const char **cp_p); extern int parse_rename_score(const char **cp_p);

View File

@ -23,6 +23,10 @@ int userdiff_config(const char *k, const char *v);
struct userdiff_driver *userdiff_find_by_name(const char *name); struct userdiff_driver *userdiff_find_by_name(const char *name);
struct userdiff_driver *userdiff_find_by_path(const char *path); struct userdiff_driver *userdiff_find_by_path(const char *path);
/*
* Initialize any textconv-related fields in the driver and return it, or NULL
* if it does not have textconv enabled at all.
*/
struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver); struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver);
#endif /* USERDIFF */ #endif /* USERDIFF */