diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/diff.c | 104 | ||||
-rw-r--r-- | src/xdiff/xinclude.h | 6 |
2 files changed, 109 insertions, 1 deletions
diff --git a/src/diff.c b/src/diff.c new file mode 100644 index 000000000..7128b7c76 --- /dev/null +++ b/src/diff.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2009-2011 the libgit2 contributors + * + * 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/diff.h" +#include "xdiff/xdiff.h" +#include "blob.h" +#include <ctype.h> + +static int read_next_int(const char **str, int *value) +{ + const char *scan = *str; + int v = 0, digits = 0; + /* find next digit */ + for (scan = *str; *scan && !isdigit(*scan); scan++); + /* parse next number */ + for (; isdigit(*scan); scan++, digits++) + v = (v * 10) + (*scan - '0'); + *str = scan; + *value = v; + return (digits > 0) ? GIT_SUCCESS : GIT_ENOTFOUND; +} + +static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) +{ + int err = GIT_SUCCESS; + git_diff_opts *opts = priv; + + if (len == 1) { + int ostart = -1, olen = 0, nstart = -1, nlen = 0; + /* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */ + if (opts->hunk_cb && bufs[0].ptr[0] == '@') { + const char *scan = bufs[0].ptr; + if (!(err = read_next_int(&scan, &ostart)) && *scan == ',') + err = read_next_int(&scan, &olen); + if (!err && !(err = read_next_int(&scan, &nstart)) && *scan == ',') + err = read_next_int(&scan, &nlen); + if (!err && ostart >= 0 && nstart >= 0) + err = opts->hunk_cb( + opts->cb_data, ostart, olen, nstart, nlen); + } + } + else if (len == 2 || len == 3) { + int origin; + /* expect " "/"-"/"+", then data, then maybe newline */ + origin = + (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_ADDITION : + (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : + GIT_DIFF_LINE_CONTEXT; + + if (opts->line_cb) + err = opts->line_cb( + opts->cb_data, origin, bufs[1].ptr, bufs[1].size); + } + + return err; +} + +int git_diff_blobs( + git_repository *repo, + git_blob *old_blob, + git_blob *new_blob, + git_diff_opts *options) +{ + mmfile_t old, new; + xpparam_t params; + xdemitconf_t cfg; + xdemitcb_t callback; + + assert(repo && old_blob && new_blob && options); + + old.ptr = (char *)git_blob_rawcontent(old_blob); + old.size = git_blob_rawsize(old_blob); + + new.ptr = (char *)git_blob_rawcontent(new_blob); + new.size = git_blob_rawsize(new_blob); + + memset(¶ms, 0, sizeof(params)); + + memset(&cfg, 0, sizeof(cfg)); + cfg.ctxlen = options->context_lines || 3; + cfg.interhunkctxlen = options->interhunk_lines || 3; + if (options->ignore_whitespace) + cfg.flags |= XDF_WHITESPACE_FLAGS; + + memset(&callback, 0, sizeof(callback)); + callback.outf = diff_output_cb; + callback.priv = options; + + if (options->file_cb) + options->file_cb( + options->cb_data, + git_object_id((const git_object *)old_blob), NULL, 010644, + git_object_id((const git_object *)new_blob), NULL, 010644); + + xdl_diff(&old, &new, ¶ms, &cfg, &callback); + + return GIT_SUCCESS; +} + diff --git a/src/xdiff/xinclude.h b/src/xdiff/xinclude.h index 526ccb344..2928d329b 100644 --- a/src/xdiff/xinclude.h +++ b/src/xdiff/xinclude.h @@ -26,10 +26,14 @@ #include <ctype.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include <string.h> #include <limits.h> +#ifdef WIN32 +#else +#include <unistd.h> +#endif + #include "xmacros.h" #include "xdiff.h" #include "xtypes.h" |