diff options
Diffstat (limited to 'src/diff_driver.c')
-rw-r--r-- | src/diff_driver.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/diff_driver.c b/src/diff_driver.c new file mode 100644 index 000000000..5438afc67 --- /dev/null +++ b/src/diff_driver.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#include "common.h" + +#include "git2/attr.h" + +#include "diff.h" +#include "diff_patch.h" +#include "diff_driver.h" +#include "strmap.h" +#include "pool.h" +#include "map.h" +#include "buf_text.h" + +typedef enum { + DIFF_DRIVER_AUTO = 0, + DIFF_DRIVER_FALSE = 1, + DIFF_DRIVER_TRUE = 2, + DIFF_DRIVER_NAMED = 3, +} git_diff_driver_t; + +enum { + DIFF_CONTEXT_FIND_NORMAL = 0, + DIFF_CONTEXT_FIND_ICASE = (1 << 0), + DIFF_CONTEXT_FIND_EXT = (1 << 1), +}; + +/* data for finding function context for a given file type */ +struct git_diff_driver { + git_diff_driver_t type; + git_strarray fn_patterns; + int binary; +}; + +struct git_diff_driver_registry { + git_strmap *drivers; + git_pool strings; +}; + +static git_diff_driver global_drivers[3] = { + { DIFF_DRIVER_AUTO, { NULL, 0 }, -1 }, + { DIFF_DRIVER_FALSE, { NULL, 0 }, 1 }, + { DIFF_DRIVER_TRUE, { NULL, 0 }, 0 }, +}; + +git_diff_driver_registry *git_diff_driver_registry_new() +{ + return git__calloc(1, sizeof(git_diff_driver_registry)); +} + +void git_diff_driver_registry_free(git_diff_driver_registry *reg) +{ + git__free(reg); +} + +int git_diff_driver_lookup( + git_diff_driver **out, git_repository *repo, const char *path) +{ + const char *value; + + assert(out); + + if (!repo || !path || !strlen(path)) + goto use_auto; + + if (git_attr_get(&value, repo, 0, path, "diff") < 0) + return -1; + + if (GIT_ATTR_FALSE(value)) { + *out = &global_drivers[DIFF_DRIVER_FALSE]; + return 0; + } + + else if (GIT_ATTR_TRUE(value)) { + *out = &global_drivers[DIFF_DRIVER_TRUE]; + return 0; + } + + /* otherwise look for driver information in config and build driver */ + +use_auto: + *out = &global_drivers[DIFF_DRIVER_AUTO]; + return 0; +} + +void git_diff_driver_free(git_diff_driver *driver) +{ + GIT_UNUSED(driver); + /* do nothing for now */ +} + +int git_diff_driver_is_binary(git_diff_driver *driver) +{ + return driver ? driver->binary : -1; +} + +int git_diff_driver_content_is_binary( + git_diff_driver *driver, const char *content, size_t content_len) +{ + const git_buf search = { (char *)content, 0, min(content_len, 4000) }; + + GIT_UNUSED(driver); + + /* TODO: provide encoding / binary detection callbacks that can + * be UTF-8 aware, etc. For now, instead of trying to be smart, + * let's just use the simple NUL-byte detection that core git uses. + */ + + /* previously was: if (git_buf_text_is_binary(&search)) */ + if (git_buf_text_contains_nul(&search)) + return 1; + + return 0; +} + +static long diff_context_find( + const char *line, + long line_len, + char *out, + long out_size, + void *payload) +{ + git_diff_driver *driver = payload; + const char *scan; + + GIT_UNUSED(driver); + + if (line_len > 0 && line[line_len - 1] == '\n') + line_len--; + if (line_len > 0 && line[line_len - 1] == '\r') + line_len--; + if (!line_len) + return -1; + + if (!git__isalpha(*line) && *line != '_' && *line != '$') + return -1; + + for (scan = &line[line_len-1]; scan > line && git__isspace(*scan); --scan) + /* search backward for non-space */; + line_len = scan - line; + + if (line_len >= out_size) + line_len = out_size - 1; + + memcpy(out, line, line_len); + out[line_len] = '\0'; + + return line_len; +} + +git_diff_find_context_fn git_diff_driver_find_content_fn(git_diff_driver *driver) +{ + GIT_UNUSED(driver); + return diff_context_find; +} + |