1 #include "git2/patch.h"
6 int git_patch__invoke_callbacks(
8 git_diff_file_cb file_cb
,
9 git_diff_binary_cb binary_cb
,
10 git_diff_hunk_cb hunk_cb
,
11 git_diff_line_cb line_cb
,
18 error
= file_cb(patch
->delta
, 0, payload
);
23 if ((patch
->delta
->flags
& GIT_DIFF_FLAG_BINARY
) != 0) {
25 error
= binary_cb(patch
->delta
, &patch
->binary
, payload
);
30 if (!hunk_cb
&& !line_cb
)
33 for (i
= 0; !error
&& i
< git_array_size(patch
->hunks
); ++i
) {
34 git_patch_hunk
*h
= git_array_get(patch
->hunks
, i
);
37 error
= hunk_cb(patch
->delta
, &h
->hunk
, payload
);
42 for (j
= 0; !error
&& j
< h
->line_count
; ++j
) {
44 git_array_get(patch
->lines
, h
->line_start
+ j
);
46 error
= line_cb(patch
->delta
, &h
->hunk
, l
, payload
);
53 size_t git_patch_size(
56 int include_hunk_headers
,
57 int include_file_headers
)
63 out
= patch
->content_size
;
66 out
-= patch
->context_size
;
68 if (include_hunk_headers
)
69 out
+= patch
->header_size
;
71 if (include_file_headers
) {
72 git_buf file_header
= GIT_BUF_INIT
;
74 if (git_diff_delta__format_file_header(
75 &file_header
, patch
->delta
, NULL
, NULL
, 0) < 0)
78 out
+= git_buf_len(&file_header
);
80 git_buf_free(&file_header
);
86 int git_patch_line_stats(
90 const git_patch
*patch
)
92 size_t totals
[3], idx
;
94 memset(totals
, 0, sizeof(totals
));
96 for (idx
= 0; idx
< git_array_size(patch
->lines
); ++idx
) {
97 git_diff_line
*line
= git_array_get(patch
->lines
, idx
);
101 switch (line
->origin
) {
102 case GIT_DIFF_LINE_CONTEXT
: totals
[0]++; break;
103 case GIT_DIFF_LINE_ADDITION
: totals
[1]++; break;
104 case GIT_DIFF_LINE_DELETION
: totals
[2]++; break;
106 /* diff --stat and --numstat don't count EOFNL marks because
107 * they will always be paired with a ADDITION or DELETION line.
114 *total_ctxt
= totals
[0];
116 *total_adds
= totals
[1];
118 *total_dels
= totals
[2];
123 const git_diff_delta
*git_patch_get_delta(const git_patch
*patch
)
129 size_t git_patch_num_hunks(const git_patch
*patch
)
132 return git_array_size(patch
->hunks
);
135 static int patch_error_outofrange(const char *thing
)
137 giterr_set(GITERR_INVALID
, "patch %s index out of range", thing
);
138 return GIT_ENOTFOUND
;
141 int git_patch_get_hunk(
142 const git_diff_hunk
**out
,
143 size_t *lines_in_hunk
,
147 git_patch_hunk
*hunk
;
150 hunk
= git_array_get(patch
->hunks
, hunk_idx
);
153 if (out
) *out
= NULL
;
154 if (lines_in_hunk
) *lines_in_hunk
= 0;
155 return patch_error_outofrange("hunk");
158 if (out
) *out
= &hunk
->hunk
;
159 if (lines_in_hunk
) *lines_in_hunk
= hunk
->line_count
;
163 int git_patch_num_lines_in_hunk(const git_patch
*patch
, size_t hunk_idx
)
165 git_patch_hunk
*hunk
;
168 if (!(hunk
= git_array_get(patch
->hunks
, hunk_idx
)))
169 return patch_error_outofrange("hunk");
170 return (int)hunk
->line_count
;
173 int git_patch_get_line_in_hunk(
174 const git_diff_line
**out
,
179 git_patch_hunk
*hunk
;
184 if (!(hunk
= git_array_get(patch
->hunks
, hunk_idx
))) {
185 if (out
) *out
= NULL
;
186 return patch_error_outofrange("hunk");
189 if (line_of_hunk
>= hunk
->line_count
||
190 !(line
= git_array_get(
191 patch
->lines
, hunk
->line_start
+ line_of_hunk
))) {
192 if (out
) *out
= NULL
;
193 return patch_error_outofrange("line");
196 if (out
) *out
= line
;
200 int git_patch_from_diff(git_patch
**out
, git_diff
*diff
, size_t idx
)
202 assert(out
&& diff
&& diff
->patch_fn
);
203 return diff
->patch_fn(out
, diff
, idx
);
206 static void git_patch__free(git_patch
*patch
)
209 patch
->free_fn(patch
);
212 void git_patch_free(git_patch
*patch
)
215 GIT_REFCOUNT_DEC(patch
, git_patch__free
);