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