source src/patch.c
| 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 | } |