Line Flow Count Block(s) Source
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 "patch.h"
9 -
10 - #include "git2/patch.h"
11 - #include "diff.h"
12 -
13 912 2 int git_patch__invoke_callbacks(
14 - git_patch *patch,
15 - git_diff_file_cb file_cb,
16 - git_diff_binary_cb binary_cb,
17 - git_diff_hunk_cb hunk_cb,
18 - git_diff_line_cb line_cb,
19 - void *payload)
20 - {
21 912 2 int error = 0;
22 - uint32_t i, j;
23 -
24 912 2 if (file_cb)
25 912 3 error = file_cb(patch->delta, 0, payload);
26 -
27 912 4 if (error)
28 5 5 return error;
29 -
30 907 6 if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) {
31 40 7 if (binary_cb)
32 40 8 error = binary_cb(patch->delta, &patch->binary, payload);
33 -
34 40 9 return error;
35 - }
36 -
37 867 10,11 if (!hunk_cb && !line_cb)
38 181 12 return error;
39 -
40 1269 13,29-31 for (i = 0; !error && i < git_array_size(patch->hunks); ++i) {
41 583 14-16 git_patch_hunk *h = git_array_get(patch->hunks, i);
42 -
43 583 17 if (hunk_cb)
44 567 18 error = hunk_cb(patch->delta, &h->hunk, payload);
45 -
46 583 19 if (!line_cb)
47 ##### 20 continue;
48 -
49 7363 21,26-28 for (j = 0; !error && j < h->line_count; ++j) {
50 6780 25 git_diff_line *l =
51 6780 22-24 git_array_get(patch->lines, h->line_start + j);
52 -
53 6780 25 error = line_cb(patch->delta, &h->hunk, l, payload);
54 - }
55 - }
56 -
57 686 32 return error;
58 - }
59 -
60 8 2 size_t git_patch_size(
61 - git_patch *patch,
62 - int include_context,
63 - int include_hunk_headers,
64 - int include_file_headers)
65 - {
66 - size_t out;
67 -
68 8 2,3 assert(patch);
69 -
70 8 4 out = patch->content_size;
71 -
72 8 4 if (!include_context)
73 2 5 out -= patch->context_size;
74 -
75 8 6 if (include_hunk_headers)
76 4 7 out += patch->header_size;
77 -
78 8 8 if (include_file_headers) {
79 2 9 git_buf file_header = GIT_BUF_INIT;
80 -
81 2 9,10 if (git_diff_delta__format_file_header(
82 2 9 &file_header, patch->delta, NULL, NULL, 0, true) < 0)
83 ##### 11 git_error_clear();
84 - else
85 2 12,13 out += git_buf_len(&file_header);
86 -
87 2 14,15 git_buf_dispose(&file_header);
88 - }
89 -
90 8 16 return out;
91 - }
92 -
93 58 2 int git_patch_line_stats(
94 - size_t *total_ctxt,
95 - size_t *total_adds,
96 - size_t *total_dels,
97 - const git_patch *patch)
98 - {
99 - size_t totals[3], idx;
100 -
101 58 2 memset(totals, 0, sizeof(totals));
102 -
103 553 2,13,14 for (idx = 0; idx < git_array_size(patch->lines); ++idx) {
104 495 3-5 git_diff_line *line = git_array_get(patch->lines, idx);
105 495 6 if (!line)
106 ##### 7 continue;
107 -
108 495 8 switch (line->origin) {
109 192 9 case GIT_DIFF_LINE_CONTEXT: totals[0]++; break;
110 184 10 case GIT_DIFF_LINE_ADDITION: totals[1]++; break;
111 116 11 case GIT_DIFF_LINE_DELETION: totals[2]++; break;
112 - default:
113 - /* diff --stat and --numstat don't count EOFNL marks because
114 - * they will always be paired with a ADDITION or DELETION line.
115 - */
116 3 12 break;
117 - }
118 - }
119 -
120 58 15 if (total_ctxt)
121 9 16 *total_ctxt = totals[0];
122 58 17 if (total_adds)
123 58 18 *total_adds = totals[1];
124 58 19 if (total_dels)
125 58 20 *total_dels = totals[2];
126 -
127 58 21 return 0;
128 - }
129 -
130 373 2 const git_diff_delta *git_patch_get_delta(const git_patch *patch)
131 - {
132 373 2,3 assert(patch);
133 373 4 return patch->delta;
134 - }
135 -
136 170 2 size_t git_patch_num_hunks(const git_patch *patch)
137 - {
138 170 2,3 assert(patch);
139 170 4 return git_array_size(patch->hunks);
140 - }
141 -
142 34 2 static int patch_error_outofrange(const char *thing)
143 - {
144 34 2 git_error_set(GIT_ERROR_INVALID, "patch %s index out of range", thing);
145 34 3 return GIT_ENOTFOUND;
146 - }
147 -
148 106 2 int git_patch_get_hunk(
149 - const git_diff_hunk **out,
150 - size_t *lines_in_hunk,
151 - git_patch *patch,
152 - size_t hunk_idx)
153 - {
154 - git_patch_hunk *hunk;
155 106 2,3 assert(patch);
156 -
157 106 4-6 hunk = git_array_get(patch->hunks, hunk_idx);
158 -
159 106 7 if (!hunk) {
160 8 8,9 if (out) *out = NULL;
161 8 10,11 if (lines_in_hunk) *lines_in_hunk = 0;
162 8 12 return patch_error_outofrange("hunk");
163 - }
164 -
165 98 13,14 if (out) *out = &hunk->hunk;
166 98 15,16 if (lines_in_hunk) *lines_in_hunk = hunk->line_count;
167 98 17 return 0;
168 - }
169 -
170 29 2 int git_patch_num_lines_in_hunk(const git_patch *patch, size_t hunk_idx)
171 - {
172 - git_patch_hunk *hunk;
173 29 2,3 assert(patch);
174 -
175 29 4-7 if (!(hunk = git_array_get(patch->hunks, hunk_idx)))
176 ##### 8 return patch_error_outofrange("hunk");
177 29 9 return (int)hunk->line_count;
178 - }
179 -
180 380 2 int git_patch_get_line_in_hunk(
181 - const git_diff_line **out,
182 - git_patch *patch,
183 - size_t hunk_idx,
184 - size_t line_of_hunk)
185 - {
186 - git_patch_hunk *hunk;
187 - git_diff_line *line;
188 -
189 380 2,3 assert(patch);
190 -
191 380 4-7 if (!(hunk = git_array_get(patch->hunks, hunk_idx))) {
192 ##### 8,9 if (out) *out = NULL;
193 ##### 10 return patch_error_outofrange("hunk");
194 - }
195 -
196 380 11,15 if (line_of_hunk >= hunk->line_count ||
197 354 12-14 !(line = git_array_get(
198 - patch->lines, hunk->line_start + line_of_hunk))) {
199 26 16,17 if (out) *out = NULL;
200 26 18 return patch_error_outofrange("line");
201 - }
202 -
203 354 19,20 if (out) *out = line;
204 354 21 return 0;
205 - }
206 -
207 1243 2 int git_patch_from_diff(git_patch **out, git_diff *diff, size_t idx)
208 - {
209 1243 2-5 assert(out && diff && diff->patch_fn);
210 1243 6 return diff->patch_fn(out, diff, idx);
211 - }
212 -
213 1486 2 static void git_patch__free(git_patch *patch)
214 - {
215 1486 2 if (patch->free_fn)
216 1484 3 patch->free_fn(patch);
217 1486 4 }
218 -
219 1597 2 void git_patch_free(git_patch *patch)
220 - {
221 1597 2 if (patch)
222 1596 3-6 GIT_REFCOUNT_DEC(patch, git_patch__free);
223 1597 7 }