]> git.proxmox.com Git - libgit2.git/blob - src/diff_parse.c
b4c76a3eb7074e69b1515907628a2453a34e87e0
[libgit2.git] / src / diff_parse.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "diff_parse.h"
9
10 #include "diff.h"
11 #include "patch.h"
12 #include "patch_parse.h"
13
14 static void diff_parsed_free(git_diff *d)
15 {
16 git_diff_parsed *diff = (git_diff_parsed *)d;
17 git_patch *patch;
18 size_t i;
19
20 git_vector_foreach(&diff->patches, i, patch)
21 git_patch_free(patch);
22
23 git_vector_free(&diff->patches);
24
25 git_vector_free(&diff->base.deltas);
26 git_pool_clear(&diff->base.pool);
27
28 git__memzero(diff, sizeof(*diff));
29 git__free(diff);
30 }
31
32 static git_diff_parsed *diff_parsed_alloc(void)
33 {
34 git_diff_parsed *diff;
35
36 if ((diff = git__calloc(1, sizeof(git_diff_parsed))) == NULL)
37 return NULL;
38
39 GIT_REFCOUNT_INC(&diff->base);
40 diff->base.type = GIT_DIFF_TYPE_PARSED;
41 diff->base.strcomp = git__strcmp;
42 diff->base.strncomp = git__strncmp;
43 diff->base.pfxcomp = git__prefixcmp;
44 diff->base.entrycomp = git_diff__entry_cmp;
45 diff->base.patch_fn = git_patch_parsed_from_diff;
46 diff->base.free_fn = diff_parsed_free;
47
48 if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) {
49 git__free(diff);
50 return NULL;
51 }
52
53 diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
54
55 git_pool_init(&diff->base.pool, 1);
56
57 if (git_vector_init(&diff->patches, 0, NULL) < 0 ||
58 git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) {
59 git_diff_free(&diff->base);
60 return NULL;
61 }
62
63 git_vector_set_cmp(&diff->base.deltas, git_diff_delta__cmp);
64
65 return diff;
66 }
67
68 int git_diff_from_buffer(
69 git_diff **out,
70 const char *content,
71 size_t content_len)
72 {
73 git_diff_parsed *diff;
74 git_patch *patch;
75 git_patch_parse_ctx *ctx = NULL;
76 int error = 0;
77
78 *out = NULL;
79
80 diff = diff_parsed_alloc();
81 GIT_ERROR_CHECK_ALLOC(diff);
82
83 ctx = git_patch_parse_ctx_init(content, content_len, NULL);
84 GIT_ERROR_CHECK_ALLOC(ctx);
85
86 while (ctx->parse_ctx.remain_len) {
87 if ((error = git_patch_parse(&patch, ctx)) < 0)
88 break;
89
90 git_vector_insert(&diff->patches, patch);
91 git_vector_insert(&diff->base.deltas, patch->delta);
92 }
93
94 if (error == GIT_ENOTFOUND && git_vector_length(&diff->patches) > 0) {
95 git_error_clear();
96 error = 0;
97 }
98
99 git_patch_parse_ctx_free(ctx);
100
101 if (error < 0)
102 git_diff_free(&diff->base);
103 else
104 *out = &diff->base;
105
106 return error;
107 }
108