2 * Copyright (C) the libgit2 contributors. All rights reserved.
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.
11 #include "repository.h"
14 #include "tree-cache.h"
23 #include "git2/blob.h"
24 #include "git2/config.h"
25 #include "git2/sys/index.h"
27 #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
28 #define short_entry_size(len) entry_size(struct entry_short, len)
29 #define long_entry_size(len) entry_size(struct entry_long, len)
31 #define minimal_entry_size (offsetof(struct entry_short, path))
33 static const size_t INDEX_FOOTER_SIZE
= GIT_OID_RAWSZ
;
34 static const size_t INDEX_HEADER_SIZE
= 12;
36 static const unsigned int INDEX_VERSION_NUMBER
= 2;
37 static const unsigned int INDEX_VERSION_NUMBER_EXT
= 3;
39 static const unsigned int INDEX_HEADER_SIG
= 0x44495243;
40 static const char INDEX_EXT_TREECACHE_SIG
[] = {'T', 'R', 'E', 'E'};
41 static const char INDEX_EXT_UNMERGED_SIG
[] = {'R', 'E', 'U', 'C'};
42 static const char INDEX_EXT_CONFLICT_NAME_SIG
[] = {'N', 'A', 'M', 'E'};
44 #define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
52 struct index_extension
{
54 uint32_t extension_size
;
63 struct entry_time ctime
;
64 struct entry_time mtime
;
73 char path
[1]; /* arbitrary length */
77 struct entry_time ctime
;
78 struct entry_time mtime
;
87 uint16_t flags_extended
;
88 char path
[1]; /* arbitrary length */
91 struct entry_srch_key
{
96 /* local declarations */
97 static size_t read_extension(git_index
*index
, const char *buffer
, size_t buffer_size
);
98 static size_t read_entry(git_index_entry
*dest
, const void *buffer
, size_t buffer_size
);
99 static int read_header(struct index_header
*dest
, const void *buffer
);
101 static int parse_index(git_index
*index
, const char *buffer
, size_t buffer_size
);
102 static bool is_index_extended(git_index
*index
);
103 static int write_index(git_index
*index
, git_filebuf
*file
);
105 static void index_entry_free(git_index_entry
*entry
);
106 static void index_entry_reuc_free(git_index_reuc_entry
*reuc
);
108 static int index_srch(const void *key
, const void *array_member
)
110 const struct entry_srch_key
*srch_key
= key
;
111 const git_index_entry
*entry
= array_member
;
114 ret
= strcmp(srch_key
->path
, entry
->path
);
116 if (ret
== 0 && srch_key
->stage
!= GIT_INDEX_STAGE_ANY
)
117 ret
= srch_key
->stage
- GIT_IDXENTRY_STAGE(entry
);
122 static int index_isrch(const void *key
, const void *array_member
)
124 const struct entry_srch_key
*srch_key
= key
;
125 const git_index_entry
*entry
= array_member
;
128 ret
= strcasecmp(srch_key
->path
, entry
->path
);
130 if (ret
== 0 && srch_key
->stage
!= GIT_INDEX_STAGE_ANY
)
131 ret
= srch_key
->stage
- GIT_IDXENTRY_STAGE(entry
);
136 static int index_cmp_path(const void *a
, const void *b
)
138 return strcmp((const char *)a
, (const char *)b
);
141 static int index_icmp_path(const void *a
, const void *b
)
143 return strcasecmp((const char *)a
, (const char *)b
);
146 static int index_srch_path(const void *path
, const void *array_member
)
148 const git_index_entry
*entry
= array_member
;
150 return strcmp((const char *)path
, entry
->path
);
153 static int index_isrch_path(const void *path
, const void *array_member
)
155 const git_index_entry
*entry
= array_member
;
157 return strcasecmp((const char *)path
, entry
->path
);
160 static int index_cmp(const void *a
, const void *b
)
163 const git_index_entry
*entry_a
= a
;
164 const git_index_entry
*entry_b
= b
;
166 diff
= strcmp(entry_a
->path
, entry_b
->path
);
169 diff
= (GIT_IDXENTRY_STAGE(entry_a
) - GIT_IDXENTRY_STAGE(entry_b
));
174 static int index_icmp(const void *a
, const void *b
)
177 const git_index_entry
*entry_a
= a
;
178 const git_index_entry
*entry_b
= b
;
180 diff
= strcasecmp(entry_a
->path
, entry_b
->path
);
183 diff
= (GIT_IDXENTRY_STAGE(entry_a
) - GIT_IDXENTRY_STAGE(entry_b
));
188 static int conflict_name_cmp(const void *a
, const void *b
)
190 const git_index_name_entry
*name_a
= a
;
191 const git_index_name_entry
*name_b
= b
;
193 if (name_a
->ancestor
&& !name_b
->ancestor
)
196 if (!name_a
->ancestor
&& name_b
->ancestor
)
199 if (name_a
->ancestor
)
200 return strcmp(name_a
->ancestor
, name_b
->ancestor
);
202 if (!name_a
->ours
|| !name_b
->ours
)
205 return strcmp(name_a
->ours
, name_b
->ours
);
209 * TODO: enable this when resolving case insensitive conflicts
212 static int conflict_name_icmp(const void *a
, const void *b
)
214 const git_index_name_entry
*name_a
= a
;
215 const git_index_name_entry
*name_b
= b
;
217 if (name_a
->ancestor
&& !name_b
->ancestor
)
220 if (!name_a
->ancestor
&& name_b
->ancestor
)
223 if (name_a
->ancestor
)
224 return strcasecmp(name_a
->ancestor
, name_b
->ancestor
);
226 if (!name_a
->ours
|| !name_b
->ours
)
229 return strcasecmp(name_a
->ours
, name_b
->ours
);
233 static int reuc_srch(const void *key
, const void *array_member
)
235 const git_index_reuc_entry
*reuc
= array_member
;
237 return strcmp(key
, reuc
->path
);
240 static int reuc_isrch(const void *key
, const void *array_member
)
242 const git_index_reuc_entry
*reuc
= array_member
;
244 return strcasecmp(key
, reuc
->path
);
247 static int reuc_cmp(const void *a
, const void *b
)
249 const git_index_reuc_entry
*info_a
= a
;
250 const git_index_reuc_entry
*info_b
= b
;
252 return strcmp(info_a
->path
, info_b
->path
);
255 static int reuc_icmp(const void *a
, const void *b
)
257 const git_index_reuc_entry
*info_a
= a
;
258 const git_index_reuc_entry
*info_b
= b
;
260 return strcasecmp(info_a
->path
, info_b
->path
);
263 static void index_entry_reuc_free(git_index_reuc_entry
*reuc
)
267 git__free(reuc
->path
);
271 static void index_entry_free(git_index_entry
*entry
)
275 git__free(entry
->path
);
279 static unsigned int index_create_mode(unsigned int mode
)
284 if (S_ISDIR(mode
) || (mode
& S_IFMT
) == (S_IFLNK
| S_IFDIR
))
285 return (S_IFLNK
| S_IFDIR
);
287 return S_IFREG
| GIT_PERMS_CANONICAL(mode
);
290 static unsigned int index_merge_mode(
291 git_index
*index
, git_index_entry
*existing
, unsigned int mode
)
293 if (index
->no_symlinks
&& S_ISREG(mode
) &&
294 existing
&& S_ISLNK(existing
->mode
))
295 return existing
->mode
;
297 if (index
->distrust_filemode
&& S_ISREG(mode
))
298 return (existing
&& S_ISREG(existing
->mode
)) ?
299 existing
->mode
: index_create_mode(0666);
301 return index_create_mode(mode
);
304 void git_index__set_ignore_case(git_index
*index
, bool ignore_case
)
306 index
->ignore_case
= ignore_case
;
308 index
->entries_cmp_path
= ignore_case
? index_icmp_path
: index_cmp_path
;
309 index
->entries_search
= ignore_case
? index_isrch
: index_srch
;
310 index
->entries_search_path
= ignore_case
? index_isrch_path
: index_srch_path
;
312 git_vector_set_cmp(&index
->entries
, ignore_case
? index_icmp
: index_cmp
);
313 git_vector_sort(&index
->entries
);
315 index
->reuc_search
= ignore_case
? reuc_isrch
: reuc_srch
;
317 git_vector_set_cmp(&index
->reuc
, ignore_case
? reuc_icmp
: reuc_cmp
);
318 git_vector_sort(&index
->reuc
);
321 int git_index_open(git_index
**index_out
, const char *index_path
)
327 index
= git__calloc(1, sizeof(git_index
));
328 GITERR_CHECK_ALLOC(index
);
330 if (index_path
!= NULL
) {
331 index
->index_file_path
= git__strdup(index_path
);
332 GITERR_CHECK_ALLOC(index
->index_file_path
);
334 /* Check if index file is stored on disk already */
335 if (git_path_exists(index
->index_file_path
) == true)
339 if (git_vector_init(&index
->entries
, 32, index_cmp
) < 0 ||
340 git_vector_init(&index
->names
, 32, conflict_name_cmp
) < 0 ||
341 git_vector_init(&index
->reuc
, 32, reuc_cmp
) < 0)
344 index
->entries_cmp_path
= index_cmp_path
;
345 index
->entries_search
= index_srch
;
346 index
->entries_search_path
= index_srch_path
;
347 index
->reuc_search
= reuc_srch
;
350 GIT_REFCOUNT_INC(index
);
352 return (index_path
!= NULL
) ? git_index_read(index
) : 0;
355 int git_index_new(git_index
**out
)
357 return git_index_open(out
, NULL
);
360 static void index_free(git_index
*index
)
362 git_index_clear(index
);
363 git_vector_free(&index
->entries
);
364 git_vector_free(&index
->names
);
365 git_vector_free(&index
->reuc
);
367 git__free(index
->index_file_path
);
369 git__memzero(index
, sizeof(*index
));
373 void git_index_free(git_index
*index
)
378 GIT_REFCOUNT_DEC(index
, index_free
);
381 static void index_entries_free(git_vector
*entries
)
385 for (i
= 0; i
< entries
->length
; ++i
)
386 index_entry_free(git__swap(entries
->contents
[i
], NULL
));
388 git_vector_clear(entries
);
391 void git_index_clear(git_index
*index
)
395 index_entries_free(&index
->entries
);
396 git_index_reuc_clear(index
);
397 git_index_name_clear(index
);
399 git_futils_filestamp_set(&index
->stamp
, NULL
);
401 git_tree_cache_free(index
->tree
);
405 static int create_index_error(int error
, const char *msg
)
407 giterr_set(GITERR_INDEX
, msg
);
411 int git_index_set_caps(git_index
*index
, unsigned int caps
)
413 unsigned int old_ignore_case
;
417 old_ignore_case
= index
->ignore_case
;
419 if (caps
== GIT_INDEXCAP_FROM_OWNER
) {
420 git_repository
*repo
= INDEX_OWNER(index
);
424 return create_index_error(
425 -1, "Cannot access repository to set index caps");
427 if (!git_repository__cvar(&val
, repo
, GIT_CVAR_IGNORECASE
))
428 index
->ignore_case
= (val
!= 0);
429 if (!git_repository__cvar(&val
, repo
, GIT_CVAR_FILEMODE
))
430 index
->distrust_filemode
= (val
== 0);
431 if (!git_repository__cvar(&val
, repo
, GIT_CVAR_SYMLINKS
))
432 index
->no_symlinks
= (val
== 0);
435 index
->ignore_case
= ((caps
& GIT_INDEXCAP_IGNORE_CASE
) != 0);
436 index
->distrust_filemode
= ((caps
& GIT_INDEXCAP_NO_FILEMODE
) != 0);
437 index
->no_symlinks
= ((caps
& GIT_INDEXCAP_NO_SYMLINKS
) != 0);
440 if (old_ignore_case
!= index
->ignore_case
) {
441 git_index__set_ignore_case(index
, (bool)index
->ignore_case
);
447 unsigned int git_index_caps(const git_index
*index
)
449 return ((index
->ignore_case
? GIT_INDEXCAP_IGNORE_CASE
: 0) |
450 (index
->distrust_filemode
? GIT_INDEXCAP_NO_FILEMODE
: 0) |
451 (index
->no_symlinks
? GIT_INDEXCAP_NO_SYMLINKS
: 0));
454 int git_index_read(git_index
*index
)
456 int error
= 0, updated
;
457 git_buf buffer
= GIT_BUF_INIT
;
458 git_futils_filestamp stamp
= {0};
460 if (!index
->index_file_path
)
461 return create_index_error(-1,
462 "Failed to read index: The index is in-memory only");
464 index
->on_disk
= git_path_exists(index
->index_file_path
);
466 if (!index
->on_disk
) {
467 git_index_clear(index
);
471 updated
= git_futils_filestamp_check(&stamp
, index
->index_file_path
);
475 error
= git_futils_readbuffer(&buffer
, index
->index_file_path
);
479 git_index_clear(index
);
480 error
= parse_index(index
, buffer
.ptr
, buffer
.size
);
483 git_futils_filestamp_set(&index
->stamp
, &stamp
);
485 git_buf_free(&buffer
);
489 int git_index_write(git_index
*index
)
491 git_filebuf file
= GIT_FILEBUF_INIT
;
494 if (!index
->index_file_path
)
495 return create_index_error(-1,
496 "Failed to read index: The index is in-memory only");
498 git_vector_sort(&index
->entries
);
499 git_vector_sort(&index
->reuc
);
501 if ((error
= git_filebuf_open(
502 &file
, index
->index_file_path
, GIT_FILEBUF_HASH_CONTENTS
)) < 0) {
503 if (error
== GIT_ELOCKED
)
504 giterr_set(GITERR_INDEX
, "The index is locked. This might be due to a concurrrent or crashed process");
509 if ((error
= write_index(index
, &file
)) < 0) {
510 git_filebuf_cleanup(&file
);
514 if ((error
= git_filebuf_commit(&file
, GIT_INDEX_FILE_MODE
)) < 0)
517 error
= git_futils_filestamp_check(&index
->stamp
, index
->index_file_path
);
525 const char * git_index_path(git_index
*index
)
528 return index
->index_file_path
;
531 int git_index_write_tree(git_oid
*oid
, git_index
*index
)
533 git_repository
*repo
;
535 assert(oid
&& index
);
537 repo
= INDEX_OWNER(index
);
540 return create_index_error(-1, "Failed to write tree. "
541 "The index file is not backed up by an existing repository");
543 return git_tree__write_index(oid
, index
, repo
);
546 int git_index_write_tree_to(git_oid
*oid
, git_index
*index
, git_repository
*repo
)
548 assert(oid
&& index
&& repo
);
549 return git_tree__write_index(oid
, index
, repo
);
552 size_t git_index_entrycount(const git_index
*index
)
555 return index
->entries
.length
;
558 const git_index_entry
*git_index_get_byindex(
559 git_index
*index
, size_t n
)
562 git_vector_sort(&index
->entries
);
563 return git_vector_get(&index
->entries
, n
);
566 const git_index_entry
*git_index_get_bypath(
567 git_index
*index
, const char *path
, int stage
)
573 git_vector_sort(&index
->entries
);
575 if (git_index__find(&pos
, index
, path
, stage
) < 0) {
576 giterr_set(GITERR_INDEX
, "Index does not contain %s", path
);
580 return git_index_get_byindex(index
, pos
);
583 void git_index_entry__init_from_stat(
584 git_index_entry
*entry
, struct stat
*st
, bool trust_mode
)
586 entry
->ctime
.seconds
= (git_time_t
)st
->st_ctime
;
587 entry
->mtime
.seconds
= (git_time_t
)st
->st_mtime
;
588 /* entry->mtime.nanoseconds = st->st_mtimensec; */
589 /* entry->ctime.nanoseconds = st->st_ctimensec; */
590 entry
->dev
= st
->st_rdev
;
591 entry
->ino
= st
->st_ino
;
592 entry
->mode
= (!trust_mode
&& S_ISREG(st
->st_mode
)) ?
593 index_create_mode(0666) : index_create_mode(st
->st_mode
);
594 entry
->uid
= st
->st_uid
;
595 entry
->gid
= st
->st_gid
;
596 entry
->file_size
= st
->st_size
;
599 int git_index_entry__cmp(const void *a
, const void *b
)
601 const git_index_entry
*entry_a
= a
;
602 const git_index_entry
*entry_b
= b
;
604 return strcmp(entry_a
->path
, entry_b
->path
);
607 int git_index_entry__cmp_icase(const void *a
, const void *b
)
609 const git_index_entry
*entry_a
= a
;
610 const git_index_entry
*entry_b
= b
;
612 return strcasecmp(entry_a
->path
, entry_b
->path
);
615 static int index_entry_init(
616 git_index_entry
**entry_out
, git_index
*index
, const char *rel_path
)
619 git_index_entry
*entry
= NULL
;
623 if (INDEX_OWNER(index
) == NULL
)
624 return create_index_error(-1,
625 "Could not initialize index entry. "
626 "Index is not backed up by an existing repository.");
628 /* write the blob to disk and get the oid and stat info */
629 error
= git_blob__create_from_paths(
630 &oid
, &st
, INDEX_OWNER(index
), NULL
, rel_path
, 0, true);
634 entry
= git__calloc(1, sizeof(git_index_entry
));
635 GITERR_CHECK_ALLOC(entry
);
637 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
640 entry
->path
= git__strdup(rel_path
);
641 GITERR_CHECK_ALLOC(entry
->path
);
647 static int index_entry_reuc_init(git_index_reuc_entry
**reuc_out
,
649 int ancestor_mode
, const git_oid
*ancestor_oid
,
650 int our_mode
, const git_oid
*our_oid
,
651 int their_mode
, const git_oid
*their_oid
)
653 git_index_reuc_entry
*reuc
= NULL
;
655 assert(reuc_out
&& path
);
659 reuc
= git__calloc(1, sizeof(git_index_reuc_entry
));
660 GITERR_CHECK_ALLOC(reuc
);
662 reuc
->path
= git__strdup(path
);
663 if (reuc
->path
== NULL
)
666 if ((reuc
->mode
[0] = ancestor_mode
) > 0)
667 git_oid_cpy(&reuc
->oid
[0], ancestor_oid
);
669 if ((reuc
->mode
[1] = our_mode
) > 0)
670 git_oid_cpy(&reuc
->oid
[1], our_oid
);
672 if ((reuc
->mode
[2] = their_mode
) > 0)
673 git_oid_cpy(&reuc
->oid
[2], their_oid
);
679 static git_index_entry
*index_entry_dup(const git_index_entry
*source_entry
)
681 git_index_entry
*entry
;
683 entry
= git__malloc(sizeof(git_index_entry
));
687 memcpy(entry
, source_entry
, sizeof(git_index_entry
));
689 /* duplicate the path string so we own it */
690 entry
->path
= git__strdup(entry
->path
);
697 static int index_insert(git_index
*index
, git_index_entry
*entry
, int replace
)
699 size_t path_length
, position
;
700 git_index_entry
**existing
= NULL
;
702 assert(index
&& entry
&& entry
->path
!= NULL
);
704 /* make sure that the path length flag is correct */
705 path_length
= strlen(entry
->path
);
707 entry
->flags
&= ~GIT_IDXENTRY_NAMEMASK
;
709 if (path_length
< GIT_IDXENTRY_NAMEMASK
)
710 entry
->flags
|= path_length
& GIT_IDXENTRY_NAMEMASK
;
712 entry
->flags
|= GIT_IDXENTRY_NAMEMASK
;
714 /* look if an entry with this path already exists */
715 if (!git_index__find(
716 &position
, index
, entry
->path
, GIT_IDXENTRY_STAGE(entry
))) {
717 existing
= (git_index_entry
**)&index
->entries
.contents
[position
];
719 /* update filemode to existing values if stat is not trusted */
720 entry
->mode
= index_merge_mode(index
, *existing
, entry
->mode
);
723 /* if replacing is not requested or no existing entry exists, just
724 * insert entry at the end; the index is no longer sorted
726 if (!replace
|| !existing
)
727 return git_vector_insert(&index
->entries
, entry
);
729 /* exists, replace it (preserving name from existing entry) */
730 git__free(entry
->path
);
731 entry
->path
= (*existing
)->path
;
732 git__free(*existing
);
738 static int index_conflict_to_reuc(git_index
*index
, const char *path
)
740 const git_index_entry
*conflict_entries
[3];
741 int ancestor_mode
, our_mode
, their_mode
;
742 git_oid
const *ancestor_oid
, *our_oid
, *their_oid
;
745 if ((ret
= git_index_conflict_get(&conflict_entries
[0],
746 &conflict_entries
[1], &conflict_entries
[2], index
, path
)) < 0)
749 ancestor_mode
= conflict_entries
[0] == NULL
? 0 : conflict_entries
[0]->mode
;
750 our_mode
= conflict_entries
[1] == NULL
? 0 : conflict_entries
[1]->mode
;
751 their_mode
= conflict_entries
[2] == NULL
? 0 : conflict_entries
[2]->mode
;
753 ancestor_oid
= conflict_entries
[0] == NULL
? NULL
: &conflict_entries
[0]->oid
;
754 our_oid
= conflict_entries
[1] == NULL
? NULL
: &conflict_entries
[1]->oid
;
755 their_oid
= conflict_entries
[2] == NULL
? NULL
: &conflict_entries
[2]->oid
;
757 if ((ret
= git_index_reuc_add(index
, path
, ancestor_mode
, ancestor_oid
,
758 our_mode
, our_oid
, their_mode
, their_oid
)) >= 0)
759 ret
= git_index_conflict_remove(index
, path
);
764 int git_index_add_bypath(git_index
*index
, const char *path
)
766 git_index_entry
*entry
= NULL
;
769 assert(index
&& path
);
771 if ((ret
= index_entry_init(&entry
, index
, path
)) < 0 ||
772 (ret
= index_insert(index
, entry
, 1)) < 0)
775 /* Adding implies conflict was resolved, move conflict entries to REUC */
776 if ((ret
= index_conflict_to_reuc(index
, path
)) < 0 && ret
!= GIT_ENOTFOUND
)
779 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
783 index_entry_free(entry
);
787 int git_index_remove_bypath(git_index
*index
, const char *path
)
791 assert(index
&& path
);
793 if (((ret
= git_index_remove(index
, path
, 0)) < 0 &&
794 ret
!= GIT_ENOTFOUND
) ||
795 ((ret
= index_conflict_to_reuc(index
, path
)) < 0 &&
796 ret
!= GIT_ENOTFOUND
))
802 int git_index_add(git_index
*index
, const git_index_entry
*source_entry
)
804 git_index_entry
*entry
= NULL
;
807 entry
= index_entry_dup(source_entry
);
811 if ((ret
= index_insert(index
, entry
, 1)) < 0) {
812 index_entry_free(entry
);
816 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
820 int git_index_remove(git_index
*index
, const char *path
, int stage
)
824 git_index_entry
*entry
;
826 git_vector_sort(&index
->entries
);
828 if (git_index__find(&position
, index
, path
, stage
) < 0) {
829 giterr_set(GITERR_INDEX
, "Index does not contain %s at stage %d",
831 return GIT_ENOTFOUND
;
834 entry
= git_vector_get(&index
->entries
, position
);
836 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
838 error
= git_vector_remove(&index
->entries
, position
);
841 index_entry_free(entry
);
846 int git_index_remove_directory(git_index
*index
, const char *dir
, int stage
)
848 git_buf pfx
= GIT_BUF_INIT
;
851 git_index_entry
*entry
;
853 if (git_buf_sets(&pfx
, dir
) < 0 || git_path_to_dir(&pfx
) < 0)
856 git_vector_sort(&index
->entries
);
858 pos
= git_index__prefix_position(index
, pfx
.ptr
);
861 entry
= git_vector_get(&index
->entries
, pos
);
862 if (!entry
|| git__prefixcmp(entry
->path
, pfx
.ptr
) != 0)
865 if (GIT_IDXENTRY_STAGE(entry
) != stage
) {
870 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
872 if ((error
= git_vector_remove(&index
->entries
, pos
)) < 0)
874 index_entry_free(entry
);
876 /* removed entry at 'pos' so we don't need to increment it */
885 size_t *at_pos
, git_index
*index
, const char *path
, int stage
)
887 struct entry_srch_key srch_key
;
891 srch_key
.path
= path
;
892 srch_key
.stage
= stage
;
894 return git_vector_bsearch2(
895 at_pos
, &index
->entries
, index
->entries_search
, &srch_key
);
898 int git_index_find(size_t *at_pos
, git_index
*index
, const char *path
)
902 assert(index
&& path
);
904 if (git_vector_bsearch2(&pos
, &index
->entries
, index
->entries_search_path
, path
) < 0) {
905 giterr_set(GITERR_INDEX
, "Index does not contain %s", path
);
906 return GIT_ENOTFOUND
;
909 /* Since our binary search only looked at path, we may be in the
910 * middle of a list of stages.
913 const git_index_entry
*prev
= git_vector_get(&index
->entries
, pos
-1);
915 if (index
->entries_cmp_path(prev
->path
, path
) != 0)
927 size_t git_index__prefix_position(git_index
*index
, const char *path
)
929 struct entry_srch_key srch_key
;
932 srch_key
.path
= path
;
935 git_vector_sort(&index
->entries
);
937 &pos
, &index
->entries
, index
->entries_search
, &srch_key
);
942 int git_index_conflict_add(git_index
*index
,
943 const git_index_entry
*ancestor_entry
,
944 const git_index_entry
*our_entry
,
945 const git_index_entry
*their_entry
)
947 git_index_entry
*entries
[3] = { 0 };
953 if ((ancestor_entry
!= NULL
&& (entries
[0] = index_entry_dup(ancestor_entry
)) == NULL
) ||
954 (our_entry
!= NULL
&& (entries
[1] = index_entry_dup(our_entry
)) == NULL
) ||
955 (their_entry
!= NULL
&& (entries
[2] = index_entry_dup(their_entry
)) == NULL
))
958 for (i
= 0; i
< 3; i
++) {
959 if (entries
[i
] == NULL
)
962 /* Make sure stage is correct */
963 entries
[i
]->flags
= (entries
[i
]->flags
& ~GIT_IDXENTRY_STAGEMASK
) |
964 ((i
+1) << GIT_IDXENTRY_STAGESHIFT
);
966 if ((ret
= index_insert(index
, entries
[i
], 1)) < 0)
973 for (i
= 0; i
< 3; i
++) {
974 if (entries
[i
] != NULL
)
975 index_entry_free(entries
[i
]);
981 static int index_conflict__get_byindex(
982 const git_index_entry
**ancestor_out
,
983 const git_index_entry
**our_out
,
984 const git_index_entry
**their_out
,
988 const git_index_entry
*conflict_entry
;
989 const char *path
= NULL
;
993 assert(ancestor_out
&& our_out
&& their_out
&& index
);
995 *ancestor_out
= NULL
;
999 for (count
= git_index_entrycount(index
); n
< count
; ++n
) {
1000 conflict_entry
= git_vector_get(&index
->entries
, n
);
1002 if (path
&& index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1005 stage
= GIT_IDXENTRY_STAGE(conflict_entry
);
1006 path
= conflict_entry
->path
;
1010 *their_out
= conflict_entry
;
1014 *our_out
= conflict_entry
;
1018 *ancestor_out
= conflict_entry
;
1029 int git_index_conflict_get(
1030 const git_index_entry
**ancestor_out
,
1031 const git_index_entry
**our_out
,
1032 const git_index_entry
**their_out
,
1039 assert(ancestor_out
&& our_out
&& their_out
&& index
&& path
);
1041 *ancestor_out
= NULL
;
1045 if (git_index_find(&pos
, index
, path
) < 0)
1046 return GIT_ENOTFOUND
;
1048 if ((len
= index_conflict__get_byindex(
1049 ancestor_out
, our_out
, their_out
, index
, pos
)) < 0)
1052 return GIT_ENOTFOUND
;
1057 int git_index_conflict_remove(git_index
*index
, const char *path
)
1060 git_index_entry
*conflict_entry
;
1063 assert(index
&& path
);
1065 if (git_index_find(&pos
, index
, path
) < 0)
1066 return GIT_ENOTFOUND
;
1068 posmax
= git_index_entrycount(index
);
1070 while (pos
< posmax
) {
1071 conflict_entry
= git_vector_get(&index
->entries
, pos
);
1073 if (index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1076 if (GIT_IDXENTRY_STAGE(conflict_entry
) == 0) {
1081 if ((error
= git_vector_remove(&index
->entries
, pos
)) < 0)
1084 index_entry_free(conflict_entry
);
1091 static int index_conflicts_match(const git_vector
*v
, size_t idx
)
1093 git_index_entry
*entry
= git_vector_get(v
, idx
);
1095 if (GIT_IDXENTRY_STAGE(entry
) > 0) {
1096 index_entry_free(entry
);
1103 void git_index_conflict_cleanup(git_index
*index
)
1106 git_vector_remove_matching(&index
->entries
, index_conflicts_match
);
1109 int git_index_has_conflicts(const git_index
*index
)
1112 git_index_entry
*entry
;
1116 git_vector_foreach(&index
->entries
, i
, entry
) {
1117 if (GIT_IDXENTRY_STAGE(entry
) > 0)
1124 int git_index_conflict_iterator_new(
1125 git_index_conflict_iterator
**iterator_out
,
1128 git_index_conflict_iterator
*it
= NULL
;
1130 assert(iterator_out
&& index
);
1132 it
= git__calloc(1, sizeof(git_index_conflict_iterator
));
1133 GITERR_CHECK_ALLOC(it
);
1141 int git_index_conflict_next(
1142 const git_index_entry
**ancestor_out
,
1143 const git_index_entry
**our_out
,
1144 const git_index_entry
**their_out
,
1145 git_index_conflict_iterator
*iterator
)
1147 const git_index_entry
*entry
;
1150 assert(ancestor_out
&& our_out
&& their_out
&& iterator
);
1152 *ancestor_out
= NULL
;
1156 while (iterator
->cur
< iterator
->index
->entries
.length
) {
1157 entry
= git_index_get_byindex(iterator
->index
, iterator
->cur
);
1159 if (git_index_entry_stage(entry
) > 0) {
1160 if ((len
= index_conflict__get_byindex(
1165 iterator
->cur
)) < 0)
1168 iterator
->cur
+= len
;
1175 return GIT_ITEROVER
;
1178 void git_index_conflict_iterator_free(git_index_conflict_iterator
*iterator
)
1180 if (iterator
== NULL
)
1183 git__free(iterator
);
1186 unsigned int git_index_name_entrycount(git_index
*index
)
1189 return (unsigned int)index
->names
.length
;
1192 const git_index_name_entry
*git_index_name_get_byindex(
1193 git_index
*index
, size_t n
)
1197 git_vector_sort(&index
->names
);
1198 return git_vector_get(&index
->names
, n
);
1201 int git_index_name_add(git_index
*index
,
1202 const char *ancestor
, const char *ours
, const char *theirs
)
1204 git_index_name_entry
*conflict_name
;
1206 assert ((ancestor
&& ours
) || (ancestor
&& theirs
) || (ours
&& theirs
));
1208 conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
1209 GITERR_CHECK_ALLOC(conflict_name
);
1212 conflict_name
->ancestor
= git__strdup(ancestor
);
1213 GITERR_CHECK_ALLOC(conflict_name
->ancestor
);
1217 conflict_name
->ours
= git__strdup(ours
);
1218 GITERR_CHECK_ALLOC(conflict_name
->ours
);
1222 conflict_name
->theirs
= git__strdup(theirs
);
1223 GITERR_CHECK_ALLOC(conflict_name
->theirs
);
1226 return git_vector_insert(&index
->names
, conflict_name
);
1229 void git_index_name_clear(git_index
*index
)
1232 git_index_name_entry
*conflict_name
;
1236 git_vector_foreach(&index
->names
, i
, conflict_name
) {
1237 if (conflict_name
->ancestor
)
1238 git__free(conflict_name
->ancestor
);
1240 if (conflict_name
->ours
)
1241 git__free(conflict_name
->ours
);
1243 if (conflict_name
->theirs
)
1244 git__free(conflict_name
->theirs
);
1246 git__free(conflict_name
);
1249 git_vector_clear(&index
->names
);
1252 unsigned int git_index_reuc_entrycount(git_index
*index
)
1255 return (unsigned int)index
->reuc
.length
;
1258 static int index_reuc_insert(
1260 git_index_reuc_entry
*reuc
,
1263 git_index_reuc_entry
**existing
= NULL
;
1266 assert(index
&& reuc
&& reuc
->path
!= NULL
);
1268 if (!git_index_reuc_find(&position
, index
, reuc
->path
))
1269 existing
= (git_index_reuc_entry
**)&index
->reuc
.contents
[position
];
1271 if (!replace
|| !existing
)
1272 return git_vector_insert(&index
->reuc
, reuc
);
1274 /* exists, replace it */
1275 git__free((*existing
)->path
);
1276 git__free(*existing
);
1282 int git_index_reuc_add(git_index
*index
, const char *path
,
1283 int ancestor_mode
, const git_oid
*ancestor_oid
,
1284 int our_mode
, const git_oid
*our_oid
,
1285 int their_mode
, const git_oid
*their_oid
)
1287 git_index_reuc_entry
*reuc
= NULL
;
1290 assert(index
&& path
);
1292 if ((error
= index_entry_reuc_init(&reuc
, path
, ancestor_mode
, ancestor_oid
, our_mode
, our_oid
, their_mode
, their_oid
)) < 0 ||
1293 (error
= index_reuc_insert(index
, reuc
, 1)) < 0)
1295 index_entry_reuc_free(reuc
);
1302 int git_index_reuc_find(size_t *at_pos
, git_index
*index
, const char *path
)
1304 return git_vector_bsearch2(at_pos
, &index
->reuc
, index
->reuc_search
, path
);
1307 const git_index_reuc_entry
*git_index_reuc_get_bypath(
1308 git_index
*index
, const char *path
)
1311 assert(index
&& path
);
1313 if (!index
->reuc
.length
)
1316 git_vector_sort(&index
->reuc
);
1318 if (git_index_reuc_find(&pos
, index
, path
) < 0)
1321 return git_vector_get(&index
->reuc
, pos
);
1324 const git_index_reuc_entry
*git_index_reuc_get_byindex(
1325 git_index
*index
, size_t n
)
1329 git_vector_sort(&index
->reuc
);
1330 return git_vector_get(&index
->reuc
, n
);
1333 int git_index_reuc_remove(git_index
*index
, size_t position
)
1336 git_index_reuc_entry
*reuc
;
1338 git_vector_sort(&index
->reuc
);
1340 reuc
= git_vector_get(&index
->reuc
, position
);
1341 error
= git_vector_remove(&index
->reuc
, position
);
1344 index_entry_reuc_free(reuc
);
1349 void git_index_reuc_clear(git_index
*index
)
1355 for (i
= 0; i
< index
->reuc
.length
; ++i
)
1356 index_entry_reuc_free(git__swap(index
->reuc
.contents
[i
], NULL
));
1358 git_vector_clear(&index
->reuc
);
1361 static int index_error_invalid(const char *message
)
1363 giterr_set(GITERR_INDEX
, "Invalid data in index - %s", message
);
1367 static int read_reuc(git_index
*index
, const char *buffer
, size_t size
)
1373 /* If called multiple times, the vector might already be initialized */
1374 if (index
->reuc
._alloc_size
== 0 &&
1375 git_vector_init(&index
->reuc
, 16, reuc_cmp
) < 0)
1379 git_index_reuc_entry
*lost
;
1381 len
= p_strnlen(buffer
, size
) + 1;
1383 return index_error_invalid("reading reuc entries");
1385 lost
= git__calloc(1, sizeof(git_index_reuc_entry
));
1386 GITERR_CHECK_ALLOC(lost
);
1388 /* read NUL-terminated pathname for entry */
1389 lost
->path
= git__strdup(buffer
);
1390 GITERR_CHECK_ALLOC(lost
->path
);
1395 /* read 3 ASCII octal numbers for stage entries */
1396 for (i
= 0; i
< 3; i
++) {
1399 if (git__strtol32(&tmp
, buffer
, &endptr
, 8) < 0 ||
1400 !endptr
|| endptr
== buffer
|| *endptr
||
1401 (unsigned)tmp
> UINT_MAX
) {
1402 index_entry_reuc_free(lost
);
1403 return index_error_invalid("reading reuc entry stage");
1406 lost
->mode
[i
] = tmp
;
1408 len
= (endptr
+ 1) - buffer
;
1410 index_entry_reuc_free(lost
);
1411 return index_error_invalid("reading reuc entry stage");
1418 /* read up to 3 OIDs for stage entries */
1419 for (i
= 0; i
< 3; i
++) {
1423 index_entry_reuc_free(lost
);
1424 return index_error_invalid("reading reuc entry oid");
1427 git_oid_fromraw(&lost
->oid
[i
], (const unsigned char *) buffer
);
1432 /* entry was read successfully - insert into reuc vector */
1433 if (git_vector_insert(&index
->reuc
, lost
) < 0)
1437 /* entries are guaranteed to be sorted on-disk */
1438 index
->reuc
.sorted
= 1;
1444 static int read_conflict_names(git_index
*index
, const char *buffer
, size_t size
)
1448 /* This gets called multiple times, the vector might already be initialized */
1449 if (index
->names
._alloc_size
== 0 &&
1450 git_vector_init(&index
->names
, 16, conflict_name_cmp
) < 0)
1453 #define read_conflict_name(ptr) \
1454 len = p_strnlen(buffer, size) + 1; \
1456 return index_error_invalid("reading conflict name entries"); \
1461 ptr = git__malloc(len); \
1462 GITERR_CHECK_ALLOC(ptr); \
1463 memcpy(ptr, buffer, len); \
1470 git_index_name_entry
*conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
1471 GITERR_CHECK_ALLOC(conflict_name
);
1473 read_conflict_name(conflict_name
->ancestor
);
1474 read_conflict_name(conflict_name
->ours
);
1475 read_conflict_name(conflict_name
->theirs
);
1477 if (git_vector_insert(&index
->names
, conflict_name
) < 0)
1481 #undef read_conflict_name
1483 /* entries are guaranteed to be sorted on-disk */
1484 index
->names
.sorted
= 1;
1489 static size_t read_entry(git_index_entry
*dest
, const void *buffer
, size_t buffer_size
)
1491 size_t path_length
, entry_size
;
1493 const char *path_ptr
;
1494 const struct entry_short
*source
= buffer
;
1496 if (INDEX_FOOTER_SIZE
+ minimal_entry_size
> buffer_size
)
1499 memset(dest
, 0x0, sizeof(git_index_entry
));
1501 dest
->ctime
.seconds
= (git_time_t
)ntohl(source
->ctime
.seconds
);
1502 dest
->ctime
.nanoseconds
= ntohl(source
->ctime
.nanoseconds
);
1503 dest
->mtime
.seconds
= (git_time_t
)ntohl(source
->mtime
.seconds
);
1504 dest
->mtime
.nanoseconds
= ntohl(source
->mtime
.nanoseconds
);
1505 dest
->dev
= ntohl(source
->dev
);
1506 dest
->ino
= ntohl(source
->ino
);
1507 dest
->mode
= ntohl(source
->mode
);
1508 dest
->uid
= ntohl(source
->uid
);
1509 dest
->gid
= ntohl(source
->gid
);
1510 dest
->file_size
= ntohl(source
->file_size
);
1511 git_oid_cpy(&dest
->oid
, &source
->oid
);
1512 dest
->flags
= ntohs(source
->flags
);
1514 if (dest
->flags
& GIT_IDXENTRY_EXTENDED
) {
1515 const struct entry_long
*source_l
= (const struct entry_long
*)source
;
1516 path_ptr
= source_l
->path
;
1518 flags_raw
= ntohs(source_l
->flags_extended
);
1519 memcpy(&dest
->flags_extended
, &flags_raw
, 2);
1521 path_ptr
= source
->path
;
1523 path_length
= dest
->flags
& GIT_IDXENTRY_NAMEMASK
;
1525 /* if this is a very long string, we must find its
1526 * real length without overflowing */
1527 if (path_length
== 0xFFF) {
1528 const char *path_end
;
1530 path_end
= memchr(path_ptr
, '\0', buffer_size
);
1531 if (path_end
== NULL
)
1534 path_length
= path_end
- path_ptr
;
1537 if (dest
->flags
& GIT_IDXENTRY_EXTENDED
)
1538 entry_size
= long_entry_size(path_length
);
1540 entry_size
= short_entry_size(path_length
);
1542 if (INDEX_FOOTER_SIZE
+ entry_size
> buffer_size
)
1545 dest
->path
= git__strdup(path_ptr
);
1551 static int read_header(struct index_header
*dest
, const void *buffer
)
1553 const struct index_header
*source
= buffer
;
1555 dest
->signature
= ntohl(source
->signature
);
1556 if (dest
->signature
!= INDEX_HEADER_SIG
)
1557 return index_error_invalid("incorrect header signature");
1559 dest
->version
= ntohl(source
->version
);
1560 if (dest
->version
!= INDEX_VERSION_NUMBER_EXT
&&
1561 dest
->version
!= INDEX_VERSION_NUMBER
)
1562 return index_error_invalid("incorrect header version");
1564 dest
->entry_count
= ntohl(source
->entry_count
);
1568 static size_t read_extension(git_index
*index
, const char *buffer
, size_t buffer_size
)
1570 const struct index_extension
*source
;
1571 struct index_extension dest
;
1574 source
= (const struct index_extension
*)(buffer
);
1576 memcpy(dest
.signature
, source
->signature
, 4);
1577 dest
.extension_size
= ntohl(source
->extension_size
);
1579 total_size
= dest
.extension_size
+ sizeof(struct index_extension
);
1581 if (dest
.extension_size
> total_size
||
1582 buffer_size
< total_size
||
1583 buffer_size
- total_size
< INDEX_FOOTER_SIZE
)
1586 /* optional extension */
1587 if (dest
.signature
[0] >= 'A' && dest
.signature
[0] <= 'Z') {
1589 if (memcmp(dest
.signature
, INDEX_EXT_TREECACHE_SIG
, 4) == 0) {
1590 if (git_tree_cache_read(&index
->tree
, buffer
+ 8, dest
.extension_size
) < 0)
1592 } else if (memcmp(dest
.signature
, INDEX_EXT_UNMERGED_SIG
, 4) == 0) {
1593 if (read_reuc(index
, buffer
+ 8, dest
.extension_size
) < 0)
1595 } else if (memcmp(dest
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4) == 0) {
1596 if (read_conflict_names(index
, buffer
+ 8, dest
.extension_size
) < 0)
1599 /* else, unsupported extension. We cannot parse this, but we can skip
1600 * it by returning `total_size */
1602 /* we cannot handle non-ignorable extensions;
1603 * in fact they aren't even defined in the standard */
1610 static int parse_index(git_index
*index
, const char *buffer
, size_t buffer_size
)
1613 struct index_header header
= { 0 };
1614 git_oid checksum_calculated
, checksum_expected
;
1616 #define seek_forward(_increase) { \
1617 if (_increase >= buffer_size) \
1618 return index_error_invalid("ran out of data while parsing"); \
1619 buffer += _increase; \
1620 buffer_size -= _increase;\
1623 if (buffer_size
< INDEX_HEADER_SIZE
+ INDEX_FOOTER_SIZE
)
1624 return index_error_invalid("insufficient buffer space");
1626 /* Precalculate the SHA1 of the files's contents -- we'll match it to
1627 * the provided SHA1 in the footer */
1628 git_hash_buf(&checksum_calculated
, buffer
, buffer_size
- INDEX_FOOTER_SIZE
);
1631 if (read_header(&header
, buffer
) < 0)
1634 seek_forward(INDEX_HEADER_SIZE
);
1636 git_vector_clear(&index
->entries
);
1638 /* Parse all the entries */
1639 for (i
= 0; i
< header
.entry_count
&& buffer_size
> INDEX_FOOTER_SIZE
; ++i
) {
1641 git_index_entry
*entry
;
1643 entry
= git__malloc(sizeof(git_index_entry
));
1644 GITERR_CHECK_ALLOC(entry
);
1646 entry_size
= read_entry(entry
, buffer
, buffer_size
);
1648 /* 0 bytes read means an object corruption */
1649 if (entry_size
== 0)
1650 return index_error_invalid("invalid entry");
1652 if (git_vector_insert(&index
->entries
, entry
) < 0)
1655 seek_forward(entry_size
);
1658 if (i
!= header
.entry_count
)
1659 return index_error_invalid("header entries changed while parsing");
1661 /* There's still space for some extensions! */
1662 while (buffer_size
> INDEX_FOOTER_SIZE
) {
1663 size_t extension_size
;
1665 extension_size
= read_extension(index
, buffer
, buffer_size
);
1667 /* see if we have read any bytes from the extension */
1668 if (extension_size
== 0)
1669 return index_error_invalid("extension is truncated");
1671 seek_forward(extension_size
);
1674 if (buffer_size
!= INDEX_FOOTER_SIZE
)
1675 return index_error_invalid("buffer size does not match index footer size");
1677 /* 160-bit SHA-1 over the content of the index file before this checksum. */
1678 git_oid_fromraw(&checksum_expected
, (const unsigned char *)buffer
);
1680 if (git_oid__cmp(&checksum_calculated
, &checksum_expected
) != 0)
1681 return index_error_invalid("calculated checksum does not match expected");
1685 /* Entries are stored case-sensitively on disk. */
1686 index
->entries
.sorted
= !index
->ignore_case
;
1687 git_vector_sort(&index
->entries
);
1692 static bool is_index_extended(git_index
*index
)
1695 git_index_entry
*entry
;
1699 git_vector_foreach(&index
->entries
, i
, entry
) {
1700 entry
->flags
&= ~GIT_IDXENTRY_EXTENDED
;
1701 if (entry
->flags_extended
& GIT_IDXENTRY_EXTENDED_FLAGS
) {
1703 entry
->flags
|= GIT_IDXENTRY_EXTENDED
;
1707 return (extended
> 0);
1710 static int write_disk_entry(git_filebuf
*file
, git_index_entry
*entry
)
1713 struct entry_short
*ondisk
;
1714 size_t path_len
, disk_size
;
1717 path_len
= strlen(entry
->path
);
1719 if (entry
->flags
& GIT_IDXENTRY_EXTENDED
)
1720 disk_size
= long_entry_size(path_len
);
1722 disk_size
= short_entry_size(path_len
);
1724 if (git_filebuf_reserve(file
, &mem
, disk_size
) < 0)
1727 ondisk
= (struct entry_short
*)mem
;
1729 memset(ondisk
, 0x0, disk_size
);
1732 * Yes, we have to truncate.
1734 * The on-disk format for Index entries clearly defines
1735 * the time and size fields to be 4 bytes each -- so even if
1736 * we store these values with 8 bytes on-memory, they must
1737 * be truncated to 4 bytes before writing to disk.
1739 * In 2038 I will be either too dead or too rich to care about this
1741 ondisk
->ctime
.seconds
= htonl((uint32_t)entry
->ctime
.seconds
);
1742 ondisk
->mtime
.seconds
= htonl((uint32_t)entry
->mtime
.seconds
);
1743 ondisk
->ctime
.nanoseconds
= htonl(entry
->ctime
.nanoseconds
);
1744 ondisk
->mtime
.nanoseconds
= htonl(entry
->mtime
.nanoseconds
);
1745 ondisk
->dev
= htonl(entry
->dev
);
1746 ondisk
->ino
= htonl(entry
->ino
);
1747 ondisk
->mode
= htonl(entry
->mode
);
1748 ondisk
->uid
= htonl(entry
->uid
);
1749 ondisk
->gid
= htonl(entry
->gid
);
1750 ondisk
->file_size
= htonl((uint32_t)entry
->file_size
);
1752 git_oid_cpy(&ondisk
->oid
, &entry
->oid
);
1754 ondisk
->flags
= htons(entry
->flags
);
1756 if (entry
->flags
& GIT_IDXENTRY_EXTENDED
) {
1757 struct entry_long
*ondisk_ext
;
1758 ondisk_ext
= (struct entry_long
*)ondisk
;
1759 ondisk_ext
->flags_extended
= htons(entry
->flags_extended
);
1760 path
= ondisk_ext
->path
;
1763 path
= ondisk
->path
;
1765 memcpy(path
, entry
->path
, path_len
);
1770 static int write_entries(git_index
*index
, git_filebuf
*file
)
1774 git_vector case_sorted
;
1775 git_index_entry
*entry
;
1776 git_vector
*out
= &index
->entries
;
1778 /* If index->entries is sorted case-insensitively, then we need
1779 * to re-sort it case-sensitively before writing */
1780 if (index
->ignore_case
) {
1781 git_vector_dup(&case_sorted
, &index
->entries
, index_cmp
);
1782 git_vector_sort(&case_sorted
);
1786 git_vector_foreach(out
, i
, entry
)
1787 if ((error
= write_disk_entry(file
, entry
)) < 0)
1790 if (index
->ignore_case
)
1791 git_vector_free(&case_sorted
);
1796 static int write_extension(git_filebuf
*file
, struct index_extension
*header
, git_buf
*data
)
1798 struct index_extension ondisk
;
1801 memset(&ondisk
, 0x0, sizeof(struct index_extension
));
1802 memcpy(&ondisk
, header
, 4);
1803 ondisk
.extension_size
= htonl(header
->extension_size
);
1805 if ((error
= git_filebuf_write(file
, &ondisk
, sizeof(struct index_extension
))) == 0)
1806 error
= git_filebuf_write(file
, data
->ptr
, data
->size
);
1811 static int create_name_extension_data(git_buf
*name_buf
, git_index_name_entry
*conflict_name
)
1815 if (conflict_name
->ancestor
== NULL
)
1816 error
= git_buf_put(name_buf
, "\0", 1);
1818 error
= git_buf_put(name_buf
, conflict_name
->ancestor
, strlen(conflict_name
->ancestor
) + 1);
1823 if (conflict_name
->ours
== NULL
)
1824 error
= git_buf_put(name_buf
, "\0", 1);
1826 error
= git_buf_put(name_buf
, conflict_name
->ours
, strlen(conflict_name
->ours
) + 1);
1831 if (conflict_name
->theirs
== NULL
)
1832 error
= git_buf_put(name_buf
, "\0", 1);
1834 error
= git_buf_put(name_buf
, conflict_name
->theirs
, strlen(conflict_name
->theirs
) + 1);
1840 static int write_name_extension(git_index
*index
, git_filebuf
*file
)
1842 git_buf name_buf
= GIT_BUF_INIT
;
1843 git_vector
*out
= &index
->names
;
1844 git_index_name_entry
*conflict_name
;
1845 struct index_extension extension
;
1849 git_vector_foreach(out
, i
, conflict_name
) {
1850 if ((error
= create_name_extension_data(&name_buf
, conflict_name
)) < 0)
1854 memset(&extension
, 0x0, sizeof(struct index_extension
));
1855 memcpy(&extension
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4);
1856 extension
.extension_size
= (uint32_t)name_buf
.size
;
1858 error
= write_extension(file
, &extension
, &name_buf
);
1860 git_buf_free(&name_buf
);
1866 static int create_reuc_extension_data(git_buf
*reuc_buf
, git_index_reuc_entry
*reuc
)
1871 if ((error
= git_buf_put(reuc_buf
, reuc
->path
, strlen(reuc
->path
) + 1)) < 0)
1874 for (i
= 0; i
< 3; i
++) {
1875 if ((error
= git_buf_printf(reuc_buf
, "%o", reuc
->mode
[i
])) < 0 ||
1876 (error
= git_buf_put(reuc_buf
, "\0", 1)) < 0)
1880 for (i
= 0; i
< 3; i
++) {
1881 if (reuc
->mode
[i
] && (error
= git_buf_put(reuc_buf
, (char *)&reuc
->oid
[i
].id
, GIT_OID_RAWSZ
)) < 0)
1888 static int write_reuc_extension(git_index
*index
, git_filebuf
*file
)
1890 git_buf reuc_buf
= GIT_BUF_INIT
;
1891 git_vector
*out
= &index
->reuc
;
1892 git_index_reuc_entry
*reuc
;
1893 struct index_extension extension
;
1897 git_vector_foreach(out
, i
, reuc
) {
1898 if ((error
= create_reuc_extension_data(&reuc_buf
, reuc
)) < 0)
1902 memset(&extension
, 0x0, sizeof(struct index_extension
));
1903 memcpy(&extension
.signature
, INDEX_EXT_UNMERGED_SIG
, 4);
1904 extension
.extension_size
= (uint32_t)reuc_buf
.size
;
1906 error
= write_extension(file
, &extension
, &reuc_buf
);
1908 git_buf_free(&reuc_buf
);
1914 static int write_index(git_index
*index
, git_filebuf
*file
)
1917 struct index_header header
;
1920 assert(index
&& file
);
1922 is_extended
= is_index_extended(index
);
1924 header
.signature
= htonl(INDEX_HEADER_SIG
);
1925 header
.version
= htonl(is_extended
? INDEX_VERSION_NUMBER_EXT
: INDEX_VERSION_NUMBER
);
1926 header
.entry_count
= htonl((uint32_t)index
->entries
.length
);
1928 if (git_filebuf_write(file
, &header
, sizeof(struct index_header
)) < 0)
1931 if (write_entries(index
, file
) < 0)
1934 /* TODO: write tree cache extension */
1936 /* write the rename conflict extension */
1937 if (index
->names
.length
> 0 && write_name_extension(index
, file
) < 0)
1940 /* write the reuc extension */
1941 if (index
->reuc
.length
> 0 && write_reuc_extension(index
, file
) < 0)
1944 /* get out the hash for all the contents we've appended to the file */
1945 git_filebuf_hash(&hash_final
, file
);
1947 /* write it at the end of the file */
1948 return git_filebuf_write(file
, hash_final
.id
, GIT_OID_RAWSZ
);
1951 int git_index_entry_stage(const git_index_entry
*entry
)
1953 return GIT_IDXENTRY_STAGE(entry
);
1956 typedef struct read_tree_data
{
1957 git_vector
*old_entries
;
1958 git_vector
*new_entries
;
1959 git_vector_cmp entries_search
;
1962 static int read_tree_cb(
1963 const char *root
, const git_tree_entry
*tentry
, void *payload
)
1965 read_tree_data
*data
= payload
;
1966 git_index_entry
*entry
= NULL
, *old_entry
;
1967 git_buf path
= GIT_BUF_INIT
;
1969 if (git_tree_entry__is_tree(tentry
))
1972 if (git_buf_joinpath(&path
, root
, tentry
->filename
) < 0)
1975 entry
= git__calloc(1, sizeof(git_index_entry
));
1976 GITERR_CHECK_ALLOC(entry
);
1978 entry
->mode
= tentry
->attr
;
1979 entry
->oid
= tentry
->oid
;
1981 /* look for corresponding old entry and copy data to new entry */
1982 if (data
->old_entries
) {
1984 struct entry_srch_key skey
;
1986 skey
.path
= path
.ptr
;
1989 if (!git_vector_bsearch2(
1990 &pos
, data
->old_entries
, data
->entries_search
, &skey
) &&
1991 (old_entry
= git_vector_get(data
->old_entries
, pos
)) != NULL
&&
1992 entry
->mode
== old_entry
->mode
&&
1993 git_oid_equal(&entry
->oid
, &old_entry
->oid
))
1995 memcpy(entry
, old_entry
, sizeof(*entry
));
1996 entry
->flags_extended
= 0;
2000 if (path
.size
< GIT_IDXENTRY_NAMEMASK
)
2001 entry
->flags
= path
.size
& GIT_IDXENTRY_NAMEMASK
;
2003 entry
->flags
= GIT_IDXENTRY_NAMEMASK
;
2005 entry
->path
= git_buf_detach(&path
);
2006 git_buf_free(&path
);
2008 if (git_vector_insert(data
->new_entries
, entry
) < 0) {
2009 index_entry_free(entry
);
2016 int git_index_read_tree(git_index
*index
, const git_tree
*tree
)
2019 git_vector entries
= GIT_VECTOR_INIT
;
2020 read_tree_data data
;
2022 git_vector_set_cmp(&entries
, index
->entries
._cmp
); /* match sort */
2024 data
.old_entries
= &index
->entries
;
2025 data
.new_entries
= &entries
;
2026 data
.entries_search
= index
->entries_search
;
2028 git_vector_sort(&index
->entries
);
2030 error
= git_tree_walk(tree
, GIT_TREEWALK_POST
, read_tree_cb
, &data
);
2032 git_vector_sort(&entries
);
2034 git_index_clear(index
);
2036 git_vector_swap(&entries
, &index
->entries
);
2037 git_vector_free(&entries
);
2042 git_repository
*git_index_owner(const git_index
*index
)
2044 return INDEX_OWNER(index
);
2047 int git_index_add_all(
2049 const git_strarray
*paths
,
2051 git_index_matched_path_cb cb
,
2055 git_repository
*repo
;
2056 git_iterator
*wditer
= NULL
;
2057 const git_index_entry
*wd
= NULL
;
2058 git_index_entry
*entry
;
2062 bool no_fnmatch
= (flags
& GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
) != 0;
2068 if (INDEX_OWNER(index
) == NULL
)
2069 return create_index_error(-1,
2070 "Could not add paths to index. "
2071 "Index is not backed up by an existing repository.");
2073 repo
= INDEX_OWNER(index
);
2074 if ((error
= git_repository__ensure_not_bare(repo
, "index add all")) < 0)
2077 if (git_repository__cvar(&ignorecase
, repo
, GIT_CVAR_IGNORECASE
) < 0)
2080 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
2083 /* optionally check that pathspec doesn't mention any ignored files */
2084 if ((flags
& GIT_INDEX_ADD_CHECK_PATHSPEC
) != 0 &&
2085 (flags
& GIT_INDEX_ADD_FORCE
) == 0 &&
2086 (error
= git_ignore__check_pathspec_for_exact_ignores(
2087 repo
, &ps
.pathspec
, no_fnmatch
)) < 0)
2090 if ((error
= git_iterator_for_workdir(
2091 &wditer
, repo
, 0, ps
.prefix
, ps
.prefix
)) < 0)
2094 while (!(error
= git_iterator_advance(&wd
, wditer
))) {
2096 /* check if path actually matches */
2097 if (!git_pathspec__match(
2098 &ps
.pathspec
, wd
->path
, no_fnmatch
, (bool)ignorecase
, &match
, NULL
))
2101 /* skip ignored items that are not already in the index */
2102 if ((flags
& GIT_INDEX_ADD_FORCE
) == 0 &&
2103 git_iterator_current_is_ignored(wditer
) &&
2104 git_index__find(&existing
, index
, wd
->path
, 0) < 0)
2107 /* issue notification callback if requested */
2108 if (cb
&& (error
= cb(wd
->path
, match
, payload
)) != 0) {
2109 if (error
> 0) /* return > 0 means skip this one */
2111 if (error
< 0) { /* return < 0 means abort */
2118 /* TODO: Should we check if the file on disk is already an exact
2119 * match to the file in the index and skip this work if it is?
2122 /* write the blob to disk and get the oid */
2123 if ((error
= git_blob_create_fromworkdir(&blobid
, repo
, wd
->path
)) < 0)
2126 /* make the new entry to insert */
2127 if ((entry
= index_entry_dup(wd
)) == NULL
) {
2131 entry
->oid
= blobid
;
2133 /* add working directory item to index */
2134 if ((error
= index_insert(index
, entry
, 1)) < 0) {
2135 index_entry_free(entry
);
2139 git_tree_cache_invalidate_path(index
->tree
, wd
->path
);
2141 /* add implies conflict resolved, move conflict entries to REUC */
2142 if ((error
= index_conflict_to_reuc(index
, wd
->path
)) < 0) {
2143 if (error
!= GIT_ENOTFOUND
)
2149 if (error
== GIT_ITEROVER
)
2153 git_iterator_free(wditer
);
2154 git_pathspec__clear(&ps
);
2160 INDEX_ACTION_NONE
= 0,
2161 INDEX_ACTION_UPDATE
= 1,
2162 INDEX_ACTION_REMOVE
= 2,
2165 static int index_apply_to_all(
2168 const git_strarray
*paths
,
2169 git_index_matched_path_cb cb
,
2176 git_buf path
= GIT_BUF_INIT
;
2180 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
2183 git_vector_sort(&index
->entries
);
2185 for (i
= 0; !error
&& i
< index
->entries
.length
; ++i
) {
2186 git_index_entry
*entry
= git_vector_get(&index
->entries
, i
);
2188 /* check if path actually matches */
2189 if (!git_pathspec__match(
2190 &ps
.pathspec
, entry
->path
, false, (bool)index
->ignore_case
,
2194 /* issue notification callback if requested */
2195 if (cb
&& (error
= cb(entry
->path
, match
, payload
)) != 0) {
2196 if (error
> 0) { /* return > 0 means skip this one */
2200 if (error
< 0) { /* return < 0 means abort */
2207 /* index manipulation may alter entry, so don't depend on it */
2208 if ((error
= git_buf_sets(&path
, entry
->path
)) < 0)
2212 case INDEX_ACTION_NONE
:
2214 case INDEX_ACTION_UPDATE
:
2215 error
= git_index_add_bypath(index
, path
.ptr
);
2217 if (error
== GIT_ENOTFOUND
) {
2220 error
= git_index_remove_bypath(index
, path
.ptr
);
2222 if (!error
) /* back up foreach if we removed this */
2226 case INDEX_ACTION_REMOVE
:
2227 if (!(error
= git_index_remove_bypath(index
, path
.ptr
)))
2228 i
--; /* back up foreach if we removed this */
2231 giterr_set(GITERR_INVALID
, "Unknown index action %d", action
);
2237 git_buf_free(&path
);
2238 git_pathspec__clear(&ps
);
2243 int git_index_remove_all(
2245 const git_strarray
*pathspec
,
2246 git_index_matched_path_cb cb
,
2249 return index_apply_to_all(
2250 index
, INDEX_ACTION_REMOVE
, pathspec
, cb
, payload
);
2253 int git_index_update_all(
2255 const git_strarray
*pathspec
,
2256 git_index_matched_path_cb cb
,
2259 return index_apply_to_all(
2260 index
, INDEX_ACTION_UPDATE
, pathspec
, cb
, payload
);