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 | } |