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 "index.h"
9 -
10 - #include <stddef.h>
11 -
12 - #include "repository.h"
13 - #include "tree.h"
14 - #include "tree-cache.h"
15 - #include "hash.h"
16 - #include "iterator.h"
17 - #include "pathspec.h"
18 - #include "ignore.h"
19 - #include "blob.h"
20 - #include "idxmap.h"
21 - #include "diff.h"
22 - #include "varint.h"
23 -
24 - #include "git2/odb.h"
25 - #include "git2/oid.h"
26 - #include "git2/blob.h"
27 - #include "git2/config.h"
28 - #include "git2/sys/index.h"
29 -
30 - static int index_apply_to_wd_diff(git_index *index, int action, const git_strarray *paths,
31 - unsigned int flags,
32 - git_index_matched_path_cb cb, void *payload);
33 -
34 - #define minimal_entry_size (offsetof(struct entry_short, path))
35 -
36 - static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
37 - static const size_t INDEX_HEADER_SIZE = 12;
38 -
39 - static const unsigned int INDEX_VERSION_NUMBER_DEFAULT = 2;
40 - static const unsigned int INDEX_VERSION_NUMBER_LB = 2;
41 - static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
42 - static const unsigned int INDEX_VERSION_NUMBER_COMP = 4;
43 - static const unsigned int INDEX_VERSION_NUMBER_UB = 4;
44 -
45 - static const unsigned int INDEX_HEADER_SIG = 0x44495243;
46 - static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
47 - static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
48 - static const char INDEX_EXT_CONFLICT_NAME_SIG[] = {'N', 'A', 'M', 'E'};
49 -
50 - #define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
51 -
52 - struct index_header {
53 - uint32_t signature;
54 - uint32_t version;
55 - uint32_t entry_count;
56 - };
57 -
58 - struct index_extension {
59 - char signature[4];
60 - uint32_t extension_size;
61 - };
62 -
63 - struct entry_time {
64 - uint32_t seconds;
65 - uint32_t nanoseconds;
66 - };
67 -
68 - struct entry_short {
69 - struct entry_time ctime;
70 - struct entry_time mtime;
71 - uint32_t dev;
72 - uint32_t ino;
73 - uint32_t mode;
74 - uint32_t uid;
75 - uint32_t gid;
76 - uint32_t file_size;
77 - git_oid oid;
78 - uint16_t flags;
79 - char path[1]; /* arbitrary length */
80 - };
81 -
82 - struct entry_long {
83 - struct entry_time ctime;
84 - struct entry_time mtime;
85 - uint32_t dev;
86 - uint32_t ino;
87 - uint32_t mode;
88 - uint32_t uid;
89 - uint32_t gid;
90 - uint32_t file_size;
91 - git_oid oid;
92 - uint16_t flags;
93 - uint16_t flags_extended;
94 - char path[1]; /* arbitrary length */
95 - };
96 -
97 - struct entry_srch_key {
98 - const char *path;
99 - size_t pathlen;
100 - int stage;
101 - };
102 -
103 - struct entry_internal {
104 - git_index_entry entry;
105 - size_t pathlen;
106 - char path[GIT_FLEX_ARRAY];
107 - };
108 -
109 - struct reuc_entry_internal {
110 - git_index_reuc_entry entry;
111 - size_t pathlen;
112 - char path[GIT_FLEX_ARRAY];
113 - };
114 -
115 - bool git_index__enforce_unsaved_safety = false;
116 -
117 - /* local declarations */
118 - static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size);
119 - static int read_header(struct index_header *dest, const void *buffer);
120 -
121 - static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
122 - static bool is_index_extended(git_index *index);
123 - static int write_index(git_oid *checksum, git_index *index, git_filebuf *file);
124 -
125 - static void index_entry_free(git_index_entry *entry);
126 - static void index_entry_reuc_free(git_index_reuc_entry *reuc);
127 -
128 43991 2 GIT_INLINE(int) index_map_set(git_idxmap *map, git_index_entry *e, bool ignore_case)
129 - {
130 43991 2 if (ignore_case)
131 110 3 return git_idxmap_icase_set((git_idxmap_icase *) map, e, e);
132 - else
133 43881 4 return git_idxmap_set(map, e, e);
134 - }
135 -
136 46832 2 GIT_INLINE(int) index_map_delete(git_idxmap *map, git_index_entry *e, bool ignore_case)
137 - {
138 46832 2 if (ignore_case)
139 449 3 return git_idxmap_icase_delete((git_idxmap_icase *) map, e);
140 - else
141 46383 4 return git_idxmap_delete(map, e);
142 - }
143 -
144 2449 2 GIT_INLINE(int) index_map_resize(git_idxmap *map, size_t count, bool ignore_case)
145 - {
146 2449 2 if (ignore_case)
147 1 3 return git_idxmap_icase_resize((git_idxmap_icase *) map, count);
148 - else
149 2448 4 return git_idxmap_resize(map, count);
150 - }
151 -
152 422638 2 int git_index_entry_srch(const void *key, const void *array_member)
153 - {
154 422638 2 const struct entry_srch_key *srch_key = key;
155 422638 2 const struct entry_internal *entry = array_member;
156 - int cmp;
157 - size_t len1, len2, len;
158 -
159 422638 2 len1 = srch_key->pathlen;
160 422638 2 len2 = entry->pathlen;
161 422638 2 len = len1 < len2 ? len1 : len2;
162 -
163 422638 2 cmp = memcmp(srch_key->path, entry->path, len);
164 422638 2 if (cmp)
165 411723 3 return cmp;
166 10915 4 if (len1 < len2)
167 3224 5 return -1;
168 7691 6 if (len1 > len2)
169 712 7 return 1;
170 -
171 6979 8 if (srch_key->stage != GIT_INDEX_STAGE_ANY)
172 6825 9 return srch_key->stage - GIT_INDEX_ENTRY_STAGE(&entry->entry);
173 -
174 154 10 return 0;
175 - }
176 -
177 1900 2 int git_index_entry_isrch(const void *key, const void *array_member)
178 - {
179 1900 2 const struct entry_srch_key *srch_key = key;
180 1900 2 const struct entry_internal *entry = array_member;
181 - int cmp;
182 - size_t len1, len2, len;
183 -
184 1900 2 len1 = srch_key->pathlen;
185 1900 2 len2 = entry->pathlen;
186 1900 2 len = len1 < len2 ? len1 : len2;
187 -
188 1900 2 cmp = strncasecmp(srch_key->path, entry->path, len);
189 -
190 1900 2 if (cmp)
191 1890 3 return cmp;
192 10 4 if (len1 < len2)
193 1 5 return -1;
194 9 6 if (len1 > len2)
195 ##### 7 return 1;
196 -
197 9 8 if (srch_key->stage != GIT_INDEX_STAGE_ANY)
198 9 9 return srch_key->stage - GIT_INDEX_ENTRY_STAGE(&entry->entry);
199 -
200 ##### 10 return 0;
201 - }
202 -
203 16883 2 static int index_entry_srch_path(const void *path, const void *array_member)
204 - {
205 16883 2 const git_index_entry *entry = array_member;
206 -
207 16883 2 return strcmp((const char *)path, entry->path);
208 - }
209 -
210 5 2 static int index_entry_isrch_path(const void *path, const void *array_member)
211 - {
212 5 2 const git_index_entry *entry = array_member;
213 -
214 5 2 return strcasecmp((const char *)path, entry->path);
215 - }
216 -
217 39409 2 int git_index_entry_cmp(const void *a, const void *b)
218 - {
219 - int diff;
220 39409 2 const git_index_entry *entry_a = a;
221 39409 2 const git_index_entry *entry_b = b;
222 -
223 39409 2 diff = strcmp(entry_a->path, entry_b->path);
224 -
225 39409 2 if (diff == 0)
226 5558 3 diff = (GIT_INDEX_ENTRY_STAGE(entry_a) - GIT_INDEX_ENTRY_STAGE(entry_b));
227 -
228 39409 4 return diff;
229 - }
230 -
231 1829 2 int git_index_entry_icmp(const void *a, const void *b)
232 - {
233 - int diff;
234 1829 2 const git_index_entry *entry_a = a;
235 1829 2 const git_index_entry *entry_b = b;
236 -
237 1829 2 diff = strcasecmp(entry_a->path, entry_b->path);
238 -
239 1829 2 if (diff == 0)
240 4 3 diff = (GIT_INDEX_ENTRY_STAGE(entry_a) - GIT_INDEX_ENTRY_STAGE(entry_b));
241 -
242 1829 4 return diff;
243 - }
244 -
245 73 2 static int conflict_name_cmp(const void *a, const void *b)
246 - {
247 73 2 const git_index_name_entry *name_a = a;
248 73 2 const git_index_name_entry *name_b = b;
249 -
250 73 2,3 if (name_a->ancestor && !name_b->ancestor)
251 ##### 4 return 1;
252 -
253 73 5,6 if (!name_a->ancestor && name_b->ancestor)
254 ##### 7 return -1;
255 -
256 73 8 if (name_a->ancestor)
257 73 9 return strcmp(name_a->ancestor, name_b->ancestor);
258 -
259 ##### 10,11 if (!name_a->ours || !name_b->ours)
260 ##### 12 return 0;
261 -
262 ##### 13 return strcmp(name_a->ours, name_b->ours);
263 - }
264 -
265 - /**
266 - * TODO: enable this when resolving case insensitive conflicts
267 - */
268 - #if 0
269 - static int conflict_name_icmp(const void *a, const void *b)
270 - {
271 - const git_index_name_entry *name_a = a;
272 - const git_index_name_entry *name_b = b;
273 -
274 - if (name_a->ancestor && !name_b->ancestor)
275 - return 1;
276 -
277 - if (!name_a->ancestor && name_b->ancestor)
278 - return -1;
279 -
280 - if (name_a->ancestor)
281 - return strcasecmp(name_a->ancestor, name_b->ancestor);
282 -
283 - if (!name_a->ours || !name_b->ours)
284 - return 0;
285 -
286 - return strcasecmp(name_a->ours, name_b->ours);
287 - }
288 - #endif
289 -
290 20063 2 static int reuc_srch(const void *key, const void *array_member)
291 - {
292 20063 2 const git_index_reuc_entry *reuc = array_member;
293 -
294 20063 2 return strcmp(key, reuc->path);
295 - }
296 -
297 1 2 static int reuc_isrch(const void *key, const void *array_member)
298 - {
299 1 2 const git_index_reuc_entry *reuc = array_member;
300 -
301 1 2 return strcasecmp(key, reuc->path);
302 - }
303 -
304 20252 2 static int reuc_cmp(const void *a, const void *b)
305 - {
306 20252 2 const git_index_reuc_entry *info_a = a;
307 20252 2 const git_index_reuc_entry *info_b = b;
308 -
309 20252 2 return strcmp(info_a->path, info_b->path);
310 - }
311 -
312 2 2 static int reuc_icmp(const void *a, const void *b)
313 - {
314 2 2 const git_index_reuc_entry *info_a = a;
315 2 2 const git_index_reuc_entry *info_b = b;
316 -
317 2 2 return strcasecmp(info_a->path, info_b->path);
318 - }
319 -
320 4595 2 static void index_entry_reuc_free(git_index_reuc_entry *reuc)
321 - {
322 4595 2 git__free(reuc);
323 4595 3 }
324 -
325 46633 2 static void index_entry_free(git_index_entry *entry)
326 - {
327 46633 2 if (!entry)
328 46639 3,5 return;
329 -
330 46633 4 memset(&entry->id, 0, sizeof(entry->id));
331 46633 4 git__free(entry);
332 - }
333 -
334 17873 2 unsigned int git_index__create_mode(unsigned int mode)
335 - {
336 17873 2 if (S_ISLNK(mode))
337 153 3 return S_IFLNK;
338 -
339 17720 4,5 if (S_ISDIR(mode) || (mode & S_IFMT) == (S_IFLNK | S_IFDIR))
340 88 6 return (S_IFLNK | S_IFDIR);
341 -
342 17632 7 return S_IFREG | GIT_PERMS_CANONICAL(mode);
343 - }
344 -
345 2956 2 static unsigned int index_merge_mode(
346 - git_index *index, git_index_entry *existing, unsigned int mode)
347 - {
348 2956 2-4 if (index->no_symlinks && S_ISREG(mode) &&
349 ##### 5 existing && S_ISLNK(existing->mode))
350 ##### 6 return existing->mode;
351 -
352 2956 7,8 if (index->distrust_filemode && S_ISREG(mode))
353 6 10,13 return (existing && S_ISREG(existing->mode)) ?
354 6 9,11,12 existing->mode : git_index__create_mode(0666);
355 -
356 2950 14 return git_index__create_mode(mode);
357 - }
358 -
359 127067 2 GIT_INLINE(int) index_find_in_entries(
360 - size_t *out, git_vector *entries, git_vector_cmp entry_srch,
361 - const char *path, size_t path_len, int stage)
362 - {
363 - struct entry_srch_key srch_key;
364 127067 2 srch_key.path = path;
365 127067 2-4 srch_key.pathlen = !path_len ? strlen(path) : path_len;
366 127067 5 srch_key.stage = stage;
367 127067 5 return git_vector_bsearch2(out, entries, entry_srch, &srch_key);
368 - }
369 -
370 124793 2 GIT_INLINE(int) index_find(
371 - size_t *out, git_index *index,
372 - const char *path, size_t path_len, int stage)
373 - {
374 124793 2 git_vector_sort(&index->entries);
375 -
376 124788 3 return index_find_in_entries(
377 - out, &index->entries, index->entries_search, path, path_len, stage);
378 - }
379 -
380 126 2 void git_index__set_ignore_case(git_index *index, bool ignore_case)
381 - {
382 126 2 index->ignore_case = ignore_case;
383 -
384 126 2 if (ignore_case) {
385 60 3 index->entries_cmp_path = git__strcasecmp_cb;
386 60 3 index->entries_search = git_index_entry_isrch;
387 60 3 index->entries_search_path = index_entry_isrch_path;
388 60 3 index->reuc_search = reuc_isrch;
389 - } else {
390 66 4 index->entries_cmp_path = git__strcmp_cb;
391 66 4 index->entries_search = git_index_entry_srch;
392 66 4 index->entries_search_path = index_entry_srch_path;
393 66 4 index->reuc_search = reuc_srch;
394 - }
395 -
396 126 5-8 git_vector_set_cmp(&index->entries,
397 - ignore_case ? git_index_entry_icmp : git_index_entry_cmp);
398 126 9 git_vector_sort(&index->entries);
399 -
400 126 10-13 git_vector_set_cmp(&index->reuc, ignore_case ? reuc_icmp : reuc_cmp);
401 126 14 git_vector_sort(&index->reuc);
402 126 15 }
403 -
404 2582 2 int git_index_open(git_index **index_out, const char *index_path)
405 - {
406 - git_index *index;
407 2582 2 int error = -1;
408 -
409 2582 2,3 assert(index_out);
410 -
411 2582 4 index = git__calloc(1, sizeof(git_index));
412 2582 5,6 GIT_ERROR_CHECK_ALLOC(index);
413 -
414 2582 7,8 if (git_pool_init(&index->tree_pool, 1) < 0)
415 ##### 9 goto fail;
416 -
417 2582 10 if (index_path != NULL) {
418 1993 11 index->index_file_path = git__strdup(index_path);
419 1993 12 if (!index->index_file_path)
420 ##### 13 goto fail;
421 -
422 - /* Check if index file is stored on disk already */
423 1993 14,15 if (git_path_exists(index->index_file_path) == true)
424 1746 16 index->on_disk = 1;
425 - }
426 -
427 2582 17,18,20 if (git_vector_init(&index->entries, 32, git_index_entry_cmp) < 0 ||
428 2582 19,22 git_idxmap_new(&index->entries_map) < 0 ||
429 2582 21,24 git_vector_init(&index->names, 8, conflict_name_cmp) < 0 ||
430 2582 23,26 git_vector_init(&index->reuc, 8, reuc_cmp) < 0 ||
431 2582 25 git_vector_init(&index->deleted, 8, git_index_entry_cmp) < 0)
432 - goto fail;
433 -
434 2582 27 index->entries_cmp_path = git__strcmp_cb;
435 2582 27 index->entries_search = git_index_entry_srch;
436 2582 27 index->entries_search_path = index_entry_srch_path;
437 2582 27 index->reuc_search = reuc_srch;
438 2582 27 index->version = INDEX_VERSION_NUMBER_DEFAULT;
439 -
440 2582 27-29 if (index_path != NULL && (error = git_index_read(index, true)) < 0)
441 2 30 goto fail;
442 -
443 2580 31 *index_out = index;
444 2580 31 GIT_REFCOUNT_INC(index);
445 -
446 2580 32 return 0;
447 -
448 - fail:
449 2 33 git_pool_clear(&index->tree_pool);
450 2 34 git_index_free(index);
451 2 35 return error;
452 - }
453 -
454 589 2 int git_index_new(git_index **out)
455 - {
456 589 2 return git_index_open(out, NULL);
457 - }
458 -
459 2582 2 static void index_free(git_index *index)
460 - {
461 - /* index iterators increment the refcount of the index, so if we
462 - * get here then there should be no outstanding iterators.
463 - */
464 2582 2-4 assert(!git_atomic_get(&index->readers));
465 -
466 2582 5 git_index_clear(index);
467 2582 6 git_idxmap_free(index->entries_map);
468 2582 7 git_vector_free(&index->entries);
469 2582 8 git_vector_free(&index->names);
470 2582 9 git_vector_free(&index->reuc);
471 2582 10 git_vector_free(&index->deleted);
472 -
473 2582 11 git__free(index->index_file_path);
474 -
475 2582 12 git__memzero(index, sizeof(*index));
476 2582 13 git__free(index);
477 2582 14 }
478 -
479 16367 2 void git_index_free(git_index *index)
480 - {
481 16367 2 if (index == NULL)
482 16367 3,8 return;
483 -
484 14860 4-7 GIT_REFCOUNT_DEC(index, index_free);
485 - }
486 -
487 - /* call with locked index */
488 4971 2 static void index_free_deleted(git_index *index)
489 - {
490 4971 2 int readers = (int)git_atomic_get(&index->readers);
491 - size_t i;
492 -
493 4971 3,4 if (readers > 0 || !index->deleted.length)
494 4971 5,12 return;
495 -
496 950 6,9,10 for (i = 0; i < index->deleted.length; ++i) {
497 787 7 git_index_entry *ie = git__swap(index->deleted.contents[i], NULL);
498 787 8 index_entry_free(ie);
499 - }
500 -
501 163 11 git_vector_clear(&index->deleted);
502 - }
503 -
504 - /* call with locked index */
505 - 2 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files)static int index_remove_entry(git_index *index, size_t pos)
506 - {
507 - 2 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) int error = 0;
508 - 2 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) git_index_entry *entry = git_vector_get(&index->entries, pos);
509 -
510 - 3 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) if (entry != NULL) {
511 - 4 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) git_tree_cache_invalidate_path(index->tree, entry->path);
512 - 5 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) index_map_delete(index->entries_map, entry, index->ignore_case);
513 - }
514 -
515 - 6 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) error = git_vector_remove(&index->entries, pos);
516 -
517 - 7 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) if (!error) {
518 - 8,9 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) if (git_atomic_get(&index->readers) > 0) {
519 - 10 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) error = git_vector_insert(&index->deleted, entry);
520 - } else {
521 - 11 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) index_entry_free(entry);
522 - }
523 -
524 - 12 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) index->dirty = 1;
525 - }
526 -
527 - 13 suppressed: function cannot be solved index_remove_entry (automatic due to inconsistent arc counts in .gcda files) return error;
528 - }
529 -
530 4972 2 int git_index_clear(git_index *index)
531 - {
532 4972 2 int error = 0;
533 -
534 4972 2,3 assert(index);
535 -
536 4972 4 index->dirty = 1;
537 4972 4 index->tree = NULL;
538 4972 4 git_pool_clear(&index->tree_pool);
539 -
540 4972 5 git_idxmap_clear(index->entries_map);
541 46982 6,8,9 while (!error && index->entries.length > 0)
542 42011 7 error = index_remove_entry(index, index->entries.length - 1);
543 -
544 4971 10 if (error)
545 ##### 11 goto done;
546 -
547 4971 12 index_free_deleted(index);
548 -
549 4971 13-16 if ((error = git_index_name_clear(index)) < 0 ||
550 - (error = git_index_reuc_clear(index)) < 0)
551 - goto done;
552 -
553 4971 17 git_futils_filestamp_set(&index->stamp, NULL);
554 -
555 - done:
556 4971 18 return error;
557 - }
558 -
559 1 2 static int create_index_error(int error, const char *msg)
560 - {
561 1 2 git_error_set_str(GIT_ERROR_INDEX, msg);
562 1 3 return error;
563 - }
564 -
565 1985 2 int git_index_set_caps(git_index *index, int caps)
566 - {
567 - unsigned int old_ignore_case;
568 -
569 1985 2,3 assert(index);
570 -
571 1985 4 old_ignore_case = index->ignore_case;
572 -
573 1985 4 if (caps == GIT_INDEX_CAPABILITY_FROM_OWNER) {
574 1969 5 git_repository *repo = INDEX_OWNER(index);
575 - int val;
576 -
577 1969 5 if (!repo)
578 ##### 6,7 return create_index_error(
579 - -1, "cannot access repository to set index caps");
580 -
581 1969 8,9 if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_IGNORECASE))
582 1969 10 index->ignore_case = (val != 0);
583 1969 11,12 if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_FILEMODE))
584 1969 13 index->distrust_filemode = (val == 0);
585 1969 14,15 if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_SYMLINKS))
586 1969 16,17 index->no_symlinks = (val == 0);
587 - }
588 - else {
589 16 18 index->ignore_case = ((caps & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0);
590 16 18 index->distrust_filemode = ((caps & GIT_INDEX_CAPABILITY_NO_FILEMODE) != 0);
591 16 18 index->no_symlinks = ((caps & GIT_INDEX_CAPABILITY_NO_SYMLINKS) != 0);
592 - }
593 -
594 1985 19 if (old_ignore_case != index->ignore_case) {
595 60 20 git_index__set_ignore_case(index, (bool)index->ignore_case);
596 - }
597 -
598 1985 21 return 0;
599 - }
600 -
601 52 2 int git_index_caps(const git_index *index)
602 - {
603 52 2,5 return ((index->ignore_case ? GIT_INDEX_CAPABILITY_IGNORE_CASE : 0) |
604 52 2-4 (index->distrust_filemode ? GIT_INDEX_CAPABILITY_NO_FILEMODE : 0) |
605 52 5-7 (index->no_symlinks ? GIT_INDEX_CAPABILITY_NO_SYMLINKS : 0));
606 - }
607 -
608 3 2 const git_oid *git_index_checksum(git_index *index)
609 - {
610 3 2 return &index->checksum;
611 - }
612 -
613 - /**
614 - * Returns 1 for changed, 0 for not changed and <0 for errors
615 - */
616 3648 2 static int compare_checksum(git_index *index)
617 - {
618 - int fd;
619 - ssize_t bytes_read;
620 3648 2 git_oid checksum = {{ 0 }};
621 -
622 3648 2,3 if ((fd = p_open(index->index_file_path, O_RDONLY)) < 0)
623 ##### 4 return fd;
624 -
625 3648 5,6 if (p_lseek(fd, -20, SEEK_END) < 0) {
626 ##### 7 p_close(fd);
627 ##### 8 git_error_set(GIT_ERROR_OS, "failed to seek to end of file");
628 ##### 9 return -1;
629 - }
630 -
631 3648 10 bytes_read = p_read(fd, &checksum, GIT_OID_RAWSZ);
632 3648 11 p_close(fd);
633 -
634 3648 12 if (bytes_read < 0)
635 ##### 13 return -1;
636 -
637 3648 14 return !!git_oid_cmp(&checksum, &index->checksum);
638 - }
639 -
640 4022 2 int git_index_read(git_index *index, int force)
641 - {
642 4022 2 int error = 0, updated;
643 4022 2 git_buf buffer = GIT_BUF_INIT;
644 4022 2 git_futils_filestamp stamp = index->stamp;
645 -
646 4022 2 if (!index->index_file_path)
647 ##### 3 return create_index_error(-1,
648 - "failed to read index: The index is in-memory only");
649 -
650 4022 4 index->on_disk = git_path_exists(index->index_file_path);
651 -
652 4022 5 if (!index->on_disk) {
653 374 6-8 if (force && (error = git_index_clear(index)) < 0)
654 ##### 9 return error;
655 -
656 374 10 index->dirty = 0;
657 374 10 return 0;
658 - }
659 -
660 3648 11-14 if ((updated = git_futils_filestamp_check(&stamp, index->index_file_path) < 0) ||
661 - ((updated = compare_checksum(index)) < 0)) {
662 ##### 15 git_error_set(
663 - GIT_ERROR_INDEX,
664 - "failed to read index: '%s' no longer exists",
665 - index->index_file_path);
666 ##### 16 return updated;
667 - }
668 -
669 3647 17,18 if (!updated && !force)
670 1870 19 return 0;
671 -
672 1777 20 error = git_futils_readbuffer(&buffer, index->index_file_path);
673 1777 21 if (error < 0)
674 ##### 22 return error;
675 -
676 1777 23 index->tree = NULL;
677 1777 23 git_pool_clear(&index->tree_pool);
678 -
679 1778 24 error = git_index_clear(index);
680 -
681 1778 25 if (!error)
682 1778 26 error = parse_index(index, buffer.ptr, buffer.size);
683 -
684 1778 27 if (!error) {
685 1776 28 git_futils_filestamp_set(&index->stamp, &stamp);
686 1776 29 index->dirty = 0;
687 - }
688 -
689 1778 30 git_buf_dispose(&buffer);
690 1778 31 return error;
691 - }
692 -
693 979 2 int git_index_read_safely(git_index *index)
694 - {
695 979 2,3 if (git_index__enforce_unsaved_safety && index->dirty) {
696 1 4 git_error_set(GIT_ERROR_INDEX,
697 - "the index has unsaved changes that would be overwritten by this operation");
698 1 5 return GIT_EINDEXDIRTY;
699 - }
700 -
701 978 6 return git_index_read(index, false);
702 - }
703 -
704 ##### 2 int git_index__changed_relative_to(
705 - git_index *index, const git_oid *checksum)
706 - {
707 - /* attempt to update index (ignoring errors) */
708 ##### 2,3 if (git_index_read(index, false) < 0)
709 ##### 4 git_error_clear();
710 -
711 ##### 5 return !!git_oid_cmp(&index->checksum, checksum);
712 - }
713 -
714 13353 2 static bool is_racy_entry(git_index *index, const git_index_entry *entry)
715 - {
716 - /* Git special-cases submodules in the check */
717 13353 2 if (S_ISGITLINK(entry->mode))
718 121 3 return false;
719 -
720 13232 4 return git_index_entry_newer_than_index(entry, index);
721 - }
722 -
723 - /*
724 - * Force the next diff to take a look at those entries which have the
725 - * same timestamp as the current index.
726 - */
727 1106 2 static int truncate_racily_clean(git_index *index)
728 - {
729 - size_t i;
730 - int error;
731 - git_index_entry *entry;
732 1106 2 git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
733 1106 2 git_diff *diff = NULL;
734 1106 2 git_vector paths = GIT_VECTOR_INIT;
735 - git_diff_delta *delta;
736 -
737 - /* Nothing to do if there's no repo to talk about */
738 1106 2 if (!INDEX_OWNER(index))
739 4 3 return 0;
740 -
741 - /* If there's no workdir, we can't know where to even check */
742 1102 4,5 if (!git_repository_workdir(INDEX_OWNER(index)))
743 5 6 return 0;
744 -
745 1097 7 diff_opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
746 18545 7,12-14 git_vector_foreach(&index->entries, i, entry) {
747 17448 8,10 if ((entry->flags_extended & GIT_INDEX_ENTRY_UPTODATE) == 0 &&
748 13353 9 is_racy_entry(index, entry))
749 54 11 git_vector_insert(&paths, (char *)entry->path);
750 - }
751 -
752 1097 15 if (paths.length == 0)
753 1057 16 goto done;
754 -
755 40 17 diff_opts.pathspec.count = paths.length;
756 40 17 diff_opts.pathspec.strings = (char **)paths.contents;
757 -
758 40 17,18 if ((error = git_diff_index_to_workdir(&diff, INDEX_OWNER(index), index, &diff_opts)) < 0)
759 ##### 19 return error;
760 -
761 46 20,24-26 git_vector_foreach(&diff->deltas, i, delta) {
762 6 21 entry = (git_index_entry *)git_index_get_bypath(index, delta->old_file.path, 0);
763 -
764 - /* Ensure that we have a stage 0 for this file (ie, it's not a
765 - * conflict), otherwise smudging it is quite pointless.
766 - */
767 6 22 if (entry) {
768 6 23 entry->file_size = 0;
769 6 23 index->dirty = 1;
770 - }
771 - }
772 -
773 - done:
774 1097 27 git_diff_free(diff);
775 1097 28 git_vector_free(&paths);
776 1097 29 return 0;
777 - }
778 -
779 1 2 unsigned git_index_version(git_index *index)
780 - {
781 1 2,3 assert(index);
782 -
783 1 4 return index->version;
784 - }
785 -
786 1 2 int git_index_set_version(git_index *index, unsigned int version)
787 - {
788 1 2,3 assert(index);
789 -
790 1 4,5 if (version < INDEX_VERSION_NUMBER_LB ||
791 1 5 version > INDEX_VERSION_NUMBER_UB) {
792 ##### 6 git_error_set(GIT_ERROR_INDEX, "invalid version number");
793 ##### 7 return -1;
794 - }
795 -
796 1 8 index->version = version;
797 -
798 1 8 return 0;
799 - }
800 -
801 1106 2 int git_index_write(git_index *index)
802 - {
803 1106 2 git_indexwriter writer = GIT_INDEXWRITER_INIT;
804 - int error;
805 -
806 1106 2 truncate_racily_clean(index);
807 -
808 1106 3-6 if ((error = git_indexwriter_init(&writer, index)) == 0 &&
809 - (error = git_indexwriter_commit(&writer)) == 0)
810 1104 7 index->dirty = 0;
811 -
812 1106 8 git_indexwriter_cleanup(&writer);
813 -
814 1106 9 return error;
815 - }
816 -
817 16 2 const char * git_index_path(const git_index *index)
818 - {
819 16 2,3 assert(index);
820 16 4 return index->index_file_path;
821 - }
822 -
823 124 2 int git_index_write_tree(git_oid *oid, git_index *index)
824 - {
825 - git_repository *repo;
826 -
827 124 2-4 assert(oid && index);
828 -
829 124 5 repo = INDEX_OWNER(index);
830 -
831 124 5 if (repo == NULL)
832 ##### 6 return create_index_error(-1, "Failed to write tree. "
833 - "the index file is not backed up by an existing repository");
834 -
835 124 7 return git_tree__write_index(oid, index, repo);
836 - }
837 -
838 229 2 int git_index_write_tree_to(
839 - git_oid *oid, git_index *index, git_repository *repo)
840 - {
841 229 2-5 assert(oid && index && repo);
842 229 6 return git_tree__write_index(oid, index, repo);
843 - }
844 -
845 7619 2 size_t git_index_entrycount(const git_index *index)
846 - {
847 7619 2,3 assert(index);
848 7619 4 return index->entries.length;
849 - }
850 -
851 19188 2 const git_index_entry *git_index_get_byindex(
852 - git_index *index, size_t n)
853 - {
854 19188 2,3 assert(index);
855 19188 4 git_vector_sort(&index->entries);
856 19188 5 return git_vector_get(&index->entries, n);
857 - }
858 -
859 6642 2 const git_index_entry *git_index_get_bypath(
860 - git_index *index, const char *path, int stage)
861 - {
862 6642 2 git_index_entry key = {{ 0 }};
863 - git_index_entry *value;
864 -
865 6642 2,3 assert(index);
866 -
867 6642 4 key.path = path;
868 6642 4 GIT_INDEX_ENTRY_STAGE_SET(&key, stage);
869 -
870 6642 4 if (index->ignore_case)
871 4 5 value = git_idxmap_icase_get((git_idxmap_icase *) index->entries_map, &key);
872 - else
873 6638 6 value = git_idxmap_get(index->entries_map, &key);
874 -
875 6642 7 if (!value) {
876 1190 8 git_error_set(GIT_ERROR_INDEX, "index does not contain '%s'", path);
877 1190 9 return NULL;
878 - }
879 -
880 5452 10 return value;
881 - }
882 -
883 5821 2 void git_index_entry__init_from_stat(
884 - git_index_entry *entry, struct stat *st, bool trust_mode)
885 - {
886 5821 2 entry->ctime.seconds = (int32_t)st->st_ctime;
887 5821 2 entry->mtime.seconds = (int32_t)st->st_mtime;
888 - #if defined(GIT_USE_NSEC)
889 5821 2 entry->mtime.nanoseconds = st->st_mtime_nsec;
890 5821 2 entry->ctime.nanoseconds = st->st_ctime_nsec;
891 - #endif
892 5821 2 entry->dev = st->st_rdev;
893 5821 2 entry->ino = st->st_ino;
894 5821 2,3,6 entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ?
895 5821 2,4,5 git_index__create_mode(0666) : git_index__create_mode(st->st_mode);
896 5821 6 entry->uid = st->st_uid;
897 5821 6 entry->gid = st->st_gid;
898 5821 6 entry->file_size = (uint32_t)st->st_size;
899 5821 6 }
900 -
901 13606 2 static void index_entry_adjust_namemask(
902 - git_index_entry *entry,
903 - size_t path_length)
904 - {
905 13606 2 entry->flags &= ~GIT_INDEX_ENTRY_NAMEMASK;
906 -
907 13606 2 if (path_length < GIT_INDEX_ENTRY_NAMEMASK)
908 13606 3 entry->flags |= path_length & GIT_INDEX_ENTRY_NAMEMASK;
909 - else
910 ##### 4 entry->flags |= GIT_INDEX_ENTRY_NAMEMASK;
911 13606 5 }
912 -
913 - /* When `from_workdir` is true, we will validate the paths to avoid placing
914 - * paths that are invalid for the working directory on the current filesystem
915 - * (eg, on Windows, we will disallow `GIT~1`, `AUX`, `COM1`, etc). This
916 - * function will *always* prevent `.git` and directory traversal `../` from
917 - * being added to the index.
918 - */
919 46620 2 static int index_entry_create(
920 - git_index_entry **out,
921 - git_repository *repo,
922 - const char *path,
923 - struct stat *st,
924 - bool from_workdir)
925 - {
926 46620 2 size_t pathlen = strlen(path), alloclen;
927 - struct entry_internal *entry;
928 46620 2 unsigned int path_valid_flags = GIT_PATH_REJECT_INDEX_DEFAULTS;
929 46620 2 uint16_t mode = 0;
930 -
931 - /* always reject placing `.git` in the index and directory traversal.
932 - * when requested, disallow platform-specific filenames and upgrade to
933 - * the platform-specific `.git` tests (eg, `git~1`, etc).
934 - */
935 46620 2 if (from_workdir)
936 3238 3 path_valid_flags |= GIT_PATH_REJECT_WORKDIR_DEFAULTS;
937 46620 4 if (st)
938 3238 5 mode = st->st_mode;
939 -
940 46637 6,7 if (!git_path_isvalid(repo, path, mode, path_valid_flags)) {
941 13 8 git_error_set(GIT_ERROR_INDEX, "invalid path: '%s'", path);
942 15 9 return -1;
943 - }
944 -
945 46624 10-16 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(struct entry_internal), pathlen);
946 46617 17-23 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
947 46608 24 entry = git__calloc(1, alloclen);
948 46628 25,26 GIT_ERROR_CHECK_ALLOC(entry);
949 -
950 46628 27 entry->pathlen = pathlen;
951 46628 27 memcpy(entry->path, path, pathlen);
952 46628 27 entry->entry.path = entry->path;
953 -
954 46628 27 *out = (git_index_entry *)entry;
955 46628 27 return 0;
956 - }
957 -
958 3239 2 static int index_entry_init(
959 - git_index_entry **entry_out,
960 - git_index *index,
961 - const char *rel_path)
962 - {
963 3239 2 int error = 0;
964 3239 2 git_index_entry *entry = NULL;
965 3239 2 git_buf path = GIT_BUF_INIT;
966 - struct stat st;
967 - git_oid oid;
968 - git_repository *repo;
969 -
970 3239 2 if (INDEX_OWNER(index) == NULL)
971 1 3 return create_index_error(-1,
972 - "could not initialize index entry. "
973 - "Index is not backed up by an existing repository.");
974 -
975 - /*
976 - * FIXME: this is duplicated with the work in
977 - * git_blob__create_from_paths. It should accept an optional stat
978 - * structure so we can pass in the one we have to do here.
979 - */
980 3238 4 repo = INDEX_OWNER(index);
981 3238 4,5 if (git_repository__ensure_not_bare(repo, "create blob from file") < 0)
982 1 6 return GIT_EBAREREPO;
983 -
984 3237 7-9 if (git_buf_joinpath(&path, git_repository_workdir(repo), rel_path) < 0)
985 ##### 10 return -1;
986 -
987 3237 11 error = git_path_lstat(path.ptr, &st);
988 3237 12 git_buf_dispose(&path);
989 -
990 3237 13 if (error < 0)
991 ##### 14 return error;
992 -
993 3237 15,16 if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, &st, true) < 0)
994 7 17 return -1;
995 -
996 - /* write the blob to disk and get the oid and stat info */
997 3230 18 error = git_blob__create_from_paths(
998 3230 18 &oid, &st, INDEX_OWNER(index), NULL, rel_path, 0, true);
999 -
1000 3230 19 if (error < 0) {
1001 275 20 index_entry_free(entry);
1002 275 21 return error;
1003 - }
1004 -
1005 2955 22 entry->id = oid;
1006 2955 22 git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
1007 -
1008 2955 23 *entry_out = (git_index_entry *)entry;
1009 2955 23 return 0;
1010 - }
1011 -
1012 4595 2 static git_index_reuc_entry *reuc_entry_alloc(const char *path)
1013 - {
1014 4595 2 size_t pathlen = strlen(path),
1015 4595 2 structlen = sizeof(struct reuc_entry_internal),
1016 - alloclen;
1017 - struct reuc_entry_internal *entry;
1018 -
1019 4595 2-4,6 if (GIT_ADD_SIZET_OVERFLOW(&alloclen, structlen, pathlen) ||
1020 4595 5,7 GIT_ADD_SIZET_OVERFLOW(&alloclen, alloclen, 1))
1021 ##### 8 return NULL;
1022 -
1023 4595 9 entry = git__calloc(1, alloclen);
1024 4595 10 if (!entry)
1025 ##### 11 return NULL;
1026 -
1027 4595 12 entry->pathlen = pathlen;
1028 4595 12 memcpy(entry->path, path, pathlen);
1029 4595 12 entry->entry.path = entry->path;
1030 -
1031 4595 12 return (git_index_reuc_entry *)entry;
1032 - }
1033 -
1034 4262 2 static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
1035 - const char *path,
1036 - int ancestor_mode, const git_oid *ancestor_oid,
1037 - int our_mode, const git_oid *our_oid,
1038 - int their_mode, const git_oid *their_oid)
1039 - {
1040 4262 2 git_index_reuc_entry *reuc = NULL;
1041 -
1042 4262 2-4 assert(reuc_out && path);
1043 -
1044 4262 5 *reuc_out = reuc = reuc_entry_alloc(path);
1045 4262 6,7 GIT_ERROR_CHECK_ALLOC(reuc);
1046 -
1047 4262 8 if ((reuc->mode[0] = ancestor_mode) > 0) {
1048 3220 9,10 assert(ancestor_oid);
1049 3220 11 git_oid_cpy(&reuc->oid[0], ancestor_oid);
1050 - }
1051 -
1052 4262 12 if ((reuc->mode[1] = our_mode) > 0) {
1053 1640 13,14 assert(our_oid);
1054 1640 15 git_oid_cpy(&reuc->oid[1], our_oid);
1055 - }
1056 -
1057 4262 16 if ((reuc->mode[2] = their_mode) > 0) {
1058 1460 17,18 assert(their_oid);
1059 1460 19 git_oid_cpy(&reuc->oid[2], their_oid);
1060 - }
1061 -
1062 4262 20 return 0;
1063 - }
1064 -
1065 45482 2 static void index_entry_cpy(
1066 - git_index_entry *tgt,
1067 - const git_index_entry *src)
1068 - {
1069 45482 2 const char *tgt_path = tgt->path;
1070 45482 2 memcpy(tgt, src, sizeof(*tgt));
1071 45482 2 tgt->path = tgt_path;
1072 45482 2 }
1073 -
1074 41833 2 static int index_entry_dup(
1075 - git_index_entry **out,
1076 - git_index *index,
1077 - const git_index_entry *src)
1078 - {
1079 41850 2,3 if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
1080 6 4 return -1;
1081 -
1082 41844 5 index_entry_cpy(*out, src);
1083 41842 6 return 0;
1084 - }
1085 -
1086 67 2 static void index_entry_cpy_nocache(
1087 - git_index_entry *tgt,
1088 - const git_index_entry *src)
1089 - {
1090 67 2 git_oid_cpy(&tgt->id, &src->id);
1091 67 3 tgt->mode = src->mode;
1092 67 3 tgt->flags = src->flags;
1093 67 3 tgt->flags_extended = (src->flags_extended & GIT_INDEX_ENTRY_EXTENDED_FLAGS);
1094 67 3 }
1095 -
1096 67 2 static int index_entry_dup_nocache(
1097 - git_index_entry **out,
1098 - git_index *index,
1099 - const git_index_entry *src)
1100 - {
1101 67 2,3 if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
1102 ##### 4 return -1;
1103 -
1104 67 5 index_entry_cpy_nocache(*out, src);
1105 67 6 return 0;
1106 - }
1107 -
1108 9132 2 static int has_file_name(git_index *index,
1109 - const git_index_entry *entry, size_t pos, int ok_to_replace)
1110 - {
1111 9132 2 size_t len = strlen(entry->path);
1112 9132 2 int stage = GIT_INDEX_ENTRY_STAGE(entry);
1113 9132 2 const char *name = entry->path;
1114 -
1115 9149 2,16 while (pos < index->entries.length) {
1116 8687 3 struct entry_internal *p = index->entries.contents[pos++];
1117 -
1118 8687 3 if (len >= p->pathlen)
1119 7004 4 break;
1120 1683 5 if (memcmp(name, p->path, len))
1121 1666 6 break;
1122 17 7 if (GIT_INDEX_ENTRY_STAGE(&p->entry) != stage)
1123 2 8 continue;
1124 15 9 if (p->path[len] != '/')
1125 14 10 continue;
1126 1 11 if (!ok_to_replace)
1127 ##### 12 return -1;
1128 -
1129 1 13,14 if (index_remove_entry(index, --pos) < 0)
1130 ##### 15 break;
1131 - }
1132 9132 17 return 0;
1133 - }
1134 -
1135 - /*
1136 - * Do we have another file with a pathname that is a proper
1137 - * subset of the name we're trying to add?
1138 - */
1139 9132 2 static int has_dir_name(git_index *index,
1140 - const git_index_entry *entry, int ok_to_replace)
1141 - {
1142 9132 2 int stage = GIT_INDEX_ENTRY_STAGE(entry);
1143 9132 2 const char *name = entry->path;
1144 9132 2 const char *slash = name + strlen(name);
1145 -
1146 - for (;;) {
1147 - size_t len, pos;
1148 -
1149 - for (;;) {
1150 268662 3 if (*--slash == '/')
1151 1323 4 break;
1152 267339 5 if (slash <= entry->path)
1153 9132 6,25 return 0;
1154 259192 7 }
1155 1323 8 len = slash - name;
1156 -
1157 1323 8,9 if (!index_find(&pos, index, name, len, stage)) {
1158 1 10 if (!ok_to_replace)
1159 ##### 11 return -1;
1160 -
1161 1 12,13 if (index_remove_entry(index, pos) < 0)
1162 ##### 14 break;
1163 1 15 continue;
1164 - }
1165 -
1166 - /*
1167 - * Trivial optimization: if we find an entry that
1168 - * already matches the sub-directory, then we know
1169 - * we're ok, and we can exit.
1170 - */
1171 2341 16,22-24 for (; pos < index->entries.length; ++pos) {
1172 2225 17 struct entry_internal *p = index->entries.contents[pos];
1173 -
1174 2225 17,18 if (p->pathlen <= len ||
1175 2079 18,19 p->path[len] != '/' ||
1176 2006 19 memcmp(p->path, name, len))
1177 - break; /* not our subdirectory */
1178 -
1179 2004 20 if (GIT_INDEX_ENTRY_STAGE(&p->entry) == stage)
1180 985 21 return 0;
1181 - }
1182 338 26 }
1183 -
1184 ##### 14 return 0;
1185 - }
1186 -
1187 9132 2 static int check_file_directory_collision(git_index *index,
1188 - git_index_entry *entry, size_t pos, int ok_to_replace)
1189 - {
1190 9132 2,3,5 if (has_file_name(index, entry, pos, ok_to_replace) < 0 ||
1191 9132 4 has_dir_name(index, entry, ok_to_replace) < 0) {
1192 ##### 6 git_error_set(GIT_ERROR_INDEX,
1193 - "'%s' appears as both a file and a directory", entry->path);
1194 ##### 7 return -1;
1195 - }
1196 -
1197 9132 8 return 0;
1198 - }
1199 -
1200 2956 2 static int canonicalize_directory_path(
1201 - git_index *index,
1202 - git_index_entry *entry,
1203 - git_index_entry *existing)
1204 - {
1205 2956 2 const git_index_entry *match, *best = NULL;
1206 - char *search, *sep;
1207 - size_t pos, search_len, best_len;
1208 -
1209 2956 2 if (!index->ignore_case)
1210 2953 3 return 0;
1211 -
1212 - /* item already exists in the index, simply re-use the existing case */
1213 3 4 if (existing) {
1214 2 5 memcpy((char *)entry->path, existing->path, strlen(existing->path));
1215 2 5 return 0;
1216 - }
1217 -
1218 - /* nothing to do */
1219 1 6 if (strchr(entry->path, '/') == NULL)
1220 1 7 return 0;
1221 -
1222 ##### 8,9 if ((search = git__strdup(entry->path)) == NULL)
1223 ##### 10 return -1;
1224 -
1225 - /* starting at the parent directory and descending to the root, find the
1226 - * common parent directory.
1227 - */
1228 ##### 11,26,27 while (!best && (sep = strrchr(search, '/'))) {
1229 ##### 12 sep[1] = '\0';
1230 -
1231 ##### 12 search_len = strlen(search);
1232 -
1233 ##### 12 git_vector_bsearch2(
1234 - &pos, &index->entries, index->entries_search_path, search);
1235 -
1236 ##### 13,23,24 while ((match = git_vector_get(&index->entries, pos))) {
1237 ##### 14 if (GIT_INDEX_ENTRY_STAGE(match) != 0) {
1238 - /* conflicts do not contribute to canonical paths */
1239 ##### 15 } else if (strncmp(search, match->path, search_len) == 0) {
1240 - /* prefer an exact match to the input filename */
1241 ##### 16 best = match;
1242 ##### 16 best_len = search_len;
1243 ##### 16 break;
1244 ##### 17 } else if (strncasecmp(search, match->path, search_len) == 0) {
1245 - /* continue walking, there may be a path with an exact
1246 - * (case sensitive) match later in the index, but use this
1247 - * as the best match until that happens.
1248 - */
1249 ##### 18 if (!best) {
1250 ##### 19 best = match;
1251 ##### 19,20 best_len = search_len;
1252 - }
1253 - } else {
1254 ##### 21 break;
1255 - }
1256 -
1257 ##### 22 pos++;
1258 - }
1259 -
1260 ##### 25 sep[0] = '\0';
1261 - }
1262 -
1263 ##### 28 if (best)
1264 ##### 29 memcpy((char *)entry->path, best->path, best_len);
1265 -
1266 ##### 30 git__free(search);
1267 ##### 31 return 0;
1268 - }
1269 -
1270 ##### 2 static int index_no_dups(void **old, void *new)
1271 - {
1272 ##### 2 const git_index_entry *entry = new;
1273 - GIT_UNUSED(old);
1274 ##### 2 git_error_set(GIT_ERROR_INDEX, "'%s' appears multiple times at stage %d",
1275 ##### 2 entry->path, GIT_INDEX_ENTRY_STAGE(entry));
1276 ##### 3 return GIT_EEXISTS;
1277 - }
1278 -
1279 9138 2 static void index_existing_and_best(
1280 - git_index_entry **existing,
1281 - size_t *existing_position,
1282 - git_index_entry **best,
1283 - git_index *index,
1284 - const git_index_entry *entry)
1285 - {
1286 - git_index_entry *e;
1287 - size_t pos;
1288 - int error;
1289 -
1290 9138 2 error = index_find(&pos,
1291 9138 2 index, entry->path, 0, GIT_INDEX_ENTRY_STAGE(entry));
1292 -
1293 9138 3 if (error == 0) {
1294 2427 4 *existing = index->entries.contents[pos];
1295 2427 4 *existing_position = pos;
1296 2427 4 *best = index->entries.contents[pos];
1297 9138 4,18 return;
1298 - }
1299 -
1300 6711 5 *existing = NULL;
1301 6711 5 *existing_position = 0;
1302 6711 5 *best = NULL;
1303 -
1304 6711 5 if (GIT_INDEX_ENTRY_STAGE(entry) == 0) {
1305 5205 6,14,16 for (; pos < index->entries.length; pos++) {
1306 3868 10 int (*strcomp)(const char *a, const char *b) =
1307 3868 7-9 index->ignore_case ? git__strcasecmp : git__strcmp;
1308 -
1309 3868 10 e = index->entries.contents[pos];
1310 -
1311 3868 10,11 if (strcomp(entry->path, e->path) != 0)
1312 3858 12 break;
1313 -
1314 10 13 if (GIT_INDEX_ENTRY_STAGE(e) == GIT_INDEX_STAGE_ANCESTOR) {
1315 5 14 *best = e;
1316 5 14 continue;
1317 - } else {
1318 5 15 *best = e;
1319 5 15 break;
1320 - }
1321 - }
1322 - }
1323 - }
1324 -
1325 - /* index_insert takes ownership of the new entry - if it can't insert
1326 - * it, then it will return an error **and also free the entry**. When
1327 - * it replaces an existing entry, it will update the entry_ptr with the
1328 - * actual entry in the index (and free the passed in one).
1329 - *
1330 - * trust_path is whether we use the given path, or whether (on case
1331 - * insensitive systems only) we try to canonicalize the given path to
1332 - * be within an existing directory.
1333 - *
1334 - * trust_mode is whether we trust the mode in entry_ptr.
1335 - *
1336 - * trust_id is whether we trust the id or it should be validated.
1337 - */
1338 9138 2 static int index_insert(
1339 - git_index *index,
1340 - git_index_entry **entry_ptr,
1341 - int replace,
1342 - bool trust_path,
1343 - bool trust_mode,
1344 - bool trust_id)
1345 - {
1346 - git_index_entry *existing, *best, *entry;
1347 - size_t path_length, position;
1348 - int error;
1349 -
1350 9138 2-4 assert(index && entry_ptr);
1351 -
1352 9138 5 entry = *entry_ptr;
1353 -
1354 - /* Make sure that the path length flag is correct */
1355 9138 5 path_length = ((struct entry_internal *)entry)->pathlen;
1356 9138 5 index_entry_adjust_namemask(entry, path_length);
1357 -
1358 - /* This entry is now up-to-date and should not be checked for raciness */
1359 9138 6 entry->flags_extended |= GIT_INDEX_ENTRY_UPTODATE;
1360 -
1361 9138 6 git_vector_sort(&index->entries);
1362 -
1363 - /*
1364 - * Look if an entry with this path already exists, either staged, or (if
1365 - * this entry is a regular staged item) as the "ours" side of a conflict.
1366 - */
1367 9138 7 index_existing_and_best(&existing, &position, &best, index, entry);
1368 -
1369 - /* Update the file mode */
1370 9138 11 entry->mode = trust_mode ?
1371 9138 8-10 git_index__create_mode(entry->mode) :
1372 2956 10 index_merge_mode(index, best, entry->mode);
1373 -
1374 - /* Canonicalize the directory name */
1375 9138 11-13 if (!trust_path && (error = canonicalize_directory_path(index, entry, best)) < 0)
1376 ##### 14 goto out;
1377 -
1378 - /* Ensure that the given id exists (unless it's a submodule) */
1379 9138 15-17 if (!trust_id && INDEX_OWNER(index) &&
1380 4425 17 (entry->mode & GIT_FILEMODE_COMMIT) != GIT_FILEMODE_COMMIT) {
1381 -
1382 4385 18-20 if (!git_object__is_valid(INDEX_OWNER(index), &entry->id,
1383 4385 18 git_object__type_from_filemode(entry->mode))) {
1384 6 21 error = -1;
1385 6 21 goto out;
1386 - }
1387 - }
1388 -
1389 - /* Look for tree / blob name collisions, removing conflicts if requested */
1390 9132 22,23 if ((error = check_file_directory_collision(index, entry, position, replace)) < 0)
1391 ##### 24 goto out;
1392 -
1393 - /*
1394 - * If we are replacing an existing item, overwrite the existing entry
1395 - * and return it in place of the passed in one.
1396 - */
1397 9132 25 if (existing) {
1398 2421 26 if (replace) {
1399 2421 27 index_entry_cpy(existing, entry);
1400 -
1401 2421 28 if (trust_path)
1402 2229 29 memcpy((char *)existing->path, entry->path, strlen(entry->path));
1403 - }
1404 -
1405 2421 30 index_entry_free(entry);
1406 2421 31 *entry_ptr = existing;
1407 - } else {
1408 - /*
1409 - * If replace is not requested or no existing entry exists, insert
1410 - * at the sorted position. (Since we re-sort after each insert to
1411 - * check for dups, this is actually cheaper in the long run.)
1412 - */
1413 6711 32-35 if ((error = git_vector_insert_sorted(&index->entries, entry, index_no_dups)) < 0 ||
1414 6711 34 (error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0)
1415 - goto out;
1416 - }
1417 -
1418 9132 36 index->dirty = 1;
1419 -
1420 - out:
1421 9138 37 if (error < 0) {
1422 6 38 index_entry_free(*entry_ptr);
1423 6 39 *entry_ptr = NULL;
1424 - }
1425 -
1426 9138 40 return error;
1427 - }
1428 -
1429 4647 2 static int index_conflict_to_reuc(git_index *index, const char *path)
1430 - {
1431 - const git_index_entry *conflict_entries[3];
1432 - int ancestor_mode, our_mode, their_mode;
1433 - git_oid const *ancestor_oid, *our_oid, *their_oid;
1434 - int ret;
1435 -
1436 4647 2,3 if ((ret = git_index_conflict_get(&conflict_entries[0],
1437 - &conflict_entries[1], &conflict_entries[2], index, path)) < 0)
1438 4640 4 return ret;
1439 -
1440 7 5-7 ancestor_mode = conflict_entries[0] == NULL ? 0 : conflict_entries[0]->mode;
1441 7 8-10 our_mode = conflict_entries[1] == NULL ? 0 : conflict_entries[1]->mode;
1442 7 11-13 their_mode = conflict_entries[2] == NULL ? 0 : conflict_entries[2]->mode;
1443 -
1444 7 14-16 ancestor_oid = conflict_entries[0] == NULL ? NULL : &conflict_entries[0]->id;
1445 7 17-19 our_oid = conflict_entries[1] == NULL ? NULL : &conflict_entries[1]->id;
1446 7 20-22 their_oid = conflict_entries[2] == NULL ? NULL : &conflict_entries[2]->id;
1447 -
1448 7 23,24 if ((ret = git_index_reuc_add(index, path, ancestor_mode, ancestor_oid,
1449 - our_mode, our_oid, their_mode, their_oid)) >= 0)
1450 7 25 ret = git_index_conflict_remove(index, path);
1451 -
1452 7 26 return ret;
1453 - }
1454 -
1455 6197 2 GIT_INLINE(bool) is_file_or_link(const int filemode)
1456 - {
1457 211 3 return (filemode == GIT_FILEMODE_BLOB ||
1458 6197 2,4-6 filemode == GIT_FILEMODE_BLOB_EXECUTABLE ||
1459 - filemode == GIT_FILEMODE_LINK);
1460 - }
1461 -
1462 5523 2 GIT_INLINE(bool) valid_filemode(const int filemode)
1463 - {
1464 5523 2 return (is_file_or_link(filemode) || filemode == GIT_FILEMODE_COMMIT);
1465 - }
1466 -
1467 674 2 int git_index_add_from_buffer(
1468 - git_index *index, const git_index_entry *source_entry,
1469 - const void *buffer, size_t len)
1470 - {
1471 674 2 git_index_entry *entry = NULL;
1472 674 2 int error = 0;
1473 - git_oid id;
1474 -
1475 674 2-4 assert(index && source_entry->path);
1476 -
1477 674 5 if (INDEX_OWNER(index) == NULL)
1478 ##### 6 return create_index_error(-1,
1479 - "could not initialize index entry. "
1480 - "Index is not backed up by an existing repository.");
1481 -
1482 674 7,8 if (!is_file_or_link(source_entry->mode)) {
1483 2 9 git_error_set(GIT_ERROR_INDEX, "invalid filemode");
1484 2 10 return -1;
1485 - }
1486 -
1487 672 11 if (len > UINT32_MAX) {
1488 ##### 12 git_error_set(GIT_ERROR_INDEX, "buffer is too large");
1489 ##### 13 return -1;
1490 - }
1491 -
1492 672 14,15 if (index_entry_dup(&entry, index, source_entry) < 0)
1493 ##### 16 return -1;
1494 -
1495 672 17 error = git_blob_create_from_buffer(&id, INDEX_OWNER(index), buffer, len);
1496 672 18 if (error < 0) {
1497 ##### 19 index_entry_free(entry);
1498 ##### 20 return error;
1499 - }
1500 -
1501 672 21 git_oid_cpy(&entry->id, &id);
1502 672 22 entry->file_size = (uint32_t)len;
1503 -
1504 672 22,23 if ((error = index_insert(index, &entry, 1, true, true, true)) < 0)
1505 ##### 24 return error;
1506 -
1507 - /* Adding implies conflict was resolved, move conflict entries to REUC */
1508 672 25-27 if ((error = index_conflict_to_reuc(index, entry->path)) < 0 && error != GIT_ENOTFOUND)
1509 ##### 28 return error;
1510 -
1511 672 29 git_tree_cache_invalidate_path(index->tree, entry->path);
1512 672 30 return 0;
1513 - }
1514 -
1515 1 2 static int add_repo_as_submodule(git_index_entry **out, git_index *index, const char *path)
1516 - {
1517 - git_repository *sub;
1518 1 2 git_buf abspath = GIT_BUF_INIT;
1519 1 2 git_repository *repo = INDEX_OWNER(index);
1520 - git_reference *head;
1521 - git_index_entry *entry;
1522 - struct stat st;
1523 - int error;
1524 -
1525 1 2-4 if ((error = git_buf_joinpath(&abspath, git_repository_workdir(repo), path)) < 0)
1526 ##### 5 return error;
1527 -
1528 1 6,7 if ((error = p_stat(abspath.ptr, &st)) < 0) {
1529 ##### 8 git_error_set(GIT_ERROR_OS, "failed to stat repository dir");
1530 ##### 9 return -1;
1531 - }
1532 -
1533 1 10,11 if (index_entry_create(&entry, INDEX_OWNER(index), path, &st, true) < 0)
1534 ##### 12 return -1;
1535 -
1536 1 13 git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
1537 -
1538 1 14,15 if ((error = git_repository_open(&sub, abspath.ptr)) < 0)
1539 ##### 16 return error;
1540 -
1541 1 17,18 if ((error = git_repository_head(&head, sub)) < 0)
1542 ##### 19 return error;
1543 -
1544 1 20,21 git_oid_cpy(&entry->id, git_reference_target(head));
1545 1 22 entry->mode = GIT_FILEMODE_COMMIT;
1546 -
1547 1 22 git_reference_free(head);
1548 1 23 git_repository_free(sub);
1549 1 24 git_buf_dispose(&abspath);
1550 -
1551 1 25 *out = entry;
1552 1 25 return 0;
1553 - }
1554 -
1555 3239 2 int git_index_add_bypath(git_index *index, const char *path)
1556 - {
1557 3239 2 git_index_entry *entry = NULL;
1558 - int ret;
1559 -
1560 3239 2-4 assert(index && path);
1561 -
1562 3239 5,6 if ((ret = index_entry_init(&entry, index, path)) == 0)
1563 2955 7 ret = index_insert(index, &entry, 1, false, false, true);
1564 -
1565 - /* If we were given a directory, let's see if it's a submodule */
1566 3239 8,9 if (ret < 0 && ret != GIT_EDIRECTORY)
1567 281 10 return ret;
1568 -
1569 2958 11 if (ret == GIT_EDIRECTORY) {
1570 - git_submodule *sm;
1571 - git_error_state err;
1572 -
1573 3 12 git_error_state_capture(&err, ret);
1574 -
1575 3 13 ret = git_submodule_lookup(&sm, INDEX_OWNER(index), path);
1576 3 14 if (ret == GIT_ENOTFOUND)
1577 2 15,30 return git_error_state_restore(&err);
1578 -
1579 2 16 git_error_state_free(&err);
1580 -
1581 - /*
1582 - * EEXISTS means that there is a repository at that path, but it's not known
1583 - * as a submodule. We add its HEAD as an entry and don't register it.
1584 - */
1585 2 17 if (ret == GIT_EEXISTS) {
1586 1 18,19 if ((ret = add_repo_as_submodule(&entry, index, path)) < 0)
1587 ##### 20 return ret;
1588 -
1589 1 21,22 if ((ret = index_insert(index, &entry, 1, false, false, true)) < 0)
1590 ##### 23 return ret;
1591 1 24 } else if (ret < 0) {
1592 ##### 25 return ret;
1593 - } else {
1594 1 26 ret = git_submodule_add_to_index(sm, false);
1595 1 27 git_submodule_free(sm);
1596 1 28,29 return ret;
1597 - }
1598 - }
1599 -
1600 - /* Adding implies conflict was resolved, move conflict entries to REUC */
1601 2956 31-33 if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND)
1602 ##### 34 return ret;
1603 -
1604 2956 35 git_tree_cache_invalidate_path(index->tree, entry->path);
1605 2956 36 return 0;
1606 - }
1607 -
1608 1019 2 int git_index_remove_bypath(git_index *index, const char *path)
1609 - {
1610 - int ret;
1611 -
1612 1019 2-4 assert(index && path);
1613 -
1614 1019 5-7 if (((ret = git_index_remove(index, path, 0)) < 0 &&
1615 1019 8,9 ret != GIT_ENOTFOUND) ||
1616 1017 10 ((ret = index_conflict_to_reuc(index, path)) < 0 &&
1617 - ret != GIT_ENOTFOUND))
1618 ##### 11 return ret;
1619 -
1620 1019 12 if (ret == GIT_ENOTFOUND)
1621 1017 13 git_error_clear();
1622 -
1623 1019 14 return 0;
1624 - }
1625 -
1626 388 2 int git_index__fill(git_index *index, const git_vector *source_entries)
1627 - {
1628 388 2 const git_index_entry *source_entry = NULL;
1629 388 2 int error = 0;
1630 - size_t i;
1631 -
1632 388 2,3 assert(index);
1633 -
1634 388 4 if (!source_entries->length)
1635 4 5 return 0;
1636 -
1637 384 6,7,9 if (git_vector_size_hint(&index->entries, source_entries->length) < 0 ||
1638 384 8 index_map_resize(index->entries_map, (size_t)(source_entries->length * 1.3),
1639 384 8 index->ignore_case) < 0)
1640 ##### 10 return -1;
1641 -
1642 3302 11,23,25,26 git_vector_foreach(source_entries, i, source_entry) {
1643 2918 12 git_index_entry *entry = NULL;
1644 -
1645 2918 12,13 if ((error = index_entry_dup(&entry, index, source_entry)) < 0)
1646 ##### 14,24 break;
1647 -
1648 2918 15 index_entry_adjust_namemask(entry, ((struct entry_internal *)entry)->pathlen);
1649 2918 16 entry->flags_extended |= GIT_INDEX_ENTRY_UPTODATE;
1650 2918 16 entry->mode = git_index__create_mode(entry->mode);
1651 -
1652 2918 17,18 if ((error = git_vector_insert(&index->entries, entry)) < 0)
1653 ##### 19 break;
1654 -
1655 2918 20,21 if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0)
1656 ##### 22 break;
1657 -
1658 2918 23 index->dirty = 1;
1659 - }
1660 -
1661 384 27 if (!error)
1662 384 28 git_vector_sort(&index->entries);
1663 -
1664 384 29 return error;
1665 - }
1666 -
1667 -
1668 4829 2 int git_index_add(git_index *index, const git_index_entry *source_entry)
1669 - {
1670 4829 2 git_index_entry *entry = NULL;
1671 - int ret;
1672 -
1673 4829 2-5 assert(index && source_entry && source_entry->path);
1674 -
1675 4829 6,7 if (!valid_filemode(source_entry->mode)) {
1676 1 8 git_error_set(GIT_ERROR_INDEX, "invalid entry mode");
1677 1 9 return -1;
1678 - }
1679 -
1680 4828 10-13 if ((ret = index_entry_dup(&entry, index, source_entry)) < 0 ||
1681 - (ret = index_insert(index, &entry, 1, true, true, false)) < 0)
1682 12 14 return ret;
1683 -
1684 4816 15 git_tree_cache_invalidate_path(index->tree, entry->path);
1685 4816 16 return 0;
1686 - }
1687 -
1688 2952 2 int git_index_remove(git_index *index, const char *path, int stage)
1689 - {
1690 - int error;
1691 - size_t position;
1692 2952 2 git_index_entry remove_key = {{ 0 }};
1693 -
1694 2952 2 remove_key.path = path;
1695 2952 2 GIT_INDEX_ENTRY_STAGE_SET(&remove_key, stage);
1696 -
1697 2952 2 index_map_delete(index->entries_map, &remove_key, index->ignore_case);
1698 -
1699 2952 3,4 if (index_find(&position, index, path, 0, stage) < 0) {
1700 1538 5 git_error_set(
1701 - GIT_ERROR_INDEX, "index does not contain %s at stage %d", path, stage);
1702 1538 6 error = GIT_ENOTFOUND;
1703 - } else {
1704 1414 7 error = index_remove_entry(index, position);
1705 - }
1706 -
1707 2952 8 return error;
1708 - }
1709 -
1710 17 2 int git_index_remove_directory(git_index *index, const char *dir, int stage)
1711 - {
1712 17 2 git_buf pfx = GIT_BUF_INIT;
1713 17 2 int error = 0;
1714 - size_t pos;
1715 - git_index_entry *entry;
1716 -
1717 17 2-5 if (!(error = git_buf_sets(&pfx, dir)) &&
1718 - !(error = git_path_to_dir(&pfx)))
1719 17 6 index_find(&pos, index, pfx.ptr, pfx.size, GIT_INDEX_STAGE_ANY);
1720 -
1721 19 7,15 while (!error) {
1722 19 8 entry = git_vector_get(&index->entries, pos);
1723 19 9-11 if (!entry || git__prefixcmp(entry->path, pfx.ptr) != 0)
1724 - break;
1725 -
1726 2 12 if (GIT_INDEX_ENTRY_STAGE(entry) != stage) {
1727 ##### 13 ++pos;
1728 ##### 13 continue;
1729 - }
1730 -
1731 2 14 error = index_remove_entry(index, pos);
1732 -
1733 - /* removed entry at 'pos' so we don't need to increment */
1734 - }
1735 -
1736 17 16 git_buf_dispose(&pfx);
1737 -
1738 17 17 return error;
1739 - }
1740 -
1741 18 2 int git_index_find_prefix(size_t *at_pos, git_index *index, const char *prefix)
1742 - {
1743 18 2 int error = 0;
1744 - size_t pos;
1745 - const git_index_entry *entry;
1746 -
1747 18 2 index_find(&pos, index, prefix, strlen(prefix), GIT_INDEX_STAGE_ANY);
1748 18 3 entry = git_vector_get(&index->entries, pos);
1749 18 4-6 if (!entry || git__prefixcmp(entry->path, prefix) != 0)
1750 15 7 error = GIT_ENOTFOUND;
1751 -
1752 18 8,9 if (!error && at_pos)
1753 2 10 *at_pos = pos;
1754 -
1755 18 11 return error;
1756 - }
1757 -
1758 - 2 suppressed: function cannot be solved git_index__find_pos (automatic due to inconsistent arc counts in .gcda files)int git_index__find_pos(
1759 - size_t *out, git_index *index, const char *path, size_t path_len, int stage)
1760 - {
1761 - 2-4 suppressed: function cannot be solved git_index__find_pos (automatic due to inconsistent arc counts in .gcda files) assert(index && path);
1762 - 5 suppressed: function cannot be solved git_index__find_pos (automatic due to inconsistent arc counts in .gcda files) return index_find(out, index, path, path_len, stage);
1763 - }
1764 -
1765 5014 2 int git_index_find(size_t *at_pos, git_index *index, const char *path)
1766 - {
1767 - size_t pos;
1768 -
1769 5014 2-4 assert(index && path);
1770 -
1771 5014 5,6 if (git_vector_bsearch2(
1772 - &pos, &index->entries, index->entries_search_path, path) < 0) {
1773 1047 7 git_error_set(GIT_ERROR_INDEX, "index does not contain %s", path);
1774 1047 8 return GIT_ENOTFOUND;
1775 - }
1776 -
1777 - /* Since our binary search only looked at path, we may be in the
1778 - * middle of a list of stages.
1779 - */
1780 4141 9,14,15 for (; pos > 0; --pos) {
1781 3691 10 const git_index_entry *prev = git_vector_get(&index->entries, pos - 1);
1782 -
1783 3691 11,12 if (index->entries_cmp_path(prev->path, path) != 0)
1784 3517 13 break;
1785 - }
1786 -
1787 3967 16 if (at_pos)
1788 3966 17 *at_pos = pos;
1789 -
1790 3967 18 return 0;
1791 - }
1792 -
1793 268 2 int git_index_conflict_add(git_index *index,
1794 - const git_index_entry *ancestor_entry,
1795 - const git_index_entry *our_entry,
1796 - const git_index_entry *their_entry)
1797 - {
1798 268 2 git_index_entry *entries[3] = { 0 };
1799 - unsigned short i;
1800 268 2 int ret = 0;
1801 -
1802 268 2,3 assert (index);
1803 -
1804 268 4-6 if ((ancestor_entry &&
1805 268 7 (ret = index_entry_dup(&entries[0], index, ancestor_entry)) < 0) ||
1806 236 8,9 (our_entry &&
1807 268 10 (ret = index_entry_dup(&entries[1], index, our_entry)) < 0) ||
1808 238 11,12 (their_entry &&
1809 - (ret = index_entry_dup(&entries[2], index, their_entry)) < 0))
1810 - goto on_error;
1811 -
1812 - /* Validate entries */
1813 1066 13,19,20 for (i = 0; i < 3; i++) {
1814 801 14-16 if (entries[i] && !valid_filemode(entries[i]->mode)) {
1815 3 17 git_error_set(GIT_ERROR_INDEX, "invalid filemode for stage %d entry",
1816 - i + 1);
1817 3 18 ret = -1;
1818 3 18 goto on_error;
1819 - }
1820 - }
1821 -
1822 - /* Remove existing index entries for each path */
1823 1060 21,30,31 for (i = 0; i < 3; i++) {
1824 795 22 if (entries[i] == NULL)
1825 107 23 continue;
1826 -
1827 688 24,25 if ((ret = git_index_remove(index, entries[i]->path, 0)) != 0) {
1828 682 26 if (ret != GIT_ENOTFOUND)
1829 ##### 27 goto on_error;
1830 -
1831 682 28 git_error_clear();
1832 682 29 ret = 0;
1833 - }
1834 - }
1835 -
1836 - /* Add the conflict entries */
1837 1060 32,39,40 for (i = 0; i < 3; i++) {
1838 795 33 if (entries[i] == NULL)
1839 107 34 continue;
1840 -
1841 - /* Make sure stage is correct */
1842 688 35 GIT_INDEX_ENTRY_STAGE_SET(entries[i], i + 1);
1843 -
1844 688 35,36 if ((ret = index_insert(index, &entries[i], 1, true, true, false)) < 0)
1845 ##### 37 goto on_error;
1846 -
1847 688 38 entries[i] = NULL; /* don't free if later entry fails */
1848 - }
1849 -
1850 265 41 return 0;
1851 -
1852 - on_error:
1853 12 42,45,46 for (i = 0; i < 3; i++) {
1854 9 43 if (entries[i] != NULL)
1855 9 44 index_entry_free(entries[i]);
1856 - }
1857 -
1858 3 47 return ret;
1859 - }
1860 -
1861 4101 2 static int index_conflict__get_byindex(
1862 - const git_index_entry **ancestor_out,
1863 - const git_index_entry **our_out,
1864 - const git_index_entry **their_out,
1865 - git_index *index,
1866 - size_t n)
1867 - {
1868 - const git_index_entry *conflict_entry;
1869 4101 2 const char *path = NULL;
1870 - size_t count;
1871 4101 2 int stage, len = 0;
1872 -
1873 4101 2-6 assert(ancestor_out && our_out && their_out && index);
1874 -
1875 4101 7 *ancestor_out = NULL;
1876 4101 7 *our_out = NULL;
1877 4101 7 *their_out = NULL;
1878 -
1879 8779 7,18,19 for (count = git_index_entrycount(index); n < count; ++n) {
1880 8022 8 conflict_entry = git_vector_get(&index->entries, n);
1881 -
1882 8022 9-11 if (path && index->entries_cmp_path(conflict_entry->path, path) != 0)
1883 3344 12 break;
1884 -
1885 4678 13 stage = GIT_INDEX_ENTRY_STAGE(conflict_entry);
1886 4678 13 path = conflict_entry->path;
1887 -
1888 4678 13 switch (stage) {
1889 - case 3:
1890 350 14 *their_out = conflict_entry;
1891 350 14 len++;
1892 350 14 break;
1893 - case 2:
1894 350 15 *our_out = conflict_entry;
1895 350 15 len++;
1896 350 15 break;
1897 - case 1:
1898 349 16 *ancestor_out = conflict_entry;
1899 349 16 len++;
1900 349 16 break;
1901 - default:
1902 3629 17 break;
1903 - };
1904 - }
1905 -
1906 4101 20 return len;
1907 - }
1908 -
1909 4663 2 int git_index_conflict_get(
1910 - const git_index_entry **ancestor_out,
1911 - const git_index_entry **our_out,
1912 - const git_index_entry **their_out,
1913 - git_index *index,
1914 - const char *path)
1915 - {
1916 - size_t pos;
1917 4663 2 int len = 0;
1918 -
1919 4663 2-7 assert(ancestor_out && our_out && their_out && index && path);
1920 -
1921 4663 8 *ancestor_out = NULL;
1922 4663 8 *our_out = NULL;
1923 4663 8 *their_out = NULL;
1924 -
1925 4663 8,9 if (git_index_find(&pos, index, path) < 0)
1926 1017 10 return GIT_ENOTFOUND;
1927 -
1928 3646 11,12 if ((len = index_conflict__get_byindex(
1929 - ancestor_out, our_out, their_out, index, pos)) < 0)
1930 ##### 13 return len;
1931 3646 14 else if (len == 0)
1932 3624 15 return GIT_ENOTFOUND;
1933 -
1934 22 16 return 0;
1935 - }
1936 -
1937 210 2 static int index_conflict_remove(git_index *index, const char *path)
1938 - {
1939 210 2 size_t pos = 0;
1940 - git_index_entry *conflict_entry;
1941 210 2 int error = 0;
1942 -
1943 210 2-4 if (path != NULL && git_index_find(&pos, index, path) < 0)
1944 1 5 return GIT_ENOTFOUND;
1945 -
1946 674 6,16,17 while ((conflict_entry = git_vector_get(&index->entries, pos)) != NULL) {
1947 -
1948 670 7,9 if (path != NULL &&
1949 662 8 index->entries_cmp_path(conflict_entry->path, path) != 0)
1950 205 10 break;
1951 -
1952 465 11 if (GIT_INDEX_ENTRY_STAGE(conflict_entry) == 0) {
1953 11 12 pos++;
1954 11 12 continue;
1955 - }
1956 -
1957 454 13,14 if ((error = index_remove_entry(index, pos)) < 0)
1958 ##### 15 break;
1959 - }
1960 -
1961 209 18 return error;
1962 - }
1963 -
1964 209 2 int git_index_conflict_remove(git_index *index, const char *path)
1965 - {
1966 209 2-4 assert(index && path);
1967 209 5 return index_conflict_remove(index, path);
1968 - }
1969 -
1970 1 2 int git_index_conflict_cleanup(git_index *index)
1971 - {
1972 1 2,3 assert(index);
1973 1 4 return index_conflict_remove(index, NULL);
1974 - }
1975 -
1976 887 2 int git_index_has_conflicts(const git_index *index)
1977 - {
1978 - size_t i;
1979 - git_index_entry *entry;
1980 -
1981 887 2,3 assert(index);
1982 -
1983 7687 4,7-9 git_vector_foreach(&index->entries, i, entry) {
1984 6891 5 if (GIT_INDEX_ENTRY_STAGE(entry) > 0)
1985 91 6 return 1;
1986 - }
1987 -
1988 796 10 return 0;
1989 - }
1990 -
1991 2 2 int git_index_iterator_new(
1992 - git_index_iterator **iterator_out,
1993 - git_index *index)
1994 - {
1995 - git_index_iterator *it;
1996 - int error;
1997 -
1998 2 2-4 assert(iterator_out && index);
1999 -
2000 2 5 it = git__calloc(1, sizeof(git_index_iterator));
2001 2 6,7 GIT_ERROR_CHECK_ALLOC(it);
2002 -
2003 2 8,9 if ((error = git_index_snapshot_new(&it->snap, index)) < 0) {
2004 ##### 10 git__free(it);
2005 ##### 11 return error;
2006 - }
2007 -
2008 2 12 it->index = index;
2009 -
2010 2 12 *iterator_out = it;
2011 2 12 return 0;
2012 - }
2013 -
2014 220 2 int git_index_iterator_next(
2015 - const git_index_entry **out,
2016 - git_index_iterator *it)
2017 - {
2018 220 2-4 assert(out && it);
2019 -
2020 220 5,6 if (it->cur >= git_vector_length(&it->snap))
2021 2 7 return GIT_ITEROVER;
2022 -
2023 218 8 *out = (git_index_entry *)git_vector_get(&it->snap, it->cur++);
2024 218 9 return 0;
2025 - }
2026 -
2027 2 2 void git_index_iterator_free(git_index_iterator *it)
2028 - {
2029 2 2 if (it == NULL)
2030 2 3,6 return;
2031 -
2032 2 4 git_index_snapshot_release(&it->snap, it->index);
2033 2 5 git__free(it);
2034 - }
2035 -
2036 964 2 int git_index_conflict_iterator_new(
2037 - git_index_conflict_iterator **iterator_out,
2038 - git_index *index)
2039 - {
2040 964 2 git_index_conflict_iterator *it = NULL;
2041 -
2042 964 2-4 assert(iterator_out && index);
2043 -
2044 964 5 it = git__calloc(1, sizeof(git_index_conflict_iterator));
2045 964 6,7 GIT_ERROR_CHECK_ALLOC(it);
2046 -
2047 964 8 it->index = index;
2048 -
2049 964 8 *iterator_out = it;
2050 964 8 return 0;
2051 - }
2052 -
2053 1419 2 int git_index_conflict_next(
2054 - const git_index_entry **ancestor_out,
2055 - const git_index_entry **our_out,
2056 - const git_index_entry **their_out,
2057 - git_index_conflict_iterator *iterator)
2058 - {
2059 - const git_index_entry *entry;
2060 - int len;
2061 -
2062 1419 2-6 assert(ancestor_out && our_out && their_out && iterator);
2063 -
2064 1419 7 *ancestor_out = NULL;
2065 1419 7 *our_out = NULL;
2066 1419 7 *their_out = NULL;
2067 -
2068 15147 7,16 while (iterator->cur < iterator->index->entries.length) {
2069 14183 8 entry = git_index_get_byindex(iterator->index, iterator->cur);
2070 -
2071 14183 9,10 if (git_index_entry_is_conflict(entry)) {
2072 455 11,12 if ((len = index_conflict__get_byindex(
2073 - ancestor_out,
2074 - our_out,
2075 - their_out,
2076 - iterator->index,
2077 - iterator->cur)) < 0)
2078 ##### 13 return len;
2079 -
2080 455 14 iterator->cur += len;
2081 455 14 return 0;
2082 - }
2083 -
2084 13728 15 iterator->cur++;
2085 - }
2086 -
2087 964 17 return GIT_ITEROVER;
2088 - }
2089 -
2090 964 2 void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator)
2091 - {
2092 964 2 if (iterator == NULL)
2093 964 3,5 return;
2094 -
2095 964 4 git__free(iterator);
2096 - }
2097 -
2098 264 2 size_t git_index_name_entrycount(git_index *index)
2099 - {
2100 264 2,3 assert(index);
2101 264 4 return index->names.length;
2102 - }
2103 -
2104 88 2 const git_index_name_entry *git_index_name_get_byindex(
2105 - git_index *index, size_t n)
2106 - {
2107 88 2,3 assert(index);
2108 -
2109 88 4 git_vector_sort(&index->names);
2110 88 5 return git_vector_get(&index->names, n);
2111 - }
2112 -
2113 118 2 static void index_name_entry_free(git_index_name_entry *ne)
2114 - {
2115 118 2 if (!ne)
2116 118 3,8 return;
2117 118 4 git__free(ne->ancestor);
2118 118 5 git__free(ne->ours);
2119 118 6 git__free(ne->theirs);
2120 118 7 git__free(ne);
2121 - }
2122 -
2123 115 2 int git_index_name_add(git_index *index,
2124 - const char *ancestor, const char *ours, const char *theirs)
2125 - {
2126 - git_index_name_entry *conflict_name;
2127 -
2128 115 2-8 assert((ancestor && ours) || (ancestor && theirs) || (ours && theirs));
2129 -
2130 115 9 conflict_name = git__calloc(1, sizeof(git_index_name_entry));
2131 115 10,11 GIT_ERROR_CHECK_ALLOC(conflict_name);
2132 -
2133 115 12-15 if ((ancestor && !(conflict_name->ancestor = git__strdup(ancestor))) ||
2134 115 16-18 (ours && !(conflict_name->ours = git__strdup(ours))) ||
2135 115 19,20,22 (theirs && !(conflict_name->theirs = git__strdup(theirs))) ||
2136 115 21 git_vector_insert(&index->names, conflict_name) < 0)
2137 - {
2138 ##### 23 index_name_entry_free(conflict_name);
2139 ##### 24 return -1;
2140 - }
2141 -
2142 115 25 index->dirty = 1;
2143 115 25 return 0;
2144 - }
2145 -
2146 5743 2 int git_index_name_clear(git_index *index)
2147 - {
2148 - size_t i;
2149 - git_index_name_entry *conflict_name;
2150 -
2151 5743 2,3 assert(index);
2152 -
2153 5861 4,6-8 git_vector_foreach(&index->names, i, conflict_name)
2154 118 5 index_name_entry_free(conflict_name);
2155 -
2156 5743 9 git_vector_clear(&index->names);
2157 -
2158 5743 10 index->dirty = 1;
2159 -
2160 5743 10 return 0;
2161 - }
2162 -
2163 48 2 size_t git_index_reuc_entrycount(git_index *index)
2164 - {
2165 48 2,3 assert(index);
2166 48 4 return index->reuc.length;
2167 - }
2168 -
2169 1565 2 static int index_reuc_on_dup(void **old, void *new)
2170 - {
2171 1565 2 index_entry_reuc_free(*old);
2172 1565 3 *old = new;
2173 1565 3 return GIT_EEXISTS;
2174 - }
2175 -
2176 4262 2 static int index_reuc_insert(
2177 - git_index *index,
2178 - git_index_reuc_entry *reuc)
2179 - {
2180 - int res;
2181 -
2182 4262 2-5 assert(index && reuc && reuc->path != NULL);
2183 4262 6,7 assert(git_vector_is_sorted(&index->reuc));
2184 -
2185 4262 8 res = git_vector_insert_sorted(&index->reuc, reuc, &index_reuc_on_dup);
2186 4262 9 index->dirty = 1;
2187 -
2188 4262 9 return res == GIT_EEXISTS ? 0 : res;
2189 - }
2190 -
2191 4262 2 int git_index_reuc_add(git_index *index, const char *path,
2192 - int ancestor_mode, const git_oid *ancestor_oid,
2193 - int our_mode, const git_oid *our_oid,
2194 - int their_mode, const git_oid *their_oid)
2195 - {
2196 4262 2 git_index_reuc_entry *reuc = NULL;
2197 4262 2 int error = 0;
2198 -
2199 4262 2-4 assert(index && path);
2200 -
2201 4262 5,6 if ((error = index_entry_reuc_init(&reuc, path, ancestor_mode,
2202 4262 7,8 ancestor_oid, our_mode, our_oid, their_mode, their_oid)) < 0 ||
2203 4262 7 (error = index_reuc_insert(index, reuc)) < 0)
2204 ##### 9 index_entry_reuc_free(reuc);
2205 -
2206 4262 10 return error;
2207 - }
2208 -
2209 3857 2 int git_index_reuc_find(size_t *at_pos, git_index *index, const char *path)
2210 - {
2211 3857 2 return git_vector_bsearch2(at_pos, &index->reuc, index->reuc_search, path);
2212 - }
2213 -
2214 4030 2 const git_index_reuc_entry *git_index_reuc_get_bypath(
2215 - git_index *index, const char *path)
2216 - {
2217 - size_t pos;
2218 4030 2-4 assert(index && path);
2219 -
2220 4030 5 if (!index->reuc.length)
2221 173 6 return NULL;
2222 -
2223 3857 7,8 assert(git_vector_is_sorted(&index->reuc));
2224 -
2225 3857 9,10 if (git_index_reuc_find(&pos, index, path) < 0)
2226 2274 11 return NULL;
2227 -
2228 1583 12 return git_vector_get(&index->reuc, pos);
2229 - }
2230 -
2231 64 2 const git_index_reuc_entry *git_index_reuc_get_byindex(
2232 - git_index *index, size_t n)
2233 - {
2234 64 2,3 assert(index);
2235 64 4,5 assert(git_vector_is_sorted(&index->reuc));
2236 -
2237 64 6 return git_vector_get(&index->reuc, n);
2238 - }
2239 -
2240 2 2 int git_index_reuc_remove(git_index *index, size_t position)
2241 - {
2242 - int error;
2243 - git_index_reuc_entry *reuc;
2244 -
2245 2 2,3 assert(git_vector_is_sorted(&index->reuc));
2246 -
2247 2 4 reuc = git_vector_get(&index->reuc, position);
2248 2 5 error = git_vector_remove(&index->reuc, position);
2249 -
2250 2 6 if (!error)
2251 1 7 index_entry_reuc_free(reuc);
2252 -
2253 2 8 index->dirty = 1;
2254 2 8 return error;
2255 - }
2256 -
2257 5743 2 int git_index_reuc_clear(git_index *index)
2258 - {
2259 - size_t i;
2260 -
2261 5743 2,3 assert(index);
2262 -
2263 8772 4,7,8 for (i = 0; i < index->reuc.length; ++i)
2264 3029 5,6 index_entry_reuc_free(git__swap(index->reuc.contents[i], NULL));
2265 -
2266 5743 9 git_vector_clear(&index->reuc);
2267 -
2268 5743 10 index->dirty = 1;
2269 -
2270 5743 10 return 0;
2271 - }
2272 -
2273 ##### 2 static int index_error_invalid(const char *message)
2274 - {
2275 ##### 2 git_error_set(GIT_ERROR_INDEX, "invalid data in index - %s", message);
2276 ##### 3 return -1;
2277 - }
2278 -
2279 184 2 static int read_reuc(git_index *index, const char *buffer, size_t size)
2280 - {
2281 - const char *endptr;
2282 - size_t len;
2283 - int i;
2284 -
2285 - /* If called multiple times, the vector might already be initialized */
2286 184 2,4 if (index->reuc._alloc_size == 0 &&
2287 ##### 3 git_vector_init(&index->reuc, 16, reuc_cmp) < 0)
2288 ##### 5 return -1;
2289 -
2290 517 6,42 while (size) {
2291 - git_index_reuc_entry *lost;
2292 -
2293 333 7 len = p_strnlen(buffer, size) + 1;
2294 333 8 if (size <= len)
2295 ##### 9 return index_error_invalid("reading reuc entries");
2296 -
2297 333 10 lost = reuc_entry_alloc(buffer);
2298 333 11,12 GIT_ERROR_CHECK_ALLOC(lost);
2299 -
2300 333 13 size -= len;
2301 333 13 buffer += len;
2302 -
2303 - /* read 3 ASCII octal numbers for stage entries */
2304 1332 13,26,28 for (i = 0; i < 3; i++) {
2305 - int64_t tmp;
2306 -
2307 999 14-16 if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 ||
2308 999 16-19 !endptr || endptr == buffer || *endptr ||
2309 999 19,20 tmp < 0 || tmp > UINT32_MAX) {
2310 ##### 21 index_entry_reuc_free(lost);
2311 ##### 22,27 return index_error_invalid("reading reuc entry stage");
2312 - }
2313 -
2314 999 23 lost->mode[i] = (uint32_t)tmp;
2315 -
2316 999 23 len = (endptr + 1) - buffer;
2317 999 23 if (size <= len) {
2318 ##### 24 index_entry_reuc_free(lost);
2319 ##### 25 return index_error_invalid("reading reuc entry stage");
2320 - }
2321 -
2322 999 26 size -= len;
2323 999 26 buffer += len;
2324 - }
2325 -
2326 - /* read up to 3 OIDs for stage entries */
2327 1332 29,37,38 for (i = 0; i < 3; i++) {
2328 999 30 if (!lost->mode[i])
2329 148 31 continue;
2330 851 32 if (size < 20) {
2331 ##### 33 index_entry_reuc_free(lost);
2332 ##### 34 return index_error_invalid("reading reuc entry oid");
2333 - }
2334 -
2335 851 35 git_oid_fromraw(&lost->oid[i], (const unsigned char *) buffer);
2336 851 36 size -= 20;
2337 851 36 buffer += 20;
2338 - }
2339 -
2340 - /* entry was read successfully - insert into reuc vector */
2341 333 39,40 if (git_vector_insert(&index->reuc, lost) < 0)
2342 ##### 41 return -1;
2343 - }
2344 -
2345 - /* entries are guaranteed to be sorted on-disk */
2346 184 43 git_vector_set_sorted(&index->reuc, true);
2347 -
2348 184 43 return 0;
2349 - }
2350 -
2351 -
2352 1 2 static int read_conflict_names(git_index *index, const char *buffer, size_t size)
2353 - {
2354 - size_t len;
2355 -
2356 - /* This gets called multiple times, the vector might already be initialized */
2357 1 2,4 if (index->names._alloc_size == 0 &&
2358 ##### 3 git_vector_init(&index->names, 16, conflict_name_cmp) < 0)
2359 ##### 5 return -1;
2360 -
2361 - #define read_conflict_name(ptr) \
2362 - len = p_strnlen(buffer, size) + 1; \
2363 - if (size < len) { \
2364 - index_error_invalid("reading conflict name entries"); \
2365 - goto out_err; \
2366 - } \
2367 - if (len == 1) \
2368 - ptr = NULL; \
2369 - else { \
2370 - ptr = git__malloc(len); \
2371 - GIT_ERROR_CHECK_ALLOC(ptr); \
2372 - memcpy(ptr, buffer, len); \
2373 - } \
2374 - \
2375 - buffer += len; \
2376 - size -= len;
2377 -
2378 4 6,46 while (size) {
2379 3 7 git_index_name_entry *conflict_name = git__calloc(1, sizeof(git_index_name_entry));
2380 3 8,9 GIT_ERROR_CHECK_ALLOC(conflict_name);
2381 -
2382 3 10-18 read_conflict_name(conflict_name->ancestor);
2383 3 19-27 read_conflict_name(conflict_name->ours);
2384 3 28-36 read_conflict_name(conflict_name->theirs);
2385 -
2386 3 37,38 if (git_vector_insert(&index->names, conflict_name) < 0)
2387 ##### 39 goto out_err;
2388 -
2389 3 40 continue;
2390 -
2391 - out_err:
2392 ##### 41 git__free(conflict_name->ancestor);
2393 ##### 42 git__free(conflict_name->ours);
2394 ##### 43 git__free(conflict_name->theirs);
2395 ##### 44 git__free(conflict_name);
2396 ##### 45 return -1;
2397 - }
2398 -
2399 - #undef read_conflict_name
2400 -
2401 - /* entries are guaranteed to be sorted on-disk */
2402 1 47 git_vector_set_sorted(&index->names, true);
2403 -
2404 1 47 return 0;
2405 - }
2406 -
2407 55350 2 static size_t index_entry_size(size_t path_len, size_t varint_len, uint32_t flags)
2408 - {
2409 55350 2 if (varint_len) {
2410 679 3 if (flags & GIT_INDEX_ENTRY_EXTENDED)
2411 ##### 4 return offsetof(struct entry_long, path) + path_len + 1 + varint_len;
2412 - else
2413 679 5 return offsetof(struct entry_short, path) + path_len + 1 + varint_len;
2414 - } else {
2415 - #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
2416 54671 6 if (flags & GIT_INDEX_ENTRY_EXTENDED)
2417 ##### 7 return entry_size(struct entry_long, path_len);
2418 - else
2419 54671 8 return entry_size(struct entry_short, path_len);
2420 - #undef entry_size
2421 - }
2422 - }
2423 -
2424 32737 2 static int read_entry(
2425 - git_index_entry **out,
2426 - size_t *out_size,
2427 - git_index *index,
2428 - const void *buffer,
2429 - size_t buffer_size,
2430 - const char *last)
2431 - {
2432 - size_t path_length, entry_size;
2433 - const char *path_ptr;
2434 - struct entry_short source;
2435 32737 2 git_index_entry entry = {{0}};
2436 32737 2 bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP;
2437 32737 2 char *tmp_path = NULL;
2438 -
2439 32737 2 if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
2440 1 3 return -1;
2441 -
2442 - /* buffer is not guaranteed to be aligned */
2443 32736 4 memcpy(&source, buffer, sizeof(struct entry_short));
2444 -
2445 32736 4 entry.ctime.seconds = (git_time_t)ntohl(source.ctime.seconds);
2446 32749 5 entry.ctime.nanoseconds = ntohl(source.ctime.nanoseconds);
2447 32748 6 entry.mtime.seconds = (git_time_t)ntohl(source.mtime.seconds);
2448 32745 7 entry.mtime.nanoseconds = ntohl(source.mtime.nanoseconds);
2449 32743 8 entry.dev = ntohl(source.dev);
2450 32736 9 entry.ino = ntohl(source.ino);
2451 32722 10 entry.mode = ntohl(source.mode);
2452 32736 11 entry.uid = ntohl(source.uid);
2453 32731 12 entry.gid = ntohl(source.gid);
2454 32732 13 entry.file_size = ntohl(source.file_size);
2455 32729 14 git_oid_cpy(&entry.id, &source.oid);
2456 32716 15 entry.flags = ntohs(source.flags);
2457 -
2458 32721 16 if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) {
2459 - uint16_t flags_raw;
2460 - size_t flags_offset;
2461 -
2462 ##### 17 flags_offset = offsetof(struct entry_long, flags_extended);
2463 ##### 17 memcpy(&flags_raw, (const char *) buffer + flags_offset,
2464 - sizeof(flags_raw));
2465 ##### 17 flags_raw = ntohs(flags_raw);
2466 -
2467 1 18 memcpy(&entry.flags_extended, &flags_raw, sizeof(flags_raw));
2468 1 18 path_ptr = (const char *) buffer + offsetof(struct entry_long, path);
2469 - } else
2470 32721 19 path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
2471 -
2472 32722 20 if (!compressed) {
2473 32705 21 path_length = entry.flags & GIT_INDEX_ENTRY_NAMEMASK;
2474 -
2475 - /* if this is a very long string, we must find its
2476 - * real length without overflowing */
2477 32705 21 if (path_length == 0xFFF) {
2478 - const char *path_end;
2479 -
2480 ##### 22 path_end = memchr(path_ptr, '\0', buffer_size);
2481 ##### 22 if (path_end == NULL)
2482 ##### 23 return -1;
2483 -
2484 ##### 24 path_length = path_end - path_ptr;
2485 - }
2486 -
2487 32705 25 entry_size = index_entry_size(path_length, 0, entry.flags);
2488 32704 26 entry.path = (char *)path_ptr;
2489 - } else {
2490 - size_t varint_len, last_len, prefix_len, suffix_len, path_len;
2491 - uintmax_t strip_len;
2492 -
2493 17 27 strip_len = git_decode_varint((const unsigned char *)path_ptr, &varint_len);
2494 17 28 last_len = strlen(last);
2495 -
2496 17 28,29 if (varint_len == 0 || last_len < strip_len)
2497 ##### 30,52 return index_error_invalid("incorrect prefix length");
2498 -
2499 17 31 prefix_len = last_len - (size_t)strip_len;
2500 17 31 suffix_len = strlen(path_ptr + varint_len);
2501 -
2502 17 31-37 GIT_ERROR_CHECK_ALLOC_ADD(&path_len, prefix_len, suffix_len);
2503 17 38-44 GIT_ERROR_CHECK_ALLOC_ADD(&path_len, path_len, 1);
2504 -
2505 17 45 if (path_len > GIT_PATH_MAX)
2506 ##### 46 return index_error_invalid("unreasonable path length");
2507 -
2508 17 47 tmp_path = git__malloc(path_len);
2509 17 48,49 GIT_ERROR_CHECK_ALLOC(tmp_path);
2510 -
2511 17 50 memcpy(tmp_path, last, prefix_len);
2512 17 50 memcpy(tmp_path + prefix_len, path_ptr + varint_len, suffix_len + 1);
2513 17 50 entry_size = index_entry_size(suffix_len, varint_len, entry.flags);
2514 17 51 entry.path = tmp_path;
2515 - }
2516 -
2517 32721 53 if (entry_size == 0)
2518 ##### 54 return -1;
2519 -
2520 32721 55 if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2521 ##### 56 return -1;
2522 -
2523 32735 57,58 if (index_entry_dup(out, index, &entry) < 0) {
2524 ##### 59 git__free(tmp_path);
2525 ##### 60 return -1;
2526 - }
2527 -
2528 32735 61 git__free(tmp_path);
2529 32729 62 *out_size = entry_size;
2530 32729 62 return 0;
2531 - }
2532 -
2533 1778 2 static int read_header(struct index_header *dest, const void *buffer)
2534 - {
2535 1778 2 const struct index_header *source = buffer;
2536 -
2537 1778 2 dest->signature = ntohl(source->signature);
2538 1778 3 if (dest->signature != INDEX_HEADER_SIG)
2539 ##### 4 return index_error_invalid("incorrect header signature");
2540 -
2541 1778 5 dest->version = ntohl(source->version);
2542 1778 6,7 if (dest->version < INDEX_VERSION_NUMBER_LB ||
2543 1778 7 dest->version > INDEX_VERSION_NUMBER_UB)
2544 ##### 8 return index_error_invalid("incorrect header version");
2545 -
2546 1778 9 dest->entry_count = ntohl(source->entry_count);
2547 1778 10 return 0;
2548 - }
2549 -
2550 451 2 static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size)
2551 - {
2552 - struct index_extension dest;
2553 - size_t total_size;
2554 -
2555 - /* buffer is not guaranteed to be aligned */
2556 451 2 memcpy(&dest, buffer, sizeof(struct index_extension));
2557 451 2 dest.extension_size = ntohl(dest.extension_size);
2558 -
2559 451 3 total_size = dest.extension_size + sizeof(struct index_extension);
2560 -
2561 451 3,4 if (dest.extension_size > total_size ||
2562 451 5 buffer_size < total_size ||
2563 451 5 buffer_size - total_size < INDEX_FOOTER_SIZE) {
2564 ##### 6 index_error_invalid("extension is truncated");
2565 ##### 7 return -1;
2566 - }
2567 -
2568 - /* optional extension */
2569 451 8,9 if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') {
2570 - /* tree cache */
2571 450 10,22 if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) {
2572 231 11,12 if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, &index->tree_pool) < 0)
2573 1 13 return -1;
2574 219 14 } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
2575 184 15,16 if (read_reuc(index, buffer + 8, dest.extension_size) < 0)
2576 ##### 17 return -1;
2577 35 18 } else if (memcmp(dest.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4) == 0) {
2578 1 19,20 if (read_conflict_names(index, buffer + 8, dest.extension_size) < 0)
2579 ##### 21 return -1;
2580 - }
2581 - /* else, unsupported extension. We cannot parse this, but we can skip
2582 - * it by returning `total_size */
2583 - } else {
2584 - /* we cannot handle non-ignorable extensions;
2585 - * in fact they aren't even defined in the standard */
2586 1 23 git_error_set(GIT_ERROR_INDEX, "unsupported mandatory extension: '%.4s'", dest.signature);
2587 1 24 return -1;
2588 - }
2589 -
2590 449 25 *read_len = total_size;
2591 -
2592 449 25 return 0;
2593 - }
2594 -
2595 1778 2 static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2596 - {
2597 1778 2 int error = 0;
2598 - unsigned int i;
2599 1778 2 struct index_header header = { 0 };
2600 - git_oid checksum_calculated, checksum_expected;
2601 1778 2 const char *last = NULL;
2602 1778 2 const char *empty = "";
2603 -
2604 - #define seek_forward(_increase) { \
2605 - if (_increase >= buffer_size) { \
2606 - error = index_error_invalid("ran out of data while parsing"); \
2607 - goto done; } \
2608 - buffer += _increase; \
2609 - buffer_size -= _increase;\
2610 - }
2611 -
2612 1778 2 if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
2613 ##### 3 return index_error_invalid("insufficient buffer space");
2614 -
2615 - /* Precalculate the SHA1 of the files's contents -- we'll match it to
2616 - * the provided SHA1 in the footer */
2617 1778 4 git_hash_buf(&checksum_calculated, buffer, buffer_size - INDEX_FOOTER_SIZE);
2618 -
2619 - /* Parse header */
2620 1778 5,6 if ((error = read_header(&header, buffer)) < 0)
2621 ##### 7 return error;
2622 -
2623 1778 8 index->version = header.version;
2624 1778 8 if (index->version >= INDEX_VERSION_NUMBER_COMP)
2625 3 9 last = empty;
2626 -
2627 1778 10,11 seek_forward(INDEX_HEADER_SIZE);
2628 -
2629 1778 12,13 assert(!index->entries.length);
2630 -
2631 1780 14,15 if ((error = index_map_resize(index->entries_map, header.entry_count, index->ignore_case)) < 0)
2632 ##### 16 return error;
2633 -
2634 - /* Parse all the entries */
2635 34511 17,33,36,37 for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
2636 32734 18 git_index_entry *entry = NULL;
2637 - size_t entry_size;
2638 -
2639 32734 18,19 if ((error = read_entry(&entry, &entry_size, index, buffer, buffer_size, last)) < 0) {
2640 ##### 20 error = index_error_invalid("invalid entry");
2641 ##### 34,35 goto done;
2642 - }
2643 -
2644 32727 21,22 if ((error = git_vector_insert(&index->entries, entry)) < 0) {
2645 ##### 23 index_entry_free(entry);
2646 ##### 24 goto done;
2647 - }
2648 -
2649 32731 25,26 if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) {
2650 ##### 27 index_entry_free(entry);
2651 ##### 28 goto done;
2652 - }
2653 32731 29 error = 0;
2654 -
2655 32731 29 if (index->version >= INDEX_VERSION_NUMBER_COMP)
2656 17 30 last = entry->path;
2657 -
2658 32731 31,32 seek_forward(entry_size);
2659 - }
2660 -
2661 1777 38 if (i != header.entry_count) {
2662 ##### 39 error = index_error_invalid("header entries changed while parsing");
2663 ##### 40 goto done;
2664 - }
2665 -
2666 - /* There's still space for some extensions! */
2667 2226 41,49 while (buffer_size > INDEX_FOOTER_SIZE) {
2668 - size_t extension_size;
2669 -
2670 451 42,43 if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) {
2671 2 44,48 goto done;
2672 - }
2673 -
2674 449 45-47 seek_forward(extension_size);
2675 - }
2676 -
2677 1775 50 if (buffer_size != INDEX_FOOTER_SIZE) {
2678 ##### 51 error = index_error_invalid(
2679 - "buffer size does not match index footer size");
2680 ##### 52 goto done;
2681 - }
2682 -
2683 - /* 160-bit SHA-1 over the content of the index file before this checksum. */
2684 1775 53 git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer);
2685 -
2686 1776 54,55 if (git_oid__cmp(&checksum_calculated, &checksum_expected) != 0) {
2687 ##### 56 error = index_error_invalid(
2688 - "calculated checksum does not match expected");
2689 ##### 57 goto done;
2690 - }
2691 -
2692 1776 58 git_oid_cpy(&index->checksum, &checksum_calculated);
2693 -
2694 - #undef seek_forward
2695 -
2696 - /* Entries are stored case-sensitively on disk, so re-sort now if
2697 - * in-memory index is supposed to be case-insensitive
2698 - */
2699 1776 59-61 git_vector_set_sorted(&index->entries, !index->ignore_case);
2700 1776 62 git_vector_sort(&index->entries);
2701 -
2702 1776 63 index->dirty = 0;
2703 - done:
2704 1778 64 return error;
2705 - }
2706 -
2707 1289 2 static bool is_index_extended(git_index *index)
2708 - {
2709 - size_t i, extended;
2710 - git_index_entry *entry;
2711 -
2712 1289 2 extended = 0;
2713 -
2714 23256 2,5-7 git_vector_foreach(&index->entries, i, entry) {
2715 21967 3 entry->flags &= ~GIT_INDEX_ENTRY_EXTENDED;
2716 21967 3 if (entry->flags_extended & GIT_INDEX_ENTRY_EXTENDED_FLAGS) {
2717 ##### 4 extended++;
2718 ##### 4 entry->flags |= GIT_INDEX_ENTRY_EXTENDED;
2719 - }
2720 - }
2721 -
2722 1289 8 return (extended > 0);
2723 - }
2724 -
2725 22629 2 static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char *last)
2726 - {
2727 22629 2 void *mem = NULL;
2728 - struct entry_short ondisk;
2729 - size_t path_len, disk_size;
2730 22629 2 int varint_len = 0;
2731 - char *path;
2732 22629 2 const char *path_start = entry->path;
2733 22629 2 size_t same_len = 0;
2734 -
2735 22629 2 path_len = ((struct entry_internal *)entry)->pathlen;
2736 -
2737 22629 2 if (last) {
2738 662 3 const char *last_c = last;
2739 -
2740 161617 3,7 while (*path_start == *last_c) {
2741 160955 4,5 if (!*path_start || !*last_c)
2742 - break;
2743 160955 6 ++path_start;
2744 160955 6 ++last_c;
2745 160955 6 ++same_len;
2746 - }
2747 662 8 path_len -= same_len;
2748 662 8 varint_len = git_encode_varint(NULL, 0, strlen(last) - same_len);
2749 - }
2750 -
2751 22629 9 disk_size = index_entry_size(path_len, varint_len, entry->flags);
2752 -
2753 22629 10,11 if (git_filebuf_reserve(file, &mem, disk_size) < 0)
2754 ##### 12 return -1;
2755 -
2756 22629 13 memset(mem, 0x0, disk_size);
2757 -
2758 - /**
2759 - * Yes, we have to truncate.
2760 - *
2761 - * The on-disk format for Index entries clearly defines
2762 - * the time and size fields to be 4 bytes each -- so even if
2763 - * we store these values with 8 bytes on-memory, they must
2764 - * be truncated to 4 bytes before writing to disk.
2765 - *
2766 - * In 2038 I will be either too dead or too rich to care about this
2767 - */
2768 22629 13 ondisk.ctime.seconds = htonl((uint32_t)entry->ctime.seconds);
2769 22629 14 ondisk.mtime.seconds = htonl((uint32_t)entry->mtime.seconds);
2770 22629 15 ondisk.ctime.nanoseconds = htonl(entry->ctime.nanoseconds);
2771 22629 16 ondisk.mtime.nanoseconds = htonl(entry->mtime.nanoseconds);
2772 22629 17 ondisk.dev = htonl(entry->dev);
2773 22629 18 ondisk.ino = htonl(entry->ino);
2774 22629 19 ondisk.mode = htonl(entry->mode);
2775 22629 20 ondisk.uid = htonl(entry->uid);
2776 22629 21 ondisk.gid = htonl(entry->gid);
2777 22629 22 ondisk.file_size = htonl((uint32_t)entry->file_size);
2778 -
2779 22629 23 git_oid_cpy(&ondisk.oid, &entry->id);
2780 -
2781 22629 24 ondisk.flags = htons(entry->flags);
2782 -
2783 22629 25 if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
2784 - struct entry_long ondisk_ext;
2785 ##### 26 memcpy(&ondisk_ext, &ondisk, sizeof(struct entry_short));
2786 ##### 26 ondisk_ext.flags_extended = htons(entry->flags_extended &
2787 - GIT_INDEX_ENTRY_EXTENDED_FLAGS);
2788 ##### 27 memcpy(mem, &ondisk_ext, offsetof(struct entry_long, path));
2789 ##### 27 path = ((struct entry_long*)mem)->path;
2790 ##### 27 disk_size -= offsetof(struct entry_long, path);
2791 - } else {
2792 22629 28 memcpy(mem, &ondisk, offsetof(struct entry_short, path));
2793 22629 28 path = ((struct entry_short*)mem)->path;
2794 22629 28 disk_size -= offsetof(struct entry_short, path);
2795 - }
2796 -
2797 22629 29 if (last) {
2798 662 30 varint_len = git_encode_varint((unsigned char *) path,
2799 662 30 disk_size, strlen(last) - same_len);
2800 662 31,32 assert(varint_len > 0);
2801 662 33 path += varint_len;
2802 662 33 disk_size -= varint_len;
2803 -
2804 - /*
2805 - * If using path compression, we are not allowed
2806 - * to have additional trailing NULs.
2807 - */
2808 662 33,34 assert(disk_size == path_len + 1);
2809 - } else {
2810 - /*
2811 - * If no path compression is used, we do have
2812 - * NULs as padding. As such, simply assert that
2813 - * we have enough space left to write the path.
2814 - */
2815 21967 35,36 assert(disk_size > path_len);
2816 - }
2817 -
2818 22629 37 memcpy(path, path_start, path_len + 1);
2819 -
2820 22629 37 return 0;
2821 - }
2822 -
2823 1291 2 static int write_entries(git_index *index, git_filebuf *file)
2824 - {
2825 1291 2 int error = 0;
2826 - size_t i;
2827 - git_vector case_sorted, *entries;
2828 - git_index_entry *entry;
2829 1291 2 const char *last = NULL;
2830 -
2831 - /* If index->entries is sorted case-insensitively, then we need
2832 - * to re-sort it case-sensitively before writing */
2833 1291 2 if (index->ignore_case) {
2834 3 3 git_vector_dup(&case_sorted, &index->entries, git_index_entry_cmp);
2835 3 4 git_vector_sort(&case_sorted);
2836 3 5 entries = &case_sorted;
2837 - } else {
2838 1288 6 entries = &index->entries;
2839 - }
2840 -
2841 1291 7 if (index->version >= INDEX_VERSION_NUMBER_COMP)
2842 2 8 last = "";
2843 -
2844 23920 9,15-17 git_vector_foreach(entries, i, entry) {
2845 22629 10,11 if ((error = write_disk_entry(file, entry, last)) < 0)
2846 ##### 12 break;
2847 22629 13 if (index->version >= INDEX_VERSION_NUMBER_COMP)
2848 662 14 last = entry->path;
2849 - }
2850 -
2851 1291 18 if (index->ignore_case)
2852 3 19 git_vector_free(&case_sorted);
2853 -
2854 1291 20 return error;
2855 - }
2856 -
2857 922 2 static int write_extension(git_filebuf *file, struct index_extension *header, git_buf *data)
2858 - {
2859 - struct index_extension ondisk;
2860 -
2861 922 2 memset(&ondisk, 0x0, sizeof(struct index_extension));
2862 922 2 memcpy(&ondisk, header, 4);
2863 922 2 ondisk.extension_size = htonl(header->extension_size);
2864 -
2865 922 3 git_filebuf_write(file, &ondisk, sizeof(struct index_extension));
2866 922 4 return git_filebuf_write(file, data->ptr, data->size);
2867 - }
2868 -
2869 111 2 static int create_name_extension_data(git_buf *name_buf, git_index_name_entry *conflict_name)
2870 - {
2871 111 2 int error = 0;
2872 -
2873 111 2 if (conflict_name->ancestor == NULL)
2874 ##### 3 error = git_buf_put(name_buf, "\0", 1);
2875 - else
2876 111 4 error = git_buf_put(name_buf, conflict_name->ancestor, strlen(conflict_name->ancestor) + 1);
2877 -
2878 111 5 if (error != 0)
2879 ##### 6 goto on_error;
2880 -
2881 111 7 if (conflict_name->ours == NULL)
2882 24 8 error = git_buf_put(name_buf, "\0", 1);
2883 - else
2884 87 9 error = git_buf_put(name_buf, conflict_name->ours, strlen(conflict_name->ours) + 1);
2885 -
2886 111 10 if (error != 0)
2887 ##### 11 goto on_error;
2888 -
2889 111 12 if (conflict_name->theirs == NULL)
2890 25 13 error = git_buf_put(name_buf, "\0", 1);
2891 - else
2892 86 14 error = git_buf_put(name_buf, conflict_name->theirs, strlen(conflict_name->theirs) + 1);
2893 -
2894 - on_error:
2895 111 15 return error;
2896 - }
2897 -
2898 21 2 static int write_name_extension(git_index *index, git_filebuf *file)
2899 - {
2900 21 2 git_buf name_buf = GIT_BUF_INIT;
2901 21 2 git_vector *out = &index->names;
2902 - git_index_name_entry *conflict_name;
2903 - struct index_extension extension;
2904 - size_t i;
2905 21 2 int error = 0;
2906 -
2907 132 2,6-8 git_vector_foreach(out, i, conflict_name) {
2908 111 3,4 if ((error = create_name_extension_data(&name_buf, conflict_name)) < 0)
2909 ##### 5 goto done;
2910 - }
2911 -
2912 21 9 memset(&extension, 0x0, sizeof(struct index_extension));
2913 21 9 memcpy(&extension.signature, INDEX_EXT_CONFLICT_NAME_SIG, 4);
2914 21 9 extension.extension_size = (uint32_t)name_buf.size;
2915 -
2916 21 9 error = write_extension(file, &extension, &name_buf);
2917 -
2918 21 10 git_buf_dispose(&name_buf);
2919 -
2920 - done:
2921 21 11 return error;
2922 - }
2923 -
2924 308 2 static int create_reuc_extension_data(git_buf *reuc_buf, git_index_reuc_entry *reuc)
2925 - {
2926 - int i;
2927 308 2 int error = 0;
2928 -
2929 308 2,3 if ((error = git_buf_put(reuc_buf, reuc->path, strlen(reuc->path) + 1)) < 0)
2930 ##### 4 return error;
2931 -
2932 1232 5,11,12 for (i = 0; i < 3; i++) {
2933 924 6-9 if ((error = git_buf_printf(reuc_buf, "%o", reuc->mode[i])) < 0 ||
2934 - (error = git_buf_put(reuc_buf, "\0", 1)) < 0)
2935 ##### 10 return error;
2936 - }
2937 -
2938 1232 13,18,19 for (i = 0; i < 3; i++) {
2939 924 14-16 if (reuc->mode[i] && (error = git_buf_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_RAWSZ)) < 0)
2940 ##### 17 return error;
2941 - }
2942 -
2943 308 20 return 0;
2944 - }
2945 -
2946 109 2 static int write_reuc_extension(git_index *index, git_filebuf *file)
2947 - {
2948 109 2 git_buf reuc_buf = GIT_BUF_INIT;
2949 109 2 git_vector *out = &index->reuc;
2950 - git_index_reuc_entry *reuc;
2951 - struct index_extension extension;
2952 - size_t i;
2953 109 2 int error = 0;
2954 -
2955 417 2,6-8 git_vector_foreach(out, i, reuc) {
2956 308 3,4 if ((error = create_reuc_extension_data(&reuc_buf, reuc)) < 0)
2957 ##### 5 goto done;
2958 - }
2959 -
2960 109 9 memset(&extension, 0x0, sizeof(struct index_extension));
2961 109 9 memcpy(&extension.signature, INDEX_EXT_UNMERGED_SIG, 4);
2962 109 9 extension.extension_size = (uint32_t)reuc_buf.size;
2963 -
2964 109 9 error = write_extension(file, &extension, &reuc_buf);
2965 -
2966 109 10 git_buf_dispose(&reuc_buf);
2967 -
2968 - done:
2969 109 11 return error;
2970 - }
2971 -
2972 792 2 static int write_tree_extension(git_index *index, git_filebuf *file)
2973 - {
2974 - struct index_extension extension;
2975 792 2 git_buf buf = GIT_BUF_INIT;
2976 - int error;
2977 -
2978 792 2 if (index->tree == NULL)
2979 ##### 3 return 0;
2980 -
2981 792 4,5 if ((error = git_tree_cache_write(&buf, index->tree)) < 0)
2982 ##### 6 return error;
2983 -
2984 792 7 memset(&extension, 0x0, sizeof(struct index_extension));
2985 792 7 memcpy(&extension.signature, INDEX_EXT_TREECACHE_SIG, 4);
2986 792 7 extension.extension_size = (uint32_t)buf.size;
2987 -
2988 792 7 error = write_extension(file, &extension, &buf);
2989 -
2990 792 8 git_buf_dispose(&buf);
2991 -
2992 792 9 return error;
2993 - }
2994 -
2995 1321 2 static void clear_uptodate(git_index *index)
2996 - {
2997 - git_index_entry *entry;
2998 - size_t i;
2999 -
3000 24110 2-5 git_vector_foreach(&index->entries, i, entry)
3001 22789 3 entry->flags_extended &= ~GIT_INDEX_ENTRY_UPTODATE;
3002 1321 6 }
3003 -
3004 1291 2 static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
3005 - {
3006 - git_oid hash_final;
3007 - struct index_header header;
3008 - bool is_extended;
3009 - uint32_t index_version_number;
3010 -
3011 1291 2-4 assert(index && file);
3012 -
3013 1291 5 if (index->version <= INDEX_VERSION_NUMBER_EXT) {
3014 1289 6 is_extended = is_index_extended(index);
3015 1289 7-10 index_version_number = is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER_LB;
3016 - } else {
3017 2 11 index_version_number = index->version;
3018 - }
3019 -
3020 1291 12 header.signature = htonl(INDEX_HEADER_SIG);
3021 1291 13 header.version = htonl(index_version_number);
3022 1291 14 header.entry_count = htonl((uint32_t)index->entries.length);
3023 -
3024 1291 15,16 if (git_filebuf_write(file, &header, sizeof(struct index_header)) < 0)
3025 ##### 17 return -1;
3026 -
3027 1291 18,19 if (write_entries(index, file) < 0)
3028 ##### 20 return -1;
3029 -
3030 - /* write the tree cache extension */
3031 1291 21-23 if (index->tree != NULL && write_tree_extension(index, file) < 0)
3032 ##### 24 return -1;
3033 -
3034 - /* write the rename conflict extension */
3035 1291 25-27 if (index->names.length > 0 && write_name_extension(index, file) < 0)
3036 ##### 28 return -1;
3037 -
3038 - /* write the reuc extension */
3039 1291 29-31 if (index->reuc.length > 0 && write_reuc_extension(index, file) < 0)
3040 ##### 32 return -1;
3041 -
3042 - /* get out the hash for all the contents we've appended to the file */
3043 1291 33 git_filebuf_hash(&hash_final, file);
3044 1291 34 git_oid_cpy(checksum, &hash_final);
3045 -
3046 - /* write it at the end of the file */
3047 1291 35,36 if (git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ) < 0)
3048 ##### 37 return -1;
3049 -
3050 - /* file entries are no longer up to date */
3051 1291 38 clear_uptodate(index);
3052 -
3053 1291 39 return 0;
3054 - }
3055 -
3056 775 2 int git_index_entry_stage(const git_index_entry *entry)
3057 - {
3058 775 2 return GIT_INDEX_ENTRY_STAGE(entry);
3059 - }
3060 -
3061 306761 2 int git_index_entry_is_conflict(const git_index_entry *entry)
3062 - {
3063 306761 2 return (GIT_INDEX_ENTRY_STAGE(entry) > 0);
3064 - }
3065 -
3066 - typedef struct read_tree_data {
3067 - git_index *index;
3068 - git_vector *old_entries;
3069 - git_vector *new_entries;
3070 - git_vector_cmp entry_cmp;
3071 - git_tree_cache *tree;
3072 - } read_tree_data;
3073 -
3074 1551 2 static int read_tree_cb(
3075 - const char *root, const git_tree_entry *tentry, void *payload)
3076 - {
3077 1551 2 read_tree_data *data = payload;
3078 1551 2 git_index_entry *entry = NULL, *old_entry;
3079 1551 2 git_buf path = GIT_BUF_INIT;
3080 - size_t pos;
3081 -
3082 1551 2,3 if (git_tree_entry__is_tree(tentry))
3083 68 4 return 0;
3084 -
3085 1483 5,6 if (git_buf_joinpath(&path, root, tentry->filename) < 0)
3086 ##### 7 return -1;
3087 -
3088 1483 8,9 if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, NULL, false) < 0)
3089 ##### 10 return -1;
3090 -
3091 1483 11 entry->mode = tentry->attr;
3092 1483 11,12 git_oid_cpy(&entry->id, git_tree_entry_id(tentry));
3093 -
3094 - /* look for corresponding old entry and copy data to new entry */
3095 1483 13,15 if (data->old_entries != NULL &&
3096 1483 14 !index_find_in_entries(
3097 1483 14,16,17 &pos, data->old_entries, data->entry_cmp, path.ptr, 0, 0) &&
3098 1262 16,18 (old_entry = git_vector_get(data->old_entries, pos)) != NULL &&
3099 1262 18,20 entry->mode == old_entry->mode &&
3100 1262 19 git_oid_equal(&entry->id, &old_entry->id))
3101 - {
3102 1217 21 index_entry_cpy(entry, old_entry);
3103 1217 22 entry->flags_extended = 0;
3104 - }
3105 -
3106 1483 23 index_entry_adjust_namemask(entry, path.size);
3107 1483 24 git_buf_dispose(&path);
3108 -
3109 1483 25,26 if (git_vector_insert(data->new_entries, entry) < 0) {
3110 ##### 27 index_entry_free(entry);
3111 ##### 28 return -1;
3112 - }
3113 -
3114 1483 29 return 0;
3115 - }
3116 -
3117 257 2 int git_index_read_tree(git_index *index, const git_tree *tree)
3118 - {
3119 257 2 int error = 0;
3120 257 2 git_vector entries = GIT_VECTOR_INIT;
3121 - git_idxmap *entries_map;
3122 - read_tree_data data;
3123 - size_t i;
3124 - git_index_entry *e;
3125 -
3126 257 2,3 if (git_idxmap_new(&entries_map) < 0)
3127 ##### 4 return -1;
3128 -
3129 257 5 git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */
3130 -
3131 257 6 data.index = index;
3132 257 6 data.old_entries = &index->entries;
3133 257 6 data.new_entries = &entries;
3134 257 6 data.entry_cmp = index->entries_search;
3135 -
3136 257 6 index->tree = NULL;
3137 257 6 git_pool_clear(&index->tree_pool);
3138 -
3139 257 7 git_vector_sort(&index->entries);
3140 -
3141 257 8,9 if ((error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data)) < 0)
3142 ##### 10 goto cleanup;
3143 -
3144 257 11,12 if ((error = index_map_resize(entries_map, entries.length, index->ignore_case)) < 0)
3145 ##### 13 goto cleanup;
3146 -
3147 1740 14,19-21 git_vector_foreach(&entries, i, e) {
3148 1483 15,16 if ((error = index_map_set(entries_map, e, index->ignore_case)) < 0) {
3149 ##### 17 git_error_set(GIT_ERROR_INDEX, "failed to insert entry into map");
3150 ##### 18 return error;
3151 - }
3152 - }
3153 -
3154 257 22 error = 0;
3155 -
3156 257 22 git_vector_sort(&entries);
3157 -
3158 257 23,24 if ((error = git_index_clear(index)) < 0) {
3159 - /* well, this isn't good */;
3160 - } else {
3161 257 25 git_vector_swap(&entries, &index->entries);
3162 257 26,27 entries_map = git__swap(index->entries_map, entries_map);
3163 - }
3164 -
3165 257 28 index->dirty = 1;
3166 -
3167 - cleanup:
3168 257 29 git_vector_free(&entries);
3169 257 30 git_idxmap_free(entries_map);
3170 257 31 if (error < 0)
3171 ##### 32 return error;
3172 -
3173 257 33 error = git_tree_cache_read_tree(&index->tree, tree, &index->tree_pool);
3174 -
3175 257 34 return error;
3176 - }
3177 -
3178 30 2 static int git_index_read_iterator(
3179 - git_index *index,
3180 - git_iterator *new_iterator,
3181 - size_t new_length_hint)
3182 - {
3183 30 2 git_vector new_entries = GIT_VECTOR_INIT,
3184 30 2 remove_entries = GIT_VECTOR_INIT;
3185 30 2 git_idxmap *new_entries_map = NULL;
3186 30 2 git_iterator *index_iterator = NULL;
3187 30 2 git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
3188 - const git_index_entry *old_entry, *new_entry;
3189 - git_index_entry *entry;
3190 - size_t i;
3191 - int error;
3192 -
3193 30 2,3 assert((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE));
3194 -
3195 30 4-7 if ((error = git_vector_init(&new_entries, new_length_hint, index->entries._cmp)) < 0 ||
3196 30 6,8,9 (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 ||
3197 - (error = git_idxmap_new(&new_entries_map)) < 0)
3198 - goto done;
3199 -
3200 30 10-12 if (new_length_hint && (error = index_map_resize(new_entries_map, new_length_hint,
3201 30 11 index->ignore_case)) < 0)
3202 ##### 13 goto done;
3203 -
3204 30 14 opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
3205 - GIT_ITERATOR_INCLUDE_CONFLICTS;
3206 -
3207 30 14-16 if ((error = git_iterator_for_index(&index_iterator,
3208 30 17,18 git_index_owner(index), index, &opts)) < 0 ||
3209 30 17,19 ((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
3210 30 20,21 error != GIT_ITEROVER) ||
3211 ##### 22 ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
3212 - error != GIT_ITEROVER))
3213 - goto done;
3214 -
3215 - while (true) {
3216 - git_index_entry
3217 212 23 *dup_entry = NULL,
3218 212 23 *add_entry = NULL,
3219 212 23 *remove_entry = NULL;
3220 - int diff;
3221 -
3222 212 23 error = 0;
3223 -
3224 212 23,24 if (old_entry && new_entry)
3225 161 25 diff = git_index_entry_cmp(old_entry, new_entry);
3226 51 26,27 else if (!old_entry && new_entry)
3227 12 28 diff = 1;
3228 39 29,30 else if (old_entry && !new_entry)
3229 9 31 diff = -1;
3230 - else
3231 - break;
3232 -
3233 182 32 if (diff < 0) {
3234 22 33 remove_entry = (git_index_entry *)old_entry;
3235 160 34 } else if (diff > 0) {
3236 46 35 dup_entry = (git_index_entry *)new_entry;
3237 - } else {
3238 - /* Path and stage are equal, if the OID is equal, keep it to
3239 - * keep the stat cache data.
3240 - */
3241 114 36-38 if (git_oid_equal(&old_entry->id, &new_entry->id) &&
3242 93 38 old_entry->mode == new_entry->mode) {
3243 93 39 add_entry = (git_index_entry *)old_entry;
3244 - } else {
3245 21 40 dup_entry = (git_index_entry *)new_entry;
3246 21 40 remove_entry = (git_index_entry *)old_entry;
3247 - }
3248 - }
3249 -
3250 182 41 if (dup_entry) {
3251 67 42,43 if ((error = index_entry_dup_nocache(&add_entry, index, dup_entry)) < 0)
3252 ##### 44,73 goto done;
3253 -
3254 67 45 index_entry_adjust_namemask(add_entry,
3255 67 45 ((struct entry_internal *)add_entry)->pathlen);
3256 - }
3257 -
3258 - /* invalidate this path in the tree cache if this is new (to
3259 - * invalidate the parent trees)
3260 - */
3261 182 46-48 if (dup_entry && !remove_entry && index->tree)
3262 42 49 git_tree_cache_invalidate_path(index->tree, dup_entry->path);
3263 -
3264 182 50 if (add_entry) {
3265 160 51,52 if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
3266 160 53 error = index_map_set(new_entries_map, add_entry,
3267 160 53 index->ignore_case);
3268 - }
3269 -
3270 182 54,55 if (remove_entry && error >= 0)
3271 43 56 error = git_vector_insert(&remove_entries, remove_entry);
3272 -
3273 182 57 if (error < 0) {
3274 ##### 58 git_error_set(GIT_ERROR_INDEX, "failed to insert entry");
3275 ##### 72 goto done;
3276 - }
3277 -
3278 182 59 if (diff <= 0) {
3279 136 60-62 if ((error = git_iterator_advance(&old_entry, index_iterator)) < 0 &&
3280 - error != GIT_ITEROVER)
3281 ##### 63 goto done;
3282 - }
3283 -
3284 182 64 if (diff >= 0) {
3285 160 65-67 if ((error = git_iterator_advance(&new_entry, new_iterator)) < 0 &&
3286 - error != GIT_ITEROVER)
3287 ##### 68 goto done;
3288 - }
3289 182 69 }
3290 -
3291 30 70,71,74,75 if ((error = git_index_name_clear(index)) < 0 ||
3292 - (error = git_index_reuc_clear(index)) < 0)
3293 - goto done;
3294 -
3295 30 76 git_vector_swap(&new_entries, &index->entries);
3296 30 77 new_entries_map = git__swap(index->entries_map, new_entries_map);
3297 -
3298 73 78,82-84 git_vector_foreach(&remove_entries, i, entry) {
3299 43 79 if (index->tree)
3300 43 80 git_tree_cache_invalidate_path(index->tree, entry->path);
3301 -
3302 43 81 index_entry_free(entry);
3303 - }
3304 -
3305 30 85 clear_uptodate(index);
3306 -
3307 30 86 index->dirty = 1;
3308 30 86 error = 0;
3309 -
3310 - done:
3311 30 87 git_idxmap_free(new_entries_map);
3312 30 88 git_vector_free(&new_entries);
3313 30 89 git_vector_free(&remove_entries);
3314 30 90 git_iterator_free(index_iterator);
3315 30 91 return error;
3316 - }
3317 -
3318 30 2 int git_index_read_index(
3319 - git_index *index,
3320 - const git_index *new_index)
3321 - {
3322 30 2 git_iterator *new_iterator = NULL;
3323 30 2 git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
3324 - int error;
3325 -
3326 30 2 opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
3327 - GIT_ITERATOR_INCLUDE_CONFLICTS;
3328 -
3329 30 2-4 if ((error = git_iterator_for_index(&new_iterator,
3330 30 5 git_index_owner(new_index), (git_index *)new_index, &opts)) < 0 ||
3331 30 5 (error = git_index_read_iterator(index, new_iterator,
3332 - new_index->entries.length)) < 0)
3333 - goto done;
3334 -
3335 - done:
3336 30 6 git_iterator_free(new_iterator);
3337 30 7 return error;
3338 - }
3339 -
3340 1733 2 git_repository *git_index_owner(const git_index *index)
3341 - {
3342 1733 2 return INDEX_OWNER(index);
3343 - }
3344 -
3345 - enum {
3346 - INDEX_ACTION_NONE = 0,
3347 - INDEX_ACTION_UPDATE = 1,
3348 - INDEX_ACTION_REMOVE = 2,
3349 - INDEX_ACTION_ADDALL = 3,
3350 - };
3351 -
3352 17 2 int git_index_add_all(
3353 - git_index *index,
3354 - const git_strarray *paths,
3355 - unsigned int flags,
3356 - git_index_matched_path_cb cb,
3357 - void *payload)
3358 - {
3359 - int error;
3360 - git_repository *repo;
3361 17 2 git_iterator *wditer = NULL;
3362 - git_pathspec ps;
3363 17 2 bool no_fnmatch = (flags & GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH) != 0;
3364 -
3365 17 2,3 assert(index);
3366 -
3367 17 4 repo = INDEX_OWNER(index);
3368 17 4,5 if ((error = git_repository__ensure_not_bare(repo, "index add all")) < 0)
3369 ##### 6 return error;
3370 -
3371 17 7,8 if ((error = git_pathspec__init(&ps, paths)) < 0)
3372 ##### 9 return error;
3373 -
3374 - /* optionally check that pathspec doesn't mention any ignored files */
3375 17 10,11 if ((flags & GIT_INDEX_ADD_CHECK_PATHSPEC) != 0 &&
3376 1 11-13 (flags & GIT_INDEX_ADD_FORCE) == 0 &&
3377 1 12 (error = git_ignore__check_pathspec_for_exact_ignores(
3378 - repo, &ps.pathspec, no_fnmatch)) < 0)
3379 1 14 goto cleanup;
3380 -
3381 16 15 error = index_apply_to_wd_diff(index, INDEX_ACTION_ADDALL, paths, flags, cb, payload);
3382 -
3383 16 16 if (error)
3384 2 17 git_error_set_after_callback(error);
3385 -
3386 - cleanup:
3387 17 18 git_iterator_free(wditer);
3388 17 19 git_pathspec__clear(&ps);
3389 -
3390 17 20 return error;
3391 - }
3392 -
3393 - struct foreach_diff_data {
3394 - git_index *index;
3395 - const git_pathspec *pathspec;
3396 - unsigned int flags;
3397 - git_index_matched_path_cb cb;
3398 - void *payload;
3399 - };
3400 -
3401 50 2 static int apply_each_file(const git_diff_delta *delta, float progress, void *payload)
3402 - {
3403 50 2 struct foreach_diff_data *data = payload;
3404 - const char *match, *path;
3405 50 2 int error = 0;
3406 -
3407 - GIT_UNUSED(progress);
3408 -
3409 50 2 path = delta->old_file.path;
3410 -
3411 - /* We only want those which match the pathspecs */
3412 50 2,2,3 if (!git_pathspec__match(
3413 50 2,2 &data->pathspec->pathspec, path, false, (bool)data->index->ignore_case,
3414 - &match, NULL))
3415 13 4 return 0;
3416 -
3417 37 5 if (data->cb)
3418 19 6 error = data->cb(path, match, data->payload);
3419 -
3420 37 7 if (error > 0) /* skip this entry */
3421 5 8 return 0;
3422 32 9 if (error < 0) /* actual error */
3423 4 10 return error;
3424 -
3425 - /* If the workdir item does not exist, remove it from the index. */
3426 28 11 if ((delta->new_file.flags & GIT_DIFF_FLAG_EXISTS) == 0)
3427 5 12 error = git_index_remove_bypath(data->index, path);
3428 - else
3429 23 13 error = git_index_add_bypath(data->index, delta->new_file.path);
3430 -
3431 28 14 return error;
3432 - }
3433 -
3434 25 2 static int index_apply_to_wd_diff(git_index *index, int action, const git_strarray *paths,
3435 - unsigned int flags,
3436 - git_index_matched_path_cb cb, void *payload)
3437 - {
3438 - int error;
3439 - git_diff *diff;
3440 - git_pathspec ps;
3441 - git_repository *repo;
3442 25 2 git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
3443 25 2 struct foreach_diff_data data = {
3444 - index,
3445 - NULL,
3446 - flags,
3447 - cb,
3448 - payload,
3449 - };
3450 -
3451 25 2,3 assert(index);
3452 25 4-6 assert(action == INDEX_ACTION_UPDATE || action == INDEX_ACTION_ADDALL);
3453 -
3454 25 7 repo = INDEX_OWNER(index);
3455 -
3456 25 7 if (!repo) {
3457 ##### 8 return create_index_error(-1,
3458 - "cannot run update; the index is not backed up by a repository.");
3459 - }
3460 -
3461 - /*
3462 - * We do the matching ourselves intead of passing the list to
3463 - * diff because we want to tell the callback which one
3464 - * matched, which we do not know if we ask diff to filter for us.
3465 - */
3466 25 9,10 if ((error = git_pathspec__init(&ps, paths)) < 0)
3467 ##### 11 return error;
3468 -
3469 25 12 opts.flags = GIT_DIFF_INCLUDE_TYPECHANGE;
3470 25 12 if (action == INDEX_ACTION_ADDALL) {
3471 16 13 opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED |
3472 - GIT_DIFF_RECURSE_UNTRACKED_DIRS;
3473 -
3474 16 13 if (flags == GIT_INDEX_ADD_FORCE)
3475 1 14 opts.flags |= GIT_DIFF_INCLUDE_IGNORED;
3476 - }
3477 -
3478 25 15,16 if ((error = git_diff_index_to_workdir(&diff, repo, index, &opts)) < 0)
3479 ##### 17 goto cleanup;
3480 -
3481 25 18 data.pathspec = &ps;
3482 25 18 error = git_diff_foreach(diff, apply_each_file, NULL, NULL, NULL, &data);
3483 25 19 git_diff_free(diff);
3484 -
3485 25 20 if (error) /* make sure error is set if callback stopped iteration */
3486 4 21 git_error_set_after_callback(error);
3487 -
3488 - cleanup:
3489 25 22 git_pathspec__clear(&ps);
3490 25 23 return error;
3491 - }
3492 -
3493 16 2 static int index_apply_to_all(
3494 - git_index *index,
3495 - int action,
3496 - const git_strarray *paths,
3497 - git_index_matched_path_cb cb,
3498 - void *payload)
3499 - {
3500 16 2 int error = 0;
3501 - size_t i;
3502 - git_pathspec ps;
3503 - const char *match;
3504 16 2 git_buf path = GIT_BUF_INIT;
3505 -
3506 16 2,3 assert(index);
3507 -
3508 16 4,5 if ((error = git_pathspec__init(&ps, paths)) < 0)
3509 ##### 6 return error;
3510 -
3511 16 7 git_vector_sort(&index->entries);
3512 -
3513 38 8,38-40 for (i = 0; !error && i < index->entries.length; ++i) {
3514 22 9 git_index_entry *entry = git_vector_get(&index->entries, i);
3515 -
3516 - /* check if path actually matches */
3517 22 10,11 if (!git_pathspec__match(
3518 22 10 &ps.pathspec, entry->path, false, (bool)index->ignore_case,
3519 - &match, NULL))
3520 2 12 continue;
3521 -
3522 - /* issue notification callback if requested */
3523 20 13-15 if (cb && (error = cb(entry->path, match, payload)) != 0) {
3524 1 16 if (error > 0) { /* return > 0 means skip this one */
3525 1 17 error = 0;
3526 1 17 continue;
3527 - }
3528 ##### 18 if (error < 0) /* return < 0 means abort */
3529 ##### 19 break;
3530 - }
3531 -
3532 - /* index manipulation may alter entry, so don't depend on it */
3533 19 20,21 if ((error = git_buf_sets(&path, entry->path)) < 0)
3534 ##### 22 break;
3535 -
3536 19 23 switch (action) {
3537 - case INDEX_ACTION_NONE:
3538 ##### 24 break;
3539 - case INDEX_ACTION_UPDATE:
3540 ##### 25 error = git_index_add_bypath(index, path.ptr);
3541 -
3542 ##### 26 if (error == GIT_ENOTFOUND) {
3543 ##### 27 git_error_clear();
3544 -
3545 ##### 28 error = git_index_remove_bypath(index, path.ptr);
3546 -
3547 ##### 29 if (!error) /* back up foreach if we removed this */
3548 ##### 30 i--;
3549 - }
3550 ##### 31 break;
3551 - case INDEX_ACTION_REMOVE:
3552 19 32,33 if (!(error = git_index_remove_bypath(index, path.ptr)))
3553 19 34 i--; /* back up foreach if we removed this */
3554 19 35 break;
3555 - default:
3556 ##### 36 git_error_set(GIT_ERROR_INVALID, "unknown index action %d", action);
3557 ##### 37 error = -1;
3558 ##### 37 break;
3559 - }
3560 - }
3561 -
3562 16 41 git_buf_dispose(&path);
3563 16 42 git_pathspec__clear(&ps);
3564 -
3565 16 43 return error;
3566 - }
3567 -
3568 16 2 int git_index_remove_all(
3569 - git_index *index,
3570 - const git_strarray *pathspec,
3571 - git_index_matched_path_cb cb,
3572 - void *payload)
3573 - {
3574 16 2 int error = index_apply_to_all(
3575 - index, INDEX_ACTION_REMOVE, pathspec, cb, payload);
3576 -
3577 16 3 if (error) /* make sure error is set if callback stopped iteration */
3578 ##### 4 git_error_set_after_callback(error);
3579 -
3580 16 5 return error;
3581 - }
3582 -
3583 9 2 int git_index_update_all(
3584 - git_index *index,
3585 - const git_strarray *pathspec,
3586 - git_index_matched_path_cb cb,
3587 - void *payload)
3588 - {
3589 9 2 int error = index_apply_to_wd_diff(index, INDEX_ACTION_UPDATE, pathspec, 0, cb, payload);
3590 9 3 if (error) /* make sure error is set if callback stopped iteration */
3591 2 4 git_error_set_after_callback(error);
3592 -
3593 9 5 return error;
3594 - }
3595 -
3596 6469 2 int git_index_snapshot_new(git_vector *snap, git_index *index)
3597 - {
3598 - int error;
3599 -
3600 6469 2 GIT_REFCOUNT_INC(index);
3601 -
3602 6469 3 git_atomic_inc(&index->readers);
3603 6469 4 git_vector_sort(&index->entries);
3604 -
3605 6469 5 error = git_vector_dup(snap, &index->entries, index->entries._cmp);
3606 -
3607 6469 6 if (error < 0)
3608 ##### 7 git_index_snapshot_release(snap, index);
3609 -
3610 6469 8 return error;
3611 - }
3612 -
3613 6469 2 void git_index_snapshot_release(git_vector *snap, git_index *index)
3614 - {
3615 6469 2 git_vector_free(snap);
3616 -
3617 6469 3 git_atomic_dec(&index->readers);
3618 -
3619 6469 4 git_index_free(index);
3620 6469 5 }
3621 -
3622 759 2 int git_index_snapshot_find(
3623 - size_t *out, git_vector *entries, git_vector_cmp entry_srch,
3624 - const char *path, size_t path_len, int stage)
3625 - {
3626 759 2 return index_find_in_entries(out, entries, entry_srch, path, path_len, stage);
3627 - }
3628 -
3629 1350 2 int git_indexwriter_init(
3630 - git_indexwriter *writer,
3631 - git_index *index)
3632 - {
3633 - int error;
3634 -
3635 1350 2 GIT_REFCOUNT_INC(index);
3636 -
3637 1350 3 writer->index = index;
3638 -
3639 1350 3 if (!index->index_file_path)
3640 ##### 4 return create_index_error(-1,
3641 - "failed to write index: The index is in-memory only");
3642 -
3643 1350 5,6 if ((error = git_filebuf_open(
3644 1350 5 &writer->file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) {
3645 -
3646 4 7 if (error == GIT_ELOCKED)
3647 4 8 git_error_set(GIT_ERROR_INDEX, "the index is locked; this might be due to a concurrent or crashed process");
3648 -
3649 4 9 return error;
3650 - }
3651 -
3652 1346 10 writer->should_write = 1;
3653 -
3654 1346 10 return 0;
3655 - }
3656 -
3657 193 2 int git_indexwriter_init_for_operation(
3658 - git_indexwriter *writer,
3659 - git_repository *repo,
3660 - unsigned int *checkout_strategy)
3661 - {
3662 - git_index *index;
3663 - int error;
3664 -
3665 193 2-5 if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
3666 193 4 (error = git_indexwriter_init(writer, index)) < 0)
3667 1 6 return error;
3668 -
3669 192 7 writer->should_write = (*checkout_strategy & GIT_CHECKOUT_DONT_WRITE_INDEX) == 0;
3670 192 7 *checkout_strategy |= GIT_CHECKOUT_DONT_WRITE_INDEX;
3671 -
3672 192 7 return 0;
3673 - }
3674 -
3675 1291 2 int git_indexwriter_commit(git_indexwriter *writer)
3676 - {
3677 - int error;
3678 1291 2 git_oid checksum = {{ 0 }};
3679 -
3680 1291 2 if (!writer->should_write)
3681 ##### 3 return 0;
3682 -
3683 1291 4 git_vector_sort(&writer->index->entries);
3684 1291 5 git_vector_sort(&writer->index->reuc);
3685 -
3686 1291 6,7 if ((error = write_index(&checksum, writer->index, &writer->file)) < 0) {
3687 ##### 8 git_indexwriter_cleanup(writer);
3688 ##### 9 return error;
3689 - }
3690 -
3691 1291 10,11 if ((error = git_filebuf_commit(&writer->file)) < 0)
3692 ##### 12 return error;
3693 -
3694 1291 13,14 if ((error = git_futils_filestamp_check(
3695 1291 13 &writer->index->stamp, writer->index->index_file_path)) < 0) {
3696 ##### 15 git_error_set(GIT_ERROR_OS, "could not read index timestamp");
3697 ##### 16 return -1;
3698 - }
3699 -
3700 1291 17 writer->index->dirty = 0;
3701 1291 17 writer->index->on_disk = 1;
3702 1291 17 git_oid_cpy(&writer->index->checksum, &checksum);
3703 -
3704 1291 18 git_index_free(writer->index);
3705 1291 19 writer->index = NULL;
3706 -
3707 1291 19 return 0;
3708 - }
3709 -
3710 1354 2 void git_indexwriter_cleanup(git_indexwriter *writer)
3711 - {
3712 1354 2 git_filebuf_cleanup(&writer->file);
3713 -
3714 1354 3 git_index_free(writer->index);
3715 1354 4 writer->index = NULL;
3716 1354 4 }
3717 -
3718 - /* Deprecated functions */
3719 -
3720 - #ifndef GIT_DEPRECATE_HARD
3721 ##### 2 int git_index_add_frombuffer(
3722 - git_index *index, const git_index_entry *source_entry,
3723 - const void *buffer, size_t len)
3724 - {
3725 ##### 2 return git_index_add_from_buffer(index, source_entry, buffer, len);
3726 - }
3727 - #endif