Hash :
c0eba379
Author :
Date :
2017-03-14T11:01:19
diff_parse: correctly set options for parsed diffs The function `diff_parsed_alloc` allocates and initializes a `git_diff_parsed` structure. This structure also contains diff options. While we initialize its flags, we fail to do a real initialization of its values. This bites us when we want to actually use the generated diff as we do not se the option's version field, which is required to operate correctly. Fix the issue by executing `git_diff_init_options` on the embedded struct.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/*
* 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 "diff.h"
#include "diff_parse.h"
#include "patch.h"
#include "patch_parse.h"
static void diff_parsed_free(git_diff *d)
{
git_diff_parsed *diff = (git_diff_parsed *)d;
git_patch *patch;
size_t i;
git_vector_foreach(&diff->patches, i, patch)
git_patch_free(patch);
git_vector_free(&diff->patches);
git_vector_free(&diff->base.deltas);
git_pool_clear(&diff->base.pool);
git__memzero(diff, sizeof(*diff));
git__free(diff);
}
static git_diff_parsed *diff_parsed_alloc(void)
{
git_diff_parsed *diff;
if ((diff = git__calloc(1, sizeof(git_diff_parsed))) == NULL)
return NULL;
GIT_REFCOUNT_INC(diff);
diff->base.type = GIT_DIFF_TYPE_PARSED;
diff->base.strcomp = git__strcmp;
diff->base.strncomp = git__strncmp;
diff->base.pfxcomp = git__prefixcmp;
diff->base.entrycomp = git_diff__entry_cmp;
diff->base.patch_fn = git_patch_parsed_from_diff;
diff->base.free_fn = diff_parsed_free;
git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION);
diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
git_pool_init(&diff->base.pool, 1);
if (git_vector_init(&diff->patches, 0, NULL) < 0 ||
git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) {
git_diff_free(&diff->base);
return NULL;
}
git_vector_set_cmp(&diff->base.deltas, git_diff_delta__cmp);
return diff;
}
int git_diff_from_buffer(
git_diff **out,
const char *content,
size_t content_len)
{
git_diff_parsed *diff;
git_patch *patch;
git_patch_parse_ctx *ctx = NULL;
int error = 0;
*out = NULL;
diff = diff_parsed_alloc();
GITERR_CHECK_ALLOC(diff);
ctx = git_patch_parse_ctx_init(content, content_len, NULL);
GITERR_CHECK_ALLOC(ctx);
while (ctx->remain_len) {
if ((error = git_patch_parse(&patch, ctx)) < 0)
break;
git_vector_insert(&diff->patches, patch);
git_vector_insert(&diff->base.deltas, patch->delta);
}
if (error == GIT_ENOTFOUND && git_vector_length(&diff->patches) > 0) {
giterr_clear();
error = 0;
}
git_patch_parse_ctx_free(ctx);
if (error < 0)
git_diff_free(&diff->base);
else
*out = &diff->base;
return error;
}