source src/diff_file.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 "diff_file.h" | ||
| 9 | - | |||
| 10 | - | #include "git2/blob.h" | ||
| 11 | - | #include "git2/submodule.h" | ||
| 12 | - | #include "diff.h" | ||
| 13 | - | #include "diff_generate.h" | ||
| 14 | - | #include "odb.h" | ||
| 15 | - | #include "futils.h" | ||
| 16 | - | #include "filter.h" | ||
| 17 | - | |||
| 18 | - | #define DIFF_MAX_FILESIZE 0x20000000 | ||
| 19 | - | |||
| 20 | ![]() |
3656 | 2 | static bool diff_file_content_binary_by_size(git_diff_file_content *fc) |
| 21 | - | { | ||
| 22 | - | /* if we have diff opts, check max_size vs file size */ | ||
| 23 | 3656 | 2,3 | if ((fc->file->flags & DIFF_FLAGS_KNOWN_BINARY) == 0 && | |
| 24 | 3025 | 3,4 | fc->opts_max_size > 0 && | |
| 25 | 2957 | 4 | fc->file->size > fc->opts_max_size) | |
| 26 | 4 | 5 | fc->file->flags |= GIT_DIFF_FLAG_BINARY; | |
| 27 | - | |||
| 28 | 3656 | 6 | return ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0); | |
| 29 | - | } | ||
| 30 | - | |||
| 31 | 2500 | 2 | static void diff_file_content_binary_by_content(git_diff_file_content *fc) | |
| 32 | - | { | ||
| 33 | 2500 | 2 | if ((fc->file->flags & DIFF_FLAGS_KNOWN_BINARY) != 0) | |
| 34 | 2500 | 3,9 | return; | |
| 35 | - | |||
| 36 | 2087 | 4,4,5 | switch (git_diff_driver_content_is_binary( | |
| 37 | 2087 | 4 | fc->driver, fc->map.data, fc->map.len)) { | |
| 38 | 2035 | 6 | case 0: fc->file->flags |= GIT_DIFF_FLAG_NOT_BINARY; break; | |
| 39 | 52 | 7 | case 1: fc->file->flags |= GIT_DIFF_FLAG_BINARY; break; | |
| 40 | ##### | 8 | default: break; | |
| 41 | - | } | ||
| 42 | - | } | ||
| 43 | - | |||
| 44 | ![]() |
2528 | 2 | static int diff_file_content_init_common( |
| 45 | - | git_diff_file_content *fc, const git_diff_options *opts) | ||
| 46 | - | { | ||
| 47 | 2528 | 2-4 | fc->opts_flags = opts ? opts->flags : GIT_DIFF_NORMAL; | |
| 48 | - | |||
| 49 | 2528 | 5,6 | if (opts && opts->max_size >= 0) | |
| 50 | 2460 | 7-10 | fc->opts_max_size = opts->max_size ? | |
| 51 | 26 | 8 | opts->max_size : DIFF_MAX_FILESIZE; | |
| 52 | - | |||
| 53 | 2528 | 11 | if (fc->src == GIT_ITERATOR_EMPTY) | |
| 54 | 277 | 12 | fc->src = GIT_ITERATOR_TREE; | |
| 55 | - | |||
| 56 | 2528 | 13,15 | if (!fc->driver && | |
| 57 | 264 | 14 | git_diff_driver_lookup(&fc->driver, fc->repo, | |
| 58 | 264 | 14 | NULL, fc->file->path) < 0) | |
| 59 | ##### | 16 | return -1; | |
| 60 | - | |||
| 61 | - | /* give driver a chance to modify options */ | ||
| 62 | 2528 | 17 | git_diff_driver_update_options(&fc->opts_flags, fc->driver); | |
| 63 | - | |||
| 64 | - | /* make sure file is conceivable mmap-able */ | ||
| 65 | - | if ((size_t)fc->file->size != fc->file->size) | ||
| 66 | - | fc->file->flags |= GIT_DIFF_FLAG_BINARY; | ||
| 67 | - | /* check if user is forcing text diff the file */ | ||
| 68 | 2528 | 18 | else if (fc->opts_flags & GIT_DIFF_FORCE_TEXT) { | |
| 69 | 28 | 19 | fc->file->flags &= ~GIT_DIFF_FLAG_BINARY; | |
| 70 | 28 | 19 | fc->file->flags |= GIT_DIFF_FLAG_NOT_BINARY; | |
| 71 | - | } | ||
| 72 | - | /* check if user is forcing binary diff the file */ | ||
| 73 | 2500 | 20 | else if (fc->opts_flags & GIT_DIFF_FORCE_BINARY) { | |
| 74 | 32 | 21 | fc->file->flags &= ~GIT_DIFF_FLAG_NOT_BINARY; | |
| 75 | 32 | 21 | fc->file->flags |= GIT_DIFF_FLAG_BINARY; | |
| 76 | - | } | ||
| 77 | - | |||
| 78 | 2528 | 22 | diff_file_content_binary_by_size(fc); | |
| 79 | - | |||
| 80 | 2528 | 23 | if ((fc->flags & GIT_DIFF_FLAG__NO_DATA) != 0) { | |
| 81 | 977 | 24 | fc->flags |= GIT_DIFF_FLAG__LOADED; | |
| 82 | 977 | 24 | fc->map.len = 0; | |
| 83 | 977 | 24 | fc->map.data = ""; | |
| 84 | - | } | ||
| 85 | - | |||
| 86 | 2528 | 25 | if ((fc->flags & GIT_DIFF_FLAG__LOADED) != 0) | |
| 87 | 1217 | 26 | diff_file_content_binary_by_content(fc); | |
| 88 | - | |||
| 89 | 2528 | 27 | return 0; | |
| 90 | - | } | ||
| 91 | - | |||
| 92 | ![]() |
2264 | 2 | int git_diff_file_content__init_from_diff( |
| 93 | - | git_diff_file_content *fc, | ||
| 94 | - | git_diff *diff, | ||
| 95 | - | git_diff_delta *delta, | ||
| 96 | - | bool use_old) | ||
| 97 | - | { | ||
| 98 | 2264 | 2 | bool has_data = true; | |
| 99 | - | |||
| 100 | 2264 | 2 | memset(fc, 0, sizeof(*fc)); | |
| 101 | 2264 | 2 | fc->repo = diff->repo; | |
| 102 | 2264 | 2-4 | fc->file = use_old ? &delta->old_file : &delta->new_file; | |
| 103 | 2264 | 5-7 | fc->src = use_old ? diff->old_src : diff->new_src; | |
| 104 | - | |||
| 105 | 2264 | 8,9 | if (git_diff_driver_lookup(&fc->driver, fc->repo, | |
| 106 | 2264 | 8 | &diff->attrsession, fc->file->path) < 0) | |
| 107 | ##### | 10 | return -1; | |
| 108 | - | |||
| 109 | 2264 | 11 | switch (delta->status) { | |
| 110 | - | case GIT_DELTA_ADDED: | ||
| 111 | 200 | 12 | has_data = !use_old; break; | |
| 112 | - | case GIT_DELTA_DELETED: | ||
| 113 | 454 | 13 | has_data = use_old; break; | |
| 114 | - | case GIT_DELTA_UNTRACKED: | ||
| 115 | 448 | 14-17 | has_data = !use_old && | |
| 116 | 224 | 15 | (diff->opts.flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) != 0; | |
| 117 | 448 | 18 | break; | |
| 118 | - | case GIT_DELTA_UNREADABLE: | ||
| 119 | - | case GIT_DELTA_MODIFIED: | ||
| 120 | - | case GIT_DELTA_COPIED: | ||
| 121 | - | case GIT_DELTA_RENAMED: | ||
| 122 | 974 | 19 | break; | |
| 123 | - | default: | ||
| 124 | 188 | 20 | has_data = false; | |
| 125 | 188 | 20 | break; | |
| 126 | - | } | ||
| 127 | - | |||
| 128 | 2264 | 21 | if (!has_data) | |
| 129 | 953 | 22 | fc->flags |= GIT_DIFF_FLAG__NO_DATA; | |
| 130 | - | |||
| 131 | 2264 | 23 | return diff_file_content_init_common(fc, &diff->opts); | |
| 132 | - | } | ||
| 133 | - | |||
| 134 | ![]() |
264 | 2 | int git_diff_file_content__init_from_src( |
| 135 | - | git_diff_file_content *fc, | ||
| 136 | - | git_repository *repo, | ||
| 137 | - | const git_diff_options *opts, | ||
| 138 | - | const git_diff_file_content_src *src, | ||
| 139 | - | git_diff_file *as_file) | ||
| 140 | - | { | ||
| 141 | 264 | 2 | memset(fc, 0, sizeof(*fc)); | |
| 142 | 264 | 2 | fc->repo = repo; | |
| 143 | 264 | 2 | fc->file = as_file; | |
| 144 | - | |||
| 145 | 264 | 2,3 | if (!src->blob && !src->buf) { | |
| 146 | 24 | 4 | fc->flags |= GIT_DIFF_FLAG__NO_DATA; | |
| 147 | - | } else { | ||
| 148 | 240 | 5 | fc->flags |= GIT_DIFF_FLAG__LOADED; | |
| 149 | 240 | 5 | fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; | |
| 150 | 240 | 5 | fc->file->mode = GIT_FILEMODE_BLOB; | |
| 151 | - | |||
| 152 | 240 | 5 | if (src->blob) { | |
| 153 | 90 | 6 | git_blob_dup((git_blob **)&fc->blob, (git_blob *) src->blob); | |
| 154 | 90 | 7 | fc->file->size = git_blob_rawsize(src->blob); | |
| 155 | 90 | 8,9 | git_oid_cpy(&fc->file->id, git_blob_id(src->blob)); | |
| 156 | 90 | 10 | fc->file->id_abbrev = GIT_OID_HEXSZ; | |
| 157 | - | |||
| 158 | 90 | 10 | fc->map.len = (size_t)fc->file->size; | |
| 159 | 90 | 10 | fc->map.data = (char *)git_blob_rawcontent(src->blob); | |
| 160 | - | |||
| 161 | 90 | 11 | fc->flags |= GIT_DIFF_FLAG__FREE_BLOB; | |
| 162 | - | } else { | ||
| 163 | 150 | 12 | fc->file->size = src->buflen; | |
| 164 | 150 | 12 | git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB); | |
| 165 | 150 | 13 | fc->file->id_abbrev = GIT_OID_HEXSZ; | |
| 166 | - | |||
| 167 | 150 | 13 | fc->map.len = src->buflen; | |
| 168 | 150 | 13 | fc->map.data = (char *)src->buf; | |
| 169 | - | } | ||
| 170 | - | } | ||
| 171 | - | |||
| 172 | 264 | 14 | return diff_file_content_init_common(fc, opts); | |
| 173 | - | } | ||
| 174 | - | |||
| 175 | ![]() |
81 | 2 | static int diff_file_content_commit_to_str( |
| 176 | - | git_diff_file_content *fc, bool check_status) | ||
| 177 | - | { | ||
| 178 | - | char oid[GIT_OID_HEXSZ+1]; | ||
| 179 | 81 | 2 | git_buf content = GIT_BUF_INIT; | |
| 180 | 81 | 2 | const char *status = ""; | |
| 181 | - | |||
| 182 | 81 | 2 | if (check_status) { | |
| 183 | 43 | 3 | int error = 0; | |
| 184 | 43 | 3 | git_submodule *sm = NULL; | |
| 185 | 43 | 3 | unsigned int sm_status = 0; | |
| 186 | - | const git_oid *sm_head; | ||
| 187 | - | |||
| 188 | 43 | 3,4 | if ((error = git_submodule_lookup(&sm, fc->repo, fc->file->path)) < 0) { | |
| 189 | - | /* GIT_EEXISTS means a "submodule" that has not been git added */ | ||
| 190 | ##### | 5 | if (error == GIT_EEXISTS) { | |
| 191 | ##### | 6 | git_error_clear(); | |
| 192 | ##### | 7 | error = 0; | |
| 193 | - | } | ||
| 194 | ##### | 8,24 | return error; | |
| 195 | - | } | ||
| 196 | - | |||
| 197 | 43 | 9,10 | if ((error = git_submodule_status(&sm_status, fc->repo, fc->file->path, GIT_SUBMODULE_IGNORE_UNSPECIFIED)) < 0) { | |
| 198 | ##### | 11 | git_submodule_free(sm); | |
| 199 | ##### | 12 | return error; | |
| 200 | - | } | ||
| 201 | - | |||
| 202 | - | /* update OID if we didn't have it previously */ | ||
| 203 | 43 | 13-15 | if ((fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0 && | |
| 204 | 42 | 14,16,17 | ((sm_head = git_submodule_wd_id(sm)) != NULL || | |
| 205 | ##### | 16 | (sm_head = git_submodule_head_id(sm)) != NULL)) | |
| 206 | - | { | ||
| 207 | 42 | 18 | git_oid_cpy(&fc->file->id, sm_head); | |
| 208 | 42 | 19 | fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; | |
| 209 | - | } | ||
| 210 | - | |||
| 211 | 43 | 20 | if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) | |
| 212 | 24 | 21 | status = "-dirty"; | |
| 213 | - | |||
| 214 | 43 | 22,23 | git_submodule_free(sm); | |
| 215 | - | } | ||
| 216 | - | |||
| 217 | 81 | 25 | git_oid_tostr(oid, sizeof(oid), &fc->file->id); | |
| 218 | 81 | 26,27 | if (git_buf_printf(&content, "Subproject commit %s%s\n", oid, status) < 0) | |
| 219 | ##### | 28 | return -1; | |
| 220 | - | |||
| 221 | 81 | 29 | fc->map.len = git_buf_len(&content); | |
| 222 | 81 | 30 | fc->map.data = git_buf_detach(&content); | |
| 223 | 81 | 31 | fc->flags |= GIT_DIFF_FLAG__FREE_DATA; | |
| 224 | - | |||
| 225 | 81 | 31 | return 0; | |
| 226 | - | } | ||
| 227 | - | |||
| 228 | 986 | 2 | static int diff_file_content_load_blob( | |
| 229 | - | git_diff_file_content *fc, | ||
| 230 | - | git_diff_options *opts) | ||
| 231 | - | { | ||
| 232 | 986 | 2 | int error = 0; | |
| 233 | 986 | 2 | git_odb_object *odb_obj = NULL; | |
| 234 | - | |||
| 235 | 986 | 2,3 | if (git_oid_is_zero(&fc->file->id)) | |
| 236 | ##### | 4 | return 0; | |
| 237 | - | |||
| 238 | 986 | 5 | if (fc->file->mode == GIT_FILEMODE_COMMIT) | |
| 239 | 38 | 6 | return diff_file_content_commit_to_str(fc, false); | |
| 240 | - | |||
| 241 | - | /* if we don't know size, try to peek at object header first */ | ||
| 242 | 948 | 7 | if (!fc->file->size) { | |
| 243 | 372 | 8,9 | if ((error = git_diff_file__resolve_zero_size( | |
| 244 | - | fc->file, &odb_obj, fc->repo)) < 0) | ||
| 245 | ##### | 10 | return error; | |
| 246 | - | } | ||
| 247 | - | |||
| 248 | 948 | 11,13 | if ((opts->flags & GIT_DIFF_SHOW_BINARY) == 0 && | |
| 249 | 881 | 12 | diff_file_content_binary_by_size(fc)) | |
| 250 | ##### | 14 | return 0; | |
| 251 | - | |||
| 252 | 948 | 15 | if (odb_obj != NULL) { | |
| 253 | ##### | 16,16 | error = git_object__from_odb_object( | |
| 254 | ##### | 16 | (git_object **)&fc->blob, fc->repo, odb_obj, GIT_OBJECT_BLOB); | |
| 255 | ##### | 17 | git_odb_object_free(odb_obj); | |
| 256 | - | } else { | ||
| 257 | 948 | 18,18 | error = git_blob_lookup( | |
| 258 | 948 | 18,18 | (git_blob **)&fc->blob, fc->repo, &fc->file->id); | |
| 259 | - | } | ||
| 260 | - | |||
| 261 | 948 | 19 | if (!error) { | |
| 262 | 948 | 20 | fc->flags |= GIT_DIFF_FLAG__FREE_BLOB; | |
| 263 | 948 | 20 | fc->map.data = (void *)git_blob_rawcontent(fc->blob); | |
| 264 | 948 | 21,22 | fc->map.len = (size_t)git_blob_rawsize(fc->blob); | |
| 265 | - | } | ||
| 266 | - | |||
| 267 | 948 | 23 | return error; | |
| 268 | - | } | ||
| 269 | - | |||
| 270 | ##### | 2 | static int diff_file_content_load_workdir_symlink_fake( | |
| 271 | - | git_diff_file_content *fc, git_buf *path) | ||
| 272 | - | { | ||
| 273 | ##### | 2 | git_buf target = GIT_BUF_INIT; | |
| 274 | - | int error; | ||
| 275 | - | |||
| 276 | ##### | 2,3 | if ((error = git_futils_readbuffer(&target, path->ptr)) < 0) | |
| 277 | ##### | 4 | return error; | |
| 278 | - | |||
| 279 | ##### | 5 | fc->map.len = git_buf_len(&target); | |
| 280 | ##### | 6 | fc->map.data = git_buf_detach(&target); | |
| 281 | ##### | 7 | fc->flags |= GIT_DIFF_FLAG__FREE_DATA; | |
| 282 | - | |||
| 283 | ##### | 7 | git_buf_dispose(&target); | |
| 284 | ##### | 8 | return error; | |
| 285 | - | } | ||
| 286 | - | |||
| 287 | ##### | 2 | static int diff_file_content_load_workdir_symlink( | |
| 288 | - | git_diff_file_content *fc, git_buf *path) | ||
| 289 | - | { | ||
| 290 | - | ssize_t alloc_len, read_len; | ||
| 291 | - | int symlink_supported, error; | ||
| 292 | - | |||
| 293 | ##### | 2,3 | if ((error = git_repository__configmap_lookup( | |
| 294 | - | &symlink_supported, fc->repo, GIT_CONFIGMAP_SYMLINKS)) < 0) | ||
| 295 | ##### | 4 | return -1; | |
| 296 | - | |||
| 297 | ##### | 5 | if (!symlink_supported) | |
| 298 | ##### | 6 | return diff_file_content_load_workdir_symlink_fake(fc, path); | |
| 299 | - | |||
| 300 | - | /* link path on disk could be UTF-16, so prepare a buffer that is | ||
| 301 | - | * big enough to handle some UTF-8 data expansion | ||
| 302 | - | */ | ||
| 303 | ##### | 7 | alloc_len = (ssize_t)(fc->file->size * 2) + 1; | |
| 304 | - | |||
| 305 | ##### | 7 | fc->map.data = git__calloc(alloc_len, sizeof(char)); | |
| 306 | ##### | 8,9 | GIT_ERROR_CHECK_ALLOC(fc->map.data); | |
| 307 | - | |||
| 308 | ##### | 10 | fc->flags |= GIT_DIFF_FLAG__FREE_DATA; | |
| 309 | - | |||
| 310 | ##### | 10,11 | read_len = p_readlink(git_buf_cstr(path), fc->map.data, alloc_len); | |
| 311 | ##### | 12 | if (read_len < 0) { | |
| 312 | ##### | 13 | git_error_set(GIT_ERROR_OS, "failed to read symlink '%s'", fc->file->path); | |
| 313 | ##### | 14 | return -1; | |
| 314 | - | } | ||
| 315 | - | |||
| 316 | ##### | 15 | fc->map.len = read_len; | |
| 317 | ##### | 15 | return 0; | |
| 318 | - | } | ||
| 319 | - | |||
| 320 | ![]() |
252 | 2 | static int diff_file_content_load_workdir_file( |
| 321 | - | git_diff_file_content *fc, | ||
| 322 | - | git_buf *path, | ||
| 323 | - | git_diff_options *diff_opts) | ||
| 324 | - | { | ||
| 325 | 252 | 2 | int error = 0; | |
| 326 | 252 | 2 | git_filter_list *fl = NULL; | |
| 327 | 252 | 2,3 | git_file fd = git_futils_open_ro(git_buf_cstr(path)); | |
| 328 | 252 | 4 | git_buf raw = GIT_BUF_INIT; | |
| 329 | - | |||
| 330 | 252 | 4 | if (fd < 0) | |
| 331 | ##### | 5 | return fd; | |
| 332 | - | |||
| 333 | 252 | 6 | if (!fc->file->size) | |
| 334 | 3 | 7 | error = git_futils_filesize(&fc->file->size, fd); | |
| 335 | - | |||
| 336 | 252 | 8,9 | if (error < 0 || !fc->file->size) | |
| 337 | - | goto cleanup; | ||
| 338 | - | |||
| 339 | 249 | 10,12 | if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 && | |
| 340 | 247 | 11 | diff_file_content_binary_by_size(fc)) | |
| 341 | ##### | 13 | goto cleanup; | |
| 342 | - | |||
| 343 | 249 | 14,15 | if ((error = git_filter_list_load( | |
| 344 | 249 | 14 | &fl, fc->repo, NULL, fc->file->path, | |
| 345 | - | GIT_FILTER_TO_ODB, GIT_FILTER_ALLOW_UNSAFE)) < 0) | ||
| 346 | ##### | 16 | goto cleanup; | |
| 347 | - | |||
| 348 | - | /* if there are no filters, try to mmap the file */ | ||
| 349 | 249 | 17 | if (fl == NULL) { | |
| 350 | 246 | 18,19 | if (!(error = git_futils_mmap_ro( | |
| 351 | 246 | 18 | &fc->map, fd, 0, (size_t)fc->file->size))) { | |
| 352 | 246 | 20 | fc->flags |= GIT_DIFF_FLAG__UNMAP_DATA; | |
| 353 | 246 | 20 | goto cleanup; | |
| 354 | - | } | ||
| 355 | - | |||
| 356 | - | /* if mmap failed, fall through to try readbuffer below */ | ||
| 357 | ##### | 21 | git_error_clear(); | |
| 358 | - | } | ||
| 359 | - | |||
| 360 | 3 | 22,23 | if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) { | |
| 361 | 3 | 24 | git_buf out = GIT_BUF_INIT; | |
| 362 | - | |||
| 363 | 3 | 24 | error = git_filter_list_apply_to_data(&out, fl, &raw); | |
| 364 | - | |||
| 365 | 3 | 25 | if (out.ptr != raw.ptr) | |
| 366 | 3 | 26 | git_buf_dispose(&raw); | |
| 367 | - | |||
| 368 | 3 | 27 | if (!error) { | |
| 369 | 3 | 28 | fc->map.len = out.size; | |
| 370 | 3 | 28 | fc->map.data = out.ptr; | |
| 371 | 3 | 28,29 | fc->flags |= GIT_DIFF_FLAG__FREE_DATA; | |
| 372 | - | } | ||
| 373 | - | } | ||
| 374 | - | |||
| 375 | - | cleanup: | ||
| 376 | 252 | 30 | git_filter_list_free(fl); | |
| 377 | 252 | 31 | p_close(fd); | |
| 378 | - | |||
| 379 | 252 | 32 | return error; | |
| 380 | - | } | ||
| 381 | - | |||
| 382 | ![]() |
297 | 2 | static int diff_file_content_load_workdir( |
| 383 | - | git_diff_file_content *fc, | ||
| 384 | - | git_diff_options *diff_opts) | ||
| 385 | - | { | ||
| 386 | 297 | 2 | int error = 0; | |
| 387 | 297 | 2 | git_buf path = GIT_BUF_INIT; | |
| 388 | - | |||
| 389 | 297 | 2 | if (fc->file->mode == GIT_FILEMODE_COMMIT) | |
| 390 | 43 | 3 | return diff_file_content_commit_to_str(fc, true); | |
| 391 | - | |||
| 392 | 254 | 4 | if (fc->file->mode == GIT_FILEMODE_TREE) | |
| 393 | 2 | 5 | return 0; | |
| 394 | - | |||
| 395 | 252 | 6,6-8 | if (git_buf_joinpath( | |
| 396 | 252 | 6,6 | &path, git_repository_workdir(fc->repo), fc->file->path) < 0) | |
| 397 | ##### | 9 | return -1; | |
| 398 | - | |||
| 399 | 252 | 10 | if (S_ISLNK(fc->file->mode)) | |
| 400 | ##### | 11 | error = diff_file_content_load_workdir_symlink(fc, &path); | |
| 401 | - | else | ||
| 402 | 252 | 12 | error = diff_file_content_load_workdir_file(fc, &path, diff_opts); | |
| 403 | - | |||
| 404 | - | /* once data is loaded, update OID if we didn't have it previously */ | ||
| 405 | 252 | 13,14 | if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) { | |
| 406 | 192 | 15,15 | error = git_odb_hash( | |
| 407 | 192 | 15 | &fc->file->id, fc->map.data, fc->map.len, GIT_OBJECT_BLOB); | |
| 408 | 192 | 16 | fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; | |
| 409 | - | } | ||
| 410 | - | |||
| 411 | 252 | 17 | git_buf_dispose(&path); | |
| 412 | 252 | 18 | return error; | |
| 413 | - | } | ||
| 414 | - | |||
| 415 | ![]() |
2484 | 2 | int git_diff_file_content__load( |
| 416 | - | git_diff_file_content *fc, | ||
| 417 | - | git_diff_options *diff_opts) | ||
| 418 | - | { | ||
| 419 | 2484 | 2 | int error = 0; | |
| 420 | - | |||
| 421 | 2484 | 2 | if ((fc->flags & GIT_DIFF_FLAG__LOADED) != 0) | |
| 422 | 1190 | 3 | return 0; | |
| 423 | - | |||
| 424 | 1294 | 4,5 | if ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0 && | |
| 425 | 31 | 5 | (diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0) | |
| 426 | 11 | 6 | return 0; | |
| 427 | - | |||
| 428 | 1283 | 7 | if (fc->src == GIT_ITERATOR_WORKDIR) | |
| 429 | 297 | 8 | error = diff_file_content_load_workdir(fc, diff_opts); | |
| 430 | - | else | ||
| 431 | 986 | 9 | error = diff_file_content_load_blob(fc, diff_opts); | |
| 432 | 1283 | 10 | if (error) | |
| 433 | ##### | 11 | return error; | |
| 434 | - | |||
| 435 | 1283 | 12 | fc->flags |= GIT_DIFF_FLAG__LOADED; | |
| 436 | - | |||
| 437 | 1283 | 12 | diff_file_content_binary_by_content(fc); | |
| 438 | - | |||
| 439 | 1283 | 13 | return 0; | |
| 440 | - | } | ||
| 441 | - | |||
| 442 | 2528 | 2 | void git_diff_file_content__unload(git_diff_file_content *fc) | |
| 443 | - | { | ||
| 444 | 2528 | 2 | if ((fc->flags & GIT_DIFF_FLAG__LOADED) == 0) | |
| 445 | 2528 | 3,14 | return; | |
| 446 | - | |||
| 447 | 2500 | 4 | if (fc->flags & GIT_DIFF_FLAG__FREE_DATA) { | |
| 448 | 84 | 5 | git__free(fc->map.data); | |
| 449 | 84 | 6 | fc->map.data = ""; | |
| 450 | 84 | 6 | fc->map.len = 0; | |
| 451 | 84 | 6 | fc->flags &= ~GIT_DIFF_FLAG__FREE_DATA; | |
| 452 | - | } | ||
| 453 | 2416 | 7 | else if (fc->flags & GIT_DIFF_FLAG__UNMAP_DATA) { | |
| 454 | 246 | 8 | git_futils_mmap_free(&fc->map); | |
| 455 | 246 | 9 | fc->map.data = ""; | |
| 456 | 246 | 9 | fc->map.len = 0; | |
| 457 | 246 | 9 | fc->flags &= ~GIT_DIFF_FLAG__UNMAP_DATA; | |
| 458 | - | } | ||
| 459 | - | |||
| 460 | 2500 | 10 | if (fc->flags & GIT_DIFF_FLAG__FREE_BLOB) { | |
| 461 | 1038 | 11 | git_blob_free((git_blob *)fc->blob); | |
| 462 | 1038 | 12 | fc->blob = NULL; | |
| 463 | 1038 | 12 | fc->flags &= ~GIT_DIFF_FLAG__FREE_BLOB; | |
| 464 | - | } | ||
| 465 | - | |||
| 466 | 2500 | 13 | fc->flags &= ~GIT_DIFF_FLAG__LOADED; | |
| 467 | - | } | ||
| 468 | - | |||
| 469 | 2528 | 2 | void git_diff_file_content__clear(git_diff_file_content *fc) | |
| 470 | - | { | ||
| 471 | 2528 | 2 | git_diff_file_content__unload(fc); | |
| 472 | - | |||
| 473 | - | /* for now, nothing else to do */ | ||
| 474 | 2528 | 3 | } |