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.
12 #include "repository.h"
14 #include "tree-cache.h"
27 #include "git2/blob.h"
28 #include "git2/config.h"
29 #include "git2/sys/index.h"
31 static int index_apply_to_wd_diff(git_index
*index
, int action
, const git_strarray
*paths
,
33 git_index_matched_path_cb cb
, void *payload
);
35 #define minimal_entry_size (offsetof(struct entry_short, path))
37 static const size_t INDEX_HEADER_SIZE
= 12;
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;
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'};
50 #define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
58 struct index_extension
{
60 uint32_t extension_size
;
69 struct entry_time ctime
;
70 struct entry_time mtime
;
79 char path
[1]; /* arbitrary length */
83 struct entry_time ctime
;
84 struct entry_time mtime
;
93 uint16_t flags_extended
;
94 char path
[1]; /* arbitrary length */
97 struct entry_srch_key
{
103 struct entry_internal
{
104 git_index_entry entry
;
106 char path
[GIT_FLEX_ARRAY
];
109 struct reuc_entry_internal
{
110 git_index_reuc_entry entry
;
112 char path
[GIT_FLEX_ARRAY
];
115 bool git_index__enforce_unsaved_safety
= false;
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
);
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(unsigned char checksum
[GIT_HASH_SHA1_SIZE
], size_t *checksum_size
, git_index
*index
, git_filebuf
*file
);
125 static void index_entry_free(git_index_entry
*entry
);
126 static void index_entry_reuc_free(git_index_reuc_entry
*reuc
);
128 GIT_INLINE(int) index_map_set(git_idxmap
*map
, git_index_entry
*e
, bool ignore_case
)
131 return git_idxmap_icase_set((git_idxmap_icase
*) map
, e
, e
);
133 return git_idxmap_set(map
, e
, e
);
136 GIT_INLINE(int) index_map_delete(git_idxmap
*map
, git_index_entry
*e
, bool ignore_case
)
139 return git_idxmap_icase_delete((git_idxmap_icase
*) map
, e
);
141 return git_idxmap_delete(map
, e
);
144 GIT_INLINE(int) index_map_resize(git_idxmap
*map
, size_t count
, bool ignore_case
)
147 return git_idxmap_icase_resize((git_idxmap_icase
*) map
, count
);
149 return git_idxmap_resize(map
, count
);
152 int git_index_entry_srch(const void *key
, const void *array_member
)
154 const struct entry_srch_key
*srch_key
= key
;
155 const struct entry_internal
*entry
= array_member
;
157 size_t len1
, len2
, len
;
159 len1
= srch_key
->pathlen
;
160 len2
= entry
->pathlen
;
161 len
= len1
< len2
? len1
: len2
;
163 cmp
= memcmp(srch_key
->path
, entry
->path
, len
);
171 if (srch_key
->stage
!= GIT_INDEX_STAGE_ANY
)
172 return srch_key
->stage
- GIT_INDEX_ENTRY_STAGE(&entry
->entry
);
177 int git_index_entry_isrch(const void *key
, const void *array_member
)
179 const struct entry_srch_key
*srch_key
= key
;
180 const struct entry_internal
*entry
= array_member
;
182 size_t len1
, len2
, len
;
184 len1
= srch_key
->pathlen
;
185 len2
= entry
->pathlen
;
186 len
= len1
< len2
? len1
: len2
;
188 cmp
= strncasecmp(srch_key
->path
, entry
->path
, len
);
197 if (srch_key
->stage
!= GIT_INDEX_STAGE_ANY
)
198 return srch_key
->stage
- GIT_INDEX_ENTRY_STAGE(&entry
->entry
);
203 static int index_entry_srch_path(const void *path
, const void *array_member
)
205 const git_index_entry
*entry
= array_member
;
207 return strcmp((const char *)path
, entry
->path
);
210 static int index_entry_isrch_path(const void *path
, const void *array_member
)
212 const git_index_entry
*entry
= array_member
;
214 return strcasecmp((const char *)path
, entry
->path
);
217 int git_index_entry_cmp(const void *a
, const void *b
)
220 const git_index_entry
*entry_a
= a
;
221 const git_index_entry
*entry_b
= b
;
223 diff
= strcmp(entry_a
->path
, entry_b
->path
);
226 diff
= (GIT_INDEX_ENTRY_STAGE(entry_a
) - GIT_INDEX_ENTRY_STAGE(entry_b
));
231 int git_index_entry_icmp(const void *a
, const void *b
)
234 const git_index_entry
*entry_a
= a
;
235 const git_index_entry
*entry_b
= b
;
237 diff
= strcasecmp(entry_a
->path
, entry_b
->path
);
240 diff
= (GIT_INDEX_ENTRY_STAGE(entry_a
) - GIT_INDEX_ENTRY_STAGE(entry_b
));
245 static int conflict_name_cmp(const void *a
, const void *b
)
247 const git_index_name_entry
*name_a
= a
;
248 const git_index_name_entry
*name_b
= b
;
250 if (name_a
->ancestor
&& !name_b
->ancestor
)
253 if (!name_a
->ancestor
&& name_b
->ancestor
)
256 if (name_a
->ancestor
)
257 return strcmp(name_a
->ancestor
, name_b
->ancestor
);
259 if (!name_a
->ours
|| !name_b
->ours
)
262 return strcmp(name_a
->ours
, name_b
->ours
);
266 * TODO: enable this when resolving case insensitive conflicts
269 static int conflict_name_icmp(const void *a
, const void *b
)
271 const git_index_name_entry
*name_a
= a
;
272 const git_index_name_entry
*name_b
= b
;
274 if (name_a
->ancestor
&& !name_b
->ancestor
)
277 if (!name_a
->ancestor
&& name_b
->ancestor
)
280 if (name_a
->ancestor
)
281 return strcasecmp(name_a
->ancestor
, name_b
->ancestor
);
283 if (!name_a
->ours
|| !name_b
->ours
)
286 return strcasecmp(name_a
->ours
, name_b
->ours
);
290 static int reuc_srch(const void *key
, const void *array_member
)
292 const git_index_reuc_entry
*reuc
= array_member
;
294 return strcmp(key
, reuc
->path
);
297 static int reuc_isrch(const void *key
, const void *array_member
)
299 const git_index_reuc_entry
*reuc
= array_member
;
301 return strcasecmp(key
, reuc
->path
);
304 static int reuc_cmp(const void *a
, const void *b
)
306 const git_index_reuc_entry
*info_a
= a
;
307 const git_index_reuc_entry
*info_b
= b
;
309 return strcmp(info_a
->path
, info_b
->path
);
312 static int reuc_icmp(const void *a
, const void *b
)
314 const git_index_reuc_entry
*info_a
= a
;
315 const git_index_reuc_entry
*info_b
= b
;
317 return strcasecmp(info_a
->path
, info_b
->path
);
320 static void index_entry_reuc_free(git_index_reuc_entry
*reuc
)
325 static void index_entry_free(git_index_entry
*entry
)
330 memset(&entry
->id
, 0, sizeof(entry
->id
));
334 unsigned int git_index__create_mode(unsigned int mode
)
339 if (S_ISDIR(mode
) || (mode
& S_IFMT
) == (S_IFLNK
| S_IFDIR
))
340 return (S_IFLNK
| S_IFDIR
);
342 return S_IFREG
| GIT_PERMS_CANONICAL(mode
);
345 static unsigned int index_merge_mode(
346 git_index
*index
, git_index_entry
*existing
, unsigned int mode
)
348 if (index
->no_symlinks
&& S_ISREG(mode
) &&
349 existing
&& S_ISLNK(existing
->mode
))
350 return existing
->mode
;
352 if (index
->distrust_filemode
&& S_ISREG(mode
))
353 return (existing
&& S_ISREG(existing
->mode
)) ?
354 existing
->mode
: git_index__create_mode(0666);
356 return git_index__create_mode(mode
);
359 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
)
363 struct entry_srch_key srch_key
;
364 srch_key
.path
= path
;
365 srch_key
.pathlen
= !path_len
? strlen(path
) : path_len
;
366 srch_key
.stage
= stage
;
367 return git_vector_bsearch2(out
, entries
, entry_srch
, &srch_key
);
370 GIT_INLINE(int) index_find(
371 size_t *out
, git_index
*index
,
372 const char *path
, size_t path_len
, int stage
)
374 git_vector_sort(&index
->entries
);
376 return index_find_in_entries(
377 out
, &index
->entries
, index
->entries_search
, path
, path_len
, stage
);
380 void git_index__set_ignore_case(git_index
*index
, bool ignore_case
)
382 index
->ignore_case
= ignore_case
;
385 index
->entries_cmp_path
= git__strcasecmp_cb
;
386 index
->entries_search
= git_index_entry_isrch
;
387 index
->entries_search_path
= index_entry_isrch_path
;
388 index
->reuc_search
= reuc_isrch
;
390 index
->entries_cmp_path
= git__strcmp_cb
;
391 index
->entries_search
= git_index_entry_srch
;
392 index
->entries_search_path
= index_entry_srch_path
;
393 index
->reuc_search
= reuc_srch
;
396 git_vector_set_cmp(&index
->entries
,
397 ignore_case
? git_index_entry_icmp
: git_index_entry_cmp
);
398 git_vector_sort(&index
->entries
);
400 git_vector_set_cmp(&index
->reuc
, ignore_case
? reuc_icmp
: reuc_cmp
);
401 git_vector_sort(&index
->reuc
);
404 int git_index_open(git_index
**index_out
, const char *index_path
)
409 GIT_ASSERT_ARG(index_out
);
411 index
= git__calloc(1, sizeof(git_index
));
412 GIT_ERROR_CHECK_ALLOC(index
);
414 if (git_pool_init(&index
->tree_pool
, 1) < 0)
417 if (index_path
!= NULL
) {
418 index
->index_file_path
= git__strdup(index_path
);
419 if (!index
->index_file_path
)
422 /* Check if index file is stored on disk already */
423 if (git_fs_path_exists(index
->index_file_path
) == true)
427 if (git_vector_init(&index
->entries
, 32, git_index_entry_cmp
) < 0 ||
428 git_idxmap_new(&index
->entries_map
) < 0 ||
429 git_vector_init(&index
->names
, 8, conflict_name_cmp
) < 0 ||
430 git_vector_init(&index
->reuc
, 8, reuc_cmp
) < 0 ||
431 git_vector_init(&index
->deleted
, 8, git_index_entry_cmp
) < 0)
434 index
->entries_cmp_path
= git__strcmp_cb
;
435 index
->entries_search
= git_index_entry_srch
;
436 index
->entries_search_path
= index_entry_srch_path
;
437 index
->reuc_search
= reuc_srch
;
438 index
->version
= INDEX_VERSION_NUMBER_DEFAULT
;
440 if (index_path
!= NULL
&& (error
= git_index_read(index
, true)) < 0)
444 GIT_REFCOUNT_INC(index
);
449 git_pool_clear(&index
->tree_pool
);
450 git_index_free(index
);
454 int git_index_new(git_index
**out
)
456 return git_index_open(out
, NULL
);
459 static void index_free(git_index
*index
)
461 /* index iterators increment the refcount of the index, so if we
462 * get here then there should be no outstanding iterators.
464 if (git_atomic32_get(&index
->readers
))
467 git_index_clear(index
);
468 git_idxmap_free(index
->entries_map
);
469 git_vector_free(&index
->entries
);
470 git_vector_free(&index
->names
);
471 git_vector_free(&index
->reuc
);
472 git_vector_free(&index
->deleted
);
474 git__free(index
->index_file_path
);
476 git__memzero(index
, sizeof(*index
));
480 void git_index_free(git_index
*index
)
485 GIT_REFCOUNT_DEC(index
, index_free
);
488 /* call with locked index */
489 static void index_free_deleted(git_index
*index
)
491 int readers
= (int)git_atomic32_get(&index
->readers
);
494 if (readers
> 0 || !index
->deleted
.length
)
497 for (i
= 0; i
< index
->deleted
.length
; ++i
) {
498 git_index_entry
*ie
= git_atomic_swap(index
->deleted
.contents
[i
], NULL
);
499 index_entry_free(ie
);
502 git_vector_clear(&index
->deleted
);
505 /* call with locked index */
506 static int index_remove_entry(git_index
*index
, size_t pos
)
509 git_index_entry
*entry
= git_vector_get(&index
->entries
, pos
);
512 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
513 index_map_delete(index
->entries_map
, entry
, index
->ignore_case
);
516 error
= git_vector_remove(&index
->entries
, pos
);
519 if (git_atomic32_get(&index
->readers
) > 0) {
520 error
= git_vector_insert(&index
->deleted
, entry
);
522 index_entry_free(entry
);
531 int git_index_clear(git_index
*index
)
535 GIT_ASSERT_ARG(index
);
539 git_pool_clear(&index
->tree_pool
);
541 git_idxmap_clear(index
->entries_map
);
542 while (!error
&& index
->entries
.length
> 0)
543 error
= index_remove_entry(index
, index
->entries
.length
- 1);
548 index_free_deleted(index
);
550 if ((error
= git_index_name_clear(index
)) < 0 ||
551 (error
= git_index_reuc_clear(index
)) < 0)
554 git_futils_filestamp_set(&index
->stamp
, NULL
);
560 static int create_index_error(int error
, const char *msg
)
562 git_error_set_str(GIT_ERROR_INDEX
, msg
);
566 int git_index_set_caps(git_index
*index
, int caps
)
568 unsigned int old_ignore_case
;
570 GIT_ASSERT_ARG(index
);
572 old_ignore_case
= index
->ignore_case
;
574 if (caps
== GIT_INDEX_CAPABILITY_FROM_OWNER
) {
575 git_repository
*repo
= INDEX_OWNER(index
);
579 return create_index_error(
580 -1, "cannot access repository to set index caps");
582 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_IGNORECASE
))
583 index
->ignore_case
= (val
!= 0);
584 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_FILEMODE
))
585 index
->distrust_filemode
= (val
== 0);
586 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_SYMLINKS
))
587 index
->no_symlinks
= (val
== 0);
590 index
->ignore_case
= ((caps
& GIT_INDEX_CAPABILITY_IGNORE_CASE
) != 0);
591 index
->distrust_filemode
= ((caps
& GIT_INDEX_CAPABILITY_NO_FILEMODE
) != 0);
592 index
->no_symlinks
= ((caps
& GIT_INDEX_CAPABILITY_NO_SYMLINKS
) != 0);
595 if (old_ignore_case
!= index
->ignore_case
) {
596 git_index__set_ignore_case(index
, (bool)index
->ignore_case
);
602 int git_index_caps(const git_index
*index
)
604 return ((index
->ignore_case
? GIT_INDEX_CAPABILITY_IGNORE_CASE
: 0) |
605 (index
->distrust_filemode
? GIT_INDEX_CAPABILITY_NO_FILEMODE
: 0) |
606 (index
->no_symlinks
? GIT_INDEX_CAPABILITY_NO_SYMLINKS
: 0));
609 #ifndef GIT_DEPRECATE_HARD
610 const git_oid
*git_index_checksum(git_index
*index
)
612 return (git_oid
*)index
->checksum
;
617 * Returns 1 for changed, 0 for not changed and <0 for errors
619 static int compare_checksum(git_index
*index
)
623 unsigned char checksum
[GIT_HASH_SHA1_SIZE
];
624 size_t checksum_size
= GIT_HASH_SHA1_SIZE
;
626 if ((fd
= p_open(index
->index_file_path
, O_RDONLY
)) < 0)
629 if (p_lseek(fd
, (0 - (ssize_t
)checksum_size
), SEEK_END
) < 0) {
631 git_error_set(GIT_ERROR_OS
, "failed to seek to end of file");
635 bytes_read
= p_read(fd
, checksum
, checksum_size
);
638 if (bytes_read
< (ssize_t
)checksum_size
)
641 return !!memcmp(checksum
, index
->checksum
, checksum_size
);
644 int git_index_read(git_index
*index
, int force
)
646 int error
= 0, updated
;
647 git_str buffer
= GIT_STR_INIT
;
648 git_futils_filestamp stamp
= index
->stamp
;
650 if (!index
->index_file_path
)
651 return create_index_error(-1,
652 "failed to read index: The index is in-memory only");
654 index
->on_disk
= git_fs_path_exists(index
->index_file_path
);
656 if (!index
->on_disk
) {
657 if (force
&& (error
= git_index_clear(index
)) < 0)
664 if ((updated
= git_futils_filestamp_check(&stamp
, index
->index_file_path
) < 0) ||
665 ((updated
= compare_checksum(index
)) < 0)) {
668 "failed to read index: '%s' no longer exists",
669 index
->index_file_path
);
673 if (!updated
&& !force
)
676 error
= git_futils_readbuffer(&buffer
, index
->index_file_path
);
681 git_pool_clear(&index
->tree_pool
);
683 error
= git_index_clear(index
);
686 error
= parse_index(index
, buffer
.ptr
, buffer
.size
);
689 git_futils_filestamp_set(&index
->stamp
, &stamp
);
693 git_str_dispose(&buffer
);
697 int git_index_read_safely(git_index
*index
)
699 if (git_index__enforce_unsaved_safety
&& index
->dirty
) {
700 git_error_set(GIT_ERROR_INDEX
,
701 "the index has unsaved changes that would be overwritten by this operation");
702 return GIT_EINDEXDIRTY
;
705 return git_index_read(index
, false);
708 static bool is_racy_entry(git_index
*index
, const git_index_entry
*entry
)
710 /* Git special-cases submodules in the check */
711 if (S_ISGITLINK(entry
->mode
))
714 return git_index_entry_newer_than_index(entry
, index
);
718 * Force the next diff to take a look at those entries which have the
719 * same timestamp as the current index.
721 static int truncate_racily_clean(git_index
*index
)
725 git_index_entry
*entry
;
726 git_diff_options diff_opts
= GIT_DIFF_OPTIONS_INIT
;
727 git_diff
*diff
= NULL
;
728 git_vector paths
= GIT_VECTOR_INIT
;
729 git_diff_delta
*delta
;
731 /* Nothing to do if there's no repo to talk about */
732 if (!INDEX_OWNER(index
))
735 /* If there's no workdir, we can't know where to even check */
736 if (!git_repository_workdir(INDEX_OWNER(index
)))
739 diff_opts
.flags
|= GIT_DIFF_INCLUDE_TYPECHANGE
| GIT_DIFF_IGNORE_SUBMODULES
| GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
740 git_vector_foreach(&index
->entries
, i
, entry
) {
741 if ((entry
->flags_extended
& GIT_INDEX_ENTRY_UPTODATE
) == 0 &&
742 is_racy_entry(index
, entry
))
743 git_vector_insert(&paths
, (char *)entry
->path
);
746 if (paths
.length
== 0)
749 diff_opts
.pathspec
.count
= paths
.length
;
750 diff_opts
.pathspec
.strings
= (char **)paths
.contents
;
752 if ((error
= git_diff_index_to_workdir(&diff
, INDEX_OWNER(index
), index
, &diff_opts
)) < 0)
755 git_vector_foreach(&diff
->deltas
, i
, delta
) {
756 entry
= (git_index_entry
*)git_index_get_bypath(index
, delta
->old_file
.path
, 0);
758 /* Ensure that we have a stage 0 for this file (ie, it's not a
759 * conflict), otherwise smudging it is quite pointless.
762 entry
->file_size
= 0;
769 git_vector_free(&paths
);
773 unsigned git_index_version(git_index
*index
)
775 GIT_ASSERT_ARG(index
);
777 return index
->version
;
780 int git_index_set_version(git_index
*index
, unsigned int version
)
782 GIT_ASSERT_ARG(index
);
784 if (version
< INDEX_VERSION_NUMBER_LB
||
785 version
> INDEX_VERSION_NUMBER_UB
) {
786 git_error_set(GIT_ERROR_INDEX
, "invalid version number");
790 index
->version
= version
;
795 int git_index_write(git_index
*index
)
797 git_indexwriter writer
= GIT_INDEXWRITER_INIT
;
800 truncate_racily_clean(index
);
802 if ((error
= git_indexwriter_init(&writer
, index
)) == 0 &&
803 (error
= git_indexwriter_commit(&writer
)) == 0)
806 git_indexwriter_cleanup(&writer
);
811 const char *git_index_path(const git_index
*index
)
813 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
814 return index
->index_file_path
;
817 int git_index_write_tree(git_oid
*oid
, git_index
*index
)
819 git_repository
*repo
;
822 GIT_ASSERT_ARG(index
);
824 repo
= INDEX_OWNER(index
);
827 return create_index_error(-1, "Failed to write tree. "
828 "the index file is not backed up by an existing repository");
830 return git_tree__write_index(oid
, index
, repo
);
833 int git_index_write_tree_to(
834 git_oid
*oid
, git_index
*index
, git_repository
*repo
)
837 GIT_ASSERT_ARG(index
);
838 GIT_ASSERT_ARG(repo
);
840 return git_tree__write_index(oid
, index
, repo
);
843 size_t git_index_entrycount(const git_index
*index
)
845 GIT_ASSERT_ARG(index
);
847 return index
->entries
.length
;
850 const git_index_entry
*git_index_get_byindex(
851 git_index
*index
, size_t n
)
853 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
855 git_vector_sort(&index
->entries
);
856 return git_vector_get(&index
->entries
, n
);
859 const git_index_entry
*git_index_get_bypath(
860 git_index
*index
, const char *path
, int stage
)
862 git_index_entry key
= {{ 0 }};
863 git_index_entry
*value
;
865 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
868 GIT_INDEX_ENTRY_STAGE_SET(&key
, stage
);
870 if (index
->ignore_case
)
871 value
= git_idxmap_icase_get((git_idxmap_icase
*) index
->entries_map
, &key
);
873 value
= git_idxmap_get(index
->entries_map
, &key
);
876 git_error_set(GIT_ERROR_INDEX
, "index does not contain '%s'", path
);
883 void git_index_entry__init_from_stat(
884 git_index_entry
*entry
, struct stat
*st
, bool trust_mode
)
886 entry
->ctime
.seconds
= (int32_t)st
->st_ctime
;
887 entry
->mtime
.seconds
= (int32_t)st
->st_mtime
;
888 #if defined(GIT_USE_NSEC)
889 entry
->mtime
.nanoseconds
= st
->st_mtime_nsec
;
890 entry
->ctime
.nanoseconds
= st
->st_ctime_nsec
;
892 entry
->dev
= st
->st_rdev
;
893 entry
->ino
= st
->st_ino
;
894 entry
->mode
= (!trust_mode
&& S_ISREG(st
->st_mode
)) ?
895 git_index__create_mode(0666) : git_index__create_mode(st
->st_mode
);
896 entry
->uid
= st
->st_uid
;
897 entry
->gid
= st
->st_gid
;
898 entry
->file_size
= (uint32_t)st
->st_size
;
901 static void index_entry_adjust_namemask(
902 git_index_entry
*entry
,
905 entry
->flags
&= ~GIT_INDEX_ENTRY_NAMEMASK
;
907 if (path_length
< GIT_INDEX_ENTRY_NAMEMASK
)
908 entry
->flags
|= path_length
& GIT_INDEX_ENTRY_NAMEMASK
;
910 entry
->flags
|= GIT_INDEX_ENTRY_NAMEMASK
;
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.
919 static int index_entry_create(
920 git_index_entry
**out
,
921 git_repository
*repo
,
926 size_t pathlen
= strlen(path
), alloclen
;
927 struct entry_internal
*entry
;
928 unsigned int path_valid_flags
= GIT_PATH_REJECT_INDEX_DEFAULTS
;
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).
936 path_valid_flags
|= GIT_PATH_REJECT_WORKDIR_DEFAULTS
;
940 if (!git_path_is_valid(repo
, path
, mode
, path_valid_flags
)) {
941 git_error_set(GIT_ERROR_INDEX
, "invalid path: '%s'", path
);
945 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, sizeof(struct entry_internal
), pathlen
);
946 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, alloclen
, 1);
947 entry
= git__calloc(1, alloclen
);
948 GIT_ERROR_CHECK_ALLOC(entry
);
950 entry
->pathlen
= pathlen
;
951 memcpy(entry
->path
, path
, pathlen
);
952 entry
->entry
.path
= entry
->path
;
954 *out
= (git_index_entry
*)entry
;
958 static int index_entry_init(
959 git_index_entry
**entry_out
,
961 const char *rel_path
)
964 git_index_entry
*entry
= NULL
;
965 git_str path
= GIT_STR_INIT
;
968 git_repository
*repo
;
970 if (INDEX_OWNER(index
) == NULL
)
971 return create_index_error(-1,
972 "could not initialize index entry. "
973 "Index is not backed up by an existing repository.");
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.
980 repo
= INDEX_OWNER(index
);
981 if (git_repository__ensure_not_bare(repo
, "create blob from file") < 0)
982 return GIT_EBAREREPO
;
984 if (git_repository_workdir_path(&path
, repo
, rel_path
) < 0)
987 error
= git_fs_path_lstat(path
.ptr
, &st
);
988 git_str_dispose(&path
);
993 if (index_entry_create(&entry
, INDEX_OWNER(index
), rel_path
, &st
, true) < 0)
996 /* write the blob to disk and get the oid and stat info */
997 error
= git_blob__create_from_paths(
998 &oid
, &st
, INDEX_OWNER(index
), NULL
, rel_path
, 0, true);
1001 index_entry_free(entry
);
1006 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1008 *entry_out
= (git_index_entry
*)entry
;
1012 static git_index_reuc_entry
*reuc_entry_alloc(const char *path
)
1014 size_t pathlen
= strlen(path
),
1015 structlen
= sizeof(struct reuc_entry_internal
),
1017 struct reuc_entry_internal
*entry
;
1019 if (GIT_ADD_SIZET_OVERFLOW(&alloclen
, structlen
, pathlen
) ||
1020 GIT_ADD_SIZET_OVERFLOW(&alloclen
, alloclen
, 1))
1023 entry
= git__calloc(1, alloclen
);
1027 entry
->pathlen
= pathlen
;
1028 memcpy(entry
->path
, path
, pathlen
);
1029 entry
->entry
.path
= entry
->path
;
1031 return (git_index_reuc_entry
*)entry
;
1034 static int index_entry_reuc_init(git_index_reuc_entry
**reuc_out
,
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
)
1040 git_index_reuc_entry
*reuc
= NULL
;
1042 GIT_ASSERT_ARG(reuc_out
);
1043 GIT_ASSERT_ARG(path
);
1045 *reuc_out
= reuc
= reuc_entry_alloc(path
);
1046 GIT_ERROR_CHECK_ALLOC(reuc
);
1048 if ((reuc
->mode
[0] = ancestor_mode
) > 0) {
1049 GIT_ASSERT(ancestor_oid
);
1050 git_oid_cpy(&reuc
->oid
[0], ancestor_oid
);
1053 if ((reuc
->mode
[1] = our_mode
) > 0) {
1054 GIT_ASSERT(our_oid
);
1055 git_oid_cpy(&reuc
->oid
[1], our_oid
);
1058 if ((reuc
->mode
[2] = their_mode
) > 0) {
1059 GIT_ASSERT(their_oid
);
1060 git_oid_cpy(&reuc
->oid
[2], their_oid
);
1066 static void index_entry_cpy(
1067 git_index_entry
*tgt
,
1068 const git_index_entry
*src
)
1070 const char *tgt_path
= tgt
->path
;
1071 memcpy(tgt
, src
, sizeof(*tgt
));
1072 tgt
->path
= tgt_path
;
1075 static int index_entry_dup(
1076 git_index_entry
**out
,
1078 const git_index_entry
*src
)
1080 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1083 index_entry_cpy(*out
, src
);
1087 static void index_entry_cpy_nocache(
1088 git_index_entry
*tgt
,
1089 const git_index_entry
*src
)
1091 git_oid_cpy(&tgt
->id
, &src
->id
);
1092 tgt
->mode
= src
->mode
;
1093 tgt
->flags
= src
->flags
;
1094 tgt
->flags_extended
= (src
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
1097 static int index_entry_dup_nocache(
1098 git_index_entry
**out
,
1100 const git_index_entry
*src
)
1102 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1105 index_entry_cpy_nocache(*out
, src
);
1109 static int has_file_name(git_index
*index
,
1110 const git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1112 size_t len
= strlen(entry
->path
);
1113 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1114 const char *name
= entry
->path
;
1116 while (pos
< index
->entries
.length
) {
1117 struct entry_internal
*p
= index
->entries
.contents
[pos
++];
1119 if (len
>= p
->pathlen
)
1121 if (memcmp(name
, p
->path
, len
))
1123 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) != stage
)
1125 if (p
->path
[len
] != '/')
1130 if (index_remove_entry(index
, --pos
) < 0)
1137 * Do we have another file with a pathname that is a proper
1138 * subset of the name we're trying to add?
1140 static int has_dir_name(git_index
*index
,
1141 const git_index_entry
*entry
, int ok_to_replace
)
1143 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1144 const char *name
= entry
->path
;
1145 const char *slash
= name
+ strlen(name
);
1151 if (*--slash
== '/')
1153 if (slash
<= entry
->path
)
1158 if (!index_find(&pos
, index
, name
, len
, stage
)) {
1162 if (index_remove_entry(index
, pos
) < 0)
1168 * Trivial optimization: if we find an entry that
1169 * already matches the sub-directory, then we know
1170 * we're ok, and we can exit.
1172 for (; pos
< index
->entries
.length
; ++pos
) {
1173 struct entry_internal
*p
= index
->entries
.contents
[pos
];
1175 if (p
->pathlen
<= len
||
1176 p
->path
[len
] != '/' ||
1177 memcmp(p
->path
, name
, len
))
1178 break; /* not our subdirectory */
1180 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) == stage
)
1188 static int check_file_directory_collision(git_index
*index
,
1189 git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1191 if (has_file_name(index
, entry
, pos
, ok_to_replace
) < 0 ||
1192 has_dir_name(index
, entry
, ok_to_replace
) < 0) {
1193 git_error_set(GIT_ERROR_INDEX
,
1194 "'%s' appears as both a file and a directory", entry
->path
);
1201 static int canonicalize_directory_path(
1203 git_index_entry
*entry
,
1204 git_index_entry
*existing
)
1206 const git_index_entry
*match
, *best
= NULL
;
1208 size_t pos
, search_len
, best_len
;
1210 if (!index
->ignore_case
)
1213 /* item already exists in the index, simply re-use the existing case */
1215 memcpy((char *)entry
->path
, existing
->path
, strlen(existing
->path
));
1220 if (strchr(entry
->path
, '/') == NULL
)
1223 if ((search
= git__strdup(entry
->path
)) == NULL
)
1226 /* starting at the parent directory and descending to the root, find the
1227 * common parent directory.
1229 while (!best
&& (sep
= strrchr(search
, '/'))) {
1232 search_len
= strlen(search
);
1234 git_vector_bsearch2(
1235 &pos
, &index
->entries
, index
->entries_search_path
, search
);
1237 while ((match
= git_vector_get(&index
->entries
, pos
))) {
1238 if (GIT_INDEX_ENTRY_STAGE(match
) != 0) {
1239 /* conflicts do not contribute to canonical paths */
1240 } else if (strncmp(search
, match
->path
, search_len
) == 0) {
1241 /* prefer an exact match to the input filename */
1243 best_len
= search_len
;
1245 } else if (strncasecmp(search
, match
->path
, search_len
) == 0) {
1246 /* continue walking, there may be a path with an exact
1247 * (case sensitive) match later in the index, but use this
1248 * as the best match until that happens.
1252 best_len
= search_len
;
1265 memcpy((char *)entry
->path
, best
->path
, best_len
);
1271 static int index_no_dups(void **old
, void *new)
1273 const git_index_entry
*entry
= new;
1275 git_error_set(GIT_ERROR_INDEX
, "'%s' appears multiple times at stage %d",
1276 entry
->path
, GIT_INDEX_ENTRY_STAGE(entry
));
1280 static void index_existing_and_best(
1281 git_index_entry
**existing
,
1282 size_t *existing_position
,
1283 git_index_entry
**best
,
1285 const git_index_entry
*entry
)
1291 error
= index_find(&pos
,
1292 index
, entry
->path
, 0, GIT_INDEX_ENTRY_STAGE(entry
));
1295 *existing
= index
->entries
.contents
[pos
];
1296 *existing_position
= pos
;
1297 *best
= index
->entries
.contents
[pos
];
1302 *existing_position
= 0;
1305 if (GIT_INDEX_ENTRY_STAGE(entry
) == 0) {
1306 for (; pos
< index
->entries
.length
; pos
++) {
1307 int (*strcomp
)(const char *a
, const char *b
) =
1308 index
->ignore_case
? git__strcasecmp
: git__strcmp
;
1310 e
= index
->entries
.contents
[pos
];
1312 if (strcomp(entry
->path
, e
->path
) != 0)
1315 if (GIT_INDEX_ENTRY_STAGE(e
) == GIT_INDEX_STAGE_ANCESTOR
) {
1326 /* index_insert takes ownership of the new entry - if it can't insert
1327 * it, then it will return an error **and also free the entry**. When
1328 * it replaces an existing entry, it will update the entry_ptr with the
1329 * actual entry in the index (and free the passed in one).
1331 * trust_path is whether we use the given path, or whether (on case
1332 * insensitive systems only) we try to canonicalize the given path to
1333 * be within an existing directory.
1335 * trust_mode is whether we trust the mode in entry_ptr.
1337 * trust_id is whether we trust the id or it should be validated.
1339 static int index_insert(
1341 git_index_entry
**entry_ptr
,
1347 git_index_entry
*existing
, *best
, *entry
;
1348 size_t path_length
, position
;
1351 GIT_ASSERT_ARG(index
);
1352 GIT_ASSERT_ARG(entry_ptr
);
1356 /* Make sure that the path length flag is correct */
1357 path_length
= ((struct entry_internal
*)entry
)->pathlen
;
1358 index_entry_adjust_namemask(entry
, path_length
);
1360 /* This entry is now up-to-date and should not be checked for raciness */
1361 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1363 git_vector_sort(&index
->entries
);
1366 * Look if an entry with this path already exists, either staged, or (if
1367 * this entry is a regular staged item) as the "ours" side of a conflict.
1369 index_existing_and_best(&existing
, &position
, &best
, index
, entry
);
1371 /* Update the file mode */
1372 entry
->mode
= trust_mode
?
1373 git_index__create_mode(entry
->mode
) :
1374 index_merge_mode(index
, best
, entry
->mode
);
1376 /* Canonicalize the directory name */
1377 if (!trust_path
&& (error
= canonicalize_directory_path(index
, entry
, best
)) < 0)
1380 /* Ensure that the given id exists (unless it's a submodule) */
1381 if (!trust_id
&& INDEX_OWNER(index
) &&
1382 (entry
->mode
& GIT_FILEMODE_COMMIT
) != GIT_FILEMODE_COMMIT
) {
1384 if (!git_object__is_valid(INDEX_OWNER(index
), &entry
->id
,
1385 git_object__type_from_filemode(entry
->mode
))) {
1391 /* Look for tree / blob name collisions, removing conflicts if requested */
1392 if ((error
= check_file_directory_collision(index
, entry
, position
, replace
)) < 0)
1396 * If we are replacing an existing item, overwrite the existing entry
1397 * and return it in place of the passed in one.
1401 index_entry_cpy(existing
, entry
);
1404 memcpy((char *)existing
->path
, entry
->path
, strlen(entry
->path
));
1407 index_entry_free(entry
);
1408 *entry_ptr
= existing
;
1411 * If replace is not requested or no existing entry exists, insert
1412 * at the sorted position. (Since we re-sort after each insert to
1413 * check for dups, this is actually cheaper in the long run.)
1415 if ((error
= git_vector_insert_sorted(&index
->entries
, entry
, index_no_dups
)) < 0 ||
1416 (error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1424 index_entry_free(*entry_ptr
);
1431 static int index_conflict_to_reuc(git_index
*index
, const char *path
)
1433 const git_index_entry
*conflict_entries
[3];
1434 int ancestor_mode
, our_mode
, their_mode
;
1435 git_oid
const *ancestor_oid
, *our_oid
, *their_oid
;
1438 if ((ret
= git_index_conflict_get(&conflict_entries
[0],
1439 &conflict_entries
[1], &conflict_entries
[2], index
, path
)) < 0)
1442 ancestor_mode
= conflict_entries
[0] == NULL
? 0 : conflict_entries
[0]->mode
;
1443 our_mode
= conflict_entries
[1] == NULL
? 0 : conflict_entries
[1]->mode
;
1444 their_mode
= conflict_entries
[2] == NULL
? 0 : conflict_entries
[2]->mode
;
1446 ancestor_oid
= conflict_entries
[0] == NULL
? NULL
: &conflict_entries
[0]->id
;
1447 our_oid
= conflict_entries
[1] == NULL
? NULL
: &conflict_entries
[1]->id
;
1448 their_oid
= conflict_entries
[2] == NULL
? NULL
: &conflict_entries
[2]->id
;
1450 if ((ret
= git_index_reuc_add(index
, path
, ancestor_mode
, ancestor_oid
,
1451 our_mode
, our_oid
, their_mode
, their_oid
)) >= 0)
1452 ret
= git_index_conflict_remove(index
, path
);
1457 GIT_INLINE(bool) is_file_or_link(const int filemode
)
1459 return (filemode
== GIT_FILEMODE_BLOB
||
1460 filemode
== GIT_FILEMODE_BLOB_EXECUTABLE
||
1461 filemode
== GIT_FILEMODE_LINK
);
1464 GIT_INLINE(bool) valid_filemode(const int filemode
)
1466 return (is_file_or_link(filemode
) || filemode
== GIT_FILEMODE_COMMIT
);
1469 int git_index_add_from_buffer(
1470 git_index
*index
, const git_index_entry
*source_entry
,
1471 const void *buffer
, size_t len
)
1473 git_index_entry
*entry
= NULL
;
1477 GIT_ASSERT_ARG(index
);
1478 GIT_ASSERT_ARG(source_entry
&& source_entry
->path
);
1480 if (INDEX_OWNER(index
) == NULL
)
1481 return create_index_error(-1,
1482 "could not initialize index entry. "
1483 "Index is not backed up by an existing repository.");
1485 if (!is_file_or_link(source_entry
->mode
)) {
1486 git_error_set(GIT_ERROR_INDEX
, "invalid filemode");
1490 if (len
> UINT32_MAX
) {
1491 git_error_set(GIT_ERROR_INDEX
, "buffer is too large");
1495 if (index_entry_dup(&entry
, index
, source_entry
) < 0)
1498 error
= git_blob_create_from_buffer(&id
, INDEX_OWNER(index
), buffer
, len
);
1500 index_entry_free(entry
);
1504 git_oid_cpy(&entry
->id
, &id
);
1505 entry
->file_size
= (uint32_t)len
;
1507 if ((error
= index_insert(index
, &entry
, 1, true, true, true)) < 0)
1510 /* Adding implies conflict was resolved, move conflict entries to REUC */
1511 if ((error
= index_conflict_to_reuc(index
, entry
->path
)) < 0 && error
!= GIT_ENOTFOUND
)
1514 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1518 static int add_repo_as_submodule(git_index_entry
**out
, git_index
*index
, const char *path
)
1520 git_repository
*sub
;
1521 git_str abspath
= GIT_STR_INIT
;
1522 git_repository
*repo
= INDEX_OWNER(index
);
1523 git_reference
*head
;
1524 git_index_entry
*entry
;
1528 if ((error
= git_repository_workdir_path(&abspath
, repo
, path
)) < 0)
1531 if ((error
= p_stat(abspath
.ptr
, &st
)) < 0) {
1532 git_error_set(GIT_ERROR_OS
, "failed to stat repository dir");
1536 if (index_entry_create(&entry
, INDEX_OWNER(index
), path
, &st
, true) < 0)
1539 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1541 if ((error
= git_repository_open(&sub
, abspath
.ptr
)) < 0)
1544 if ((error
= git_repository_head(&head
, sub
)) < 0)
1547 git_oid_cpy(&entry
->id
, git_reference_target(head
));
1548 entry
->mode
= GIT_FILEMODE_COMMIT
;
1550 git_reference_free(head
);
1551 git_repository_free(sub
);
1552 git_str_dispose(&abspath
);
1558 int git_index_add_bypath(git_index
*index
, const char *path
)
1560 git_index_entry
*entry
= NULL
;
1563 GIT_ASSERT_ARG(index
);
1564 GIT_ASSERT_ARG(path
);
1566 if ((ret
= index_entry_init(&entry
, index
, path
)) == 0)
1567 ret
= index_insert(index
, &entry
, 1, false, false, true);
1569 /* If we were given a directory, let's see if it's a submodule */
1570 if (ret
< 0 && ret
!= GIT_EDIRECTORY
)
1573 if (ret
== GIT_EDIRECTORY
) {
1575 git_error_state err
;
1577 git_error_state_capture(&err
, ret
);
1579 ret
= git_submodule_lookup(&sm
, INDEX_OWNER(index
), path
);
1580 if (ret
== GIT_ENOTFOUND
)
1581 return git_error_state_restore(&err
);
1583 git_error_state_free(&err
);
1586 * EEXISTS means that there is a repository at that path, but it's not known
1587 * as a submodule. We add its HEAD as an entry and don't register it.
1589 if (ret
== GIT_EEXISTS
) {
1590 if ((ret
= add_repo_as_submodule(&entry
, index
, path
)) < 0)
1593 if ((ret
= index_insert(index
, &entry
, 1, false, false, true)) < 0)
1595 } else if (ret
< 0) {
1598 ret
= git_submodule_add_to_index(sm
, false);
1599 git_submodule_free(sm
);
1604 /* Adding implies conflict was resolved, move conflict entries to REUC */
1605 if ((ret
= index_conflict_to_reuc(index
, path
)) < 0 && ret
!= GIT_ENOTFOUND
)
1608 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1612 int git_index_remove_bypath(git_index
*index
, const char *path
)
1616 GIT_ASSERT_ARG(index
);
1617 GIT_ASSERT_ARG(path
);
1619 if (((ret
= git_index_remove(index
, path
, 0)) < 0 &&
1620 ret
!= GIT_ENOTFOUND
) ||
1621 ((ret
= index_conflict_to_reuc(index
, path
)) < 0 &&
1622 ret
!= GIT_ENOTFOUND
))
1625 if (ret
== GIT_ENOTFOUND
)
1631 int git_index__fill(git_index
*index
, const git_vector
*source_entries
)
1633 const git_index_entry
*source_entry
= NULL
;
1637 GIT_ASSERT_ARG(index
);
1639 if (!source_entries
->length
)
1642 if (git_vector_size_hint(&index
->entries
, source_entries
->length
) < 0 ||
1643 index_map_resize(index
->entries_map
, (size_t)(source_entries
->length
* 1.3),
1644 index
->ignore_case
) < 0)
1647 git_vector_foreach(source_entries
, i
, source_entry
) {
1648 git_index_entry
*entry
= NULL
;
1650 if ((error
= index_entry_dup(&entry
, index
, source_entry
)) < 0)
1653 index_entry_adjust_namemask(entry
, ((struct entry_internal
*)entry
)->pathlen
);
1654 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1655 entry
->mode
= git_index__create_mode(entry
->mode
);
1657 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0)
1660 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1667 git_vector_sort(&index
->entries
);
1673 int git_index_add(git_index
*index
, const git_index_entry
*source_entry
)
1675 git_index_entry
*entry
= NULL
;
1678 GIT_ASSERT_ARG(index
);
1679 GIT_ASSERT_ARG(source_entry
&& source_entry
->path
);
1681 if (!valid_filemode(source_entry
->mode
)) {
1682 git_error_set(GIT_ERROR_INDEX
, "invalid entry mode");
1686 if ((ret
= index_entry_dup(&entry
, index
, source_entry
)) < 0 ||
1687 (ret
= index_insert(index
, &entry
, 1, true, true, false)) < 0)
1690 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1694 int git_index_remove(git_index
*index
, const char *path
, int stage
)
1698 git_index_entry remove_key
= {{ 0 }};
1700 remove_key
.path
= path
;
1701 GIT_INDEX_ENTRY_STAGE_SET(&remove_key
, stage
);
1703 index_map_delete(index
->entries_map
, &remove_key
, index
->ignore_case
);
1705 if (index_find(&position
, index
, path
, 0, stage
) < 0) {
1707 GIT_ERROR_INDEX
, "index does not contain %s at stage %d", path
, stage
);
1708 error
= GIT_ENOTFOUND
;
1710 error
= index_remove_entry(index
, position
);
1716 int git_index_remove_directory(git_index
*index
, const char *dir
, int stage
)
1718 git_str pfx
= GIT_STR_INIT
;
1721 git_index_entry
*entry
;
1723 if (!(error
= git_str_sets(&pfx
, dir
)) &&
1724 !(error
= git_fs_path_to_dir(&pfx
)))
1725 index_find(&pos
, index
, pfx
.ptr
, pfx
.size
, GIT_INDEX_STAGE_ANY
);
1728 entry
= git_vector_get(&index
->entries
, pos
);
1729 if (!entry
|| git__prefixcmp(entry
->path
, pfx
.ptr
) != 0)
1732 if (GIT_INDEX_ENTRY_STAGE(entry
) != stage
) {
1737 error
= index_remove_entry(index
, pos
);
1739 /* removed entry at 'pos' so we don't need to increment */
1742 git_str_dispose(&pfx
);
1747 int git_index_find_prefix(size_t *at_pos
, git_index
*index
, const char *prefix
)
1751 const git_index_entry
*entry
;
1753 index_find(&pos
, index
, prefix
, strlen(prefix
), GIT_INDEX_STAGE_ANY
);
1754 entry
= git_vector_get(&index
->entries
, pos
);
1755 if (!entry
|| git__prefixcmp(entry
->path
, prefix
) != 0)
1756 error
= GIT_ENOTFOUND
;
1758 if (!error
&& at_pos
)
1764 int git_index__find_pos(
1765 size_t *out
, git_index
*index
, const char *path
, size_t path_len
, int stage
)
1767 GIT_ASSERT_ARG(index
);
1768 GIT_ASSERT_ARG(path
);
1769 return index_find(out
, index
, path
, path_len
, stage
);
1772 int git_index_find(size_t *at_pos
, git_index
*index
, const char *path
)
1776 GIT_ASSERT_ARG(index
);
1777 GIT_ASSERT_ARG(path
);
1779 if (git_vector_bsearch2(
1780 &pos
, &index
->entries
, index
->entries_search_path
, path
) < 0) {
1781 git_error_set(GIT_ERROR_INDEX
, "index does not contain %s", path
);
1782 return GIT_ENOTFOUND
;
1785 /* Since our binary search only looked at path, we may be in the
1786 * middle of a list of stages.
1788 for (; pos
> 0; --pos
) {
1789 const git_index_entry
*prev
= git_vector_get(&index
->entries
, pos
- 1);
1791 if (index
->entries_cmp_path(prev
->path
, path
) != 0)
1801 int git_index_conflict_add(git_index
*index
,
1802 const git_index_entry
*ancestor_entry
,
1803 const git_index_entry
*our_entry
,
1804 const git_index_entry
*their_entry
)
1806 git_index_entry
*entries
[3] = { 0 };
1810 GIT_ASSERT_ARG(index
);
1812 if ((ancestor_entry
&&
1813 (ret
= index_entry_dup(&entries
[0], index
, ancestor_entry
)) < 0) ||
1815 (ret
= index_entry_dup(&entries
[1], index
, our_entry
)) < 0) ||
1817 (ret
= index_entry_dup(&entries
[2], index
, their_entry
)) < 0))
1820 /* Validate entries */
1821 for (i
= 0; i
< 3; i
++) {
1822 if (entries
[i
] && !valid_filemode(entries
[i
]->mode
)) {
1823 git_error_set(GIT_ERROR_INDEX
, "invalid filemode for stage %d entry",
1830 /* Remove existing index entries for each path */
1831 for (i
= 0; i
< 3; i
++) {
1832 if (entries
[i
] == NULL
)
1835 if ((ret
= git_index_remove(index
, entries
[i
]->path
, 0)) != 0) {
1836 if (ret
!= GIT_ENOTFOUND
)
1844 /* Add the conflict entries */
1845 for (i
= 0; i
< 3; i
++) {
1846 if (entries
[i
] == NULL
)
1849 /* Make sure stage is correct */
1850 GIT_INDEX_ENTRY_STAGE_SET(entries
[i
], i
+ 1);
1852 if ((ret
= index_insert(index
, &entries
[i
], 1, true, true, false)) < 0)
1855 entries
[i
] = NULL
; /* don't free if later entry fails */
1861 for (i
= 0; i
< 3; i
++) {
1862 if (entries
[i
] != NULL
)
1863 index_entry_free(entries
[i
]);
1869 static int index_conflict__get_byindex(
1870 const git_index_entry
**ancestor_out
,
1871 const git_index_entry
**our_out
,
1872 const git_index_entry
**their_out
,
1876 const git_index_entry
*conflict_entry
;
1877 const char *path
= NULL
;
1881 GIT_ASSERT_ARG(ancestor_out
);
1882 GIT_ASSERT_ARG(our_out
);
1883 GIT_ASSERT_ARG(their_out
);
1884 GIT_ASSERT_ARG(index
);
1886 *ancestor_out
= NULL
;
1890 for (count
= git_index_entrycount(index
); n
< count
; ++n
) {
1891 conflict_entry
= git_vector_get(&index
->entries
, n
);
1893 if (path
&& index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1896 stage
= GIT_INDEX_ENTRY_STAGE(conflict_entry
);
1897 path
= conflict_entry
->path
;
1901 *their_out
= conflict_entry
;
1905 *our_out
= conflict_entry
;
1909 *ancestor_out
= conflict_entry
;
1920 int git_index_conflict_get(
1921 const git_index_entry
**ancestor_out
,
1922 const git_index_entry
**our_out
,
1923 const git_index_entry
**their_out
,
1930 GIT_ASSERT_ARG(ancestor_out
);
1931 GIT_ASSERT_ARG(our_out
);
1932 GIT_ASSERT_ARG(their_out
);
1933 GIT_ASSERT_ARG(index
);
1934 GIT_ASSERT_ARG(path
);
1936 *ancestor_out
= NULL
;
1940 if (git_index_find(&pos
, index
, path
) < 0)
1941 return GIT_ENOTFOUND
;
1943 if ((len
= index_conflict__get_byindex(
1944 ancestor_out
, our_out
, their_out
, index
, pos
)) < 0)
1947 return GIT_ENOTFOUND
;
1952 static int index_conflict_remove(git_index
*index
, const char *path
)
1955 git_index_entry
*conflict_entry
;
1958 if (path
!= NULL
&& git_index_find(&pos
, index
, path
) < 0)
1959 return GIT_ENOTFOUND
;
1961 while ((conflict_entry
= git_vector_get(&index
->entries
, pos
)) != NULL
) {
1964 index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1967 if (GIT_INDEX_ENTRY_STAGE(conflict_entry
) == 0) {
1972 if ((error
= index_remove_entry(index
, pos
)) < 0)
1979 int git_index_conflict_remove(git_index
*index
, const char *path
)
1981 GIT_ASSERT_ARG(index
);
1982 GIT_ASSERT_ARG(path
);
1983 return index_conflict_remove(index
, path
);
1986 int git_index_conflict_cleanup(git_index
*index
)
1988 GIT_ASSERT_ARG(index
);
1989 return index_conflict_remove(index
, NULL
);
1992 int git_index_has_conflicts(const git_index
*index
)
1995 git_index_entry
*entry
;
1997 GIT_ASSERT_ARG(index
);
1999 git_vector_foreach(&index
->entries
, i
, entry
) {
2000 if (GIT_INDEX_ENTRY_STAGE(entry
) > 0)
2007 int git_index_iterator_new(
2008 git_index_iterator
**iterator_out
,
2011 git_index_iterator
*it
;
2014 GIT_ASSERT_ARG(iterator_out
);
2015 GIT_ASSERT_ARG(index
);
2017 it
= git__calloc(1, sizeof(git_index_iterator
));
2018 GIT_ERROR_CHECK_ALLOC(it
);
2020 if ((error
= git_index_snapshot_new(&it
->snap
, index
)) < 0) {
2031 int git_index_iterator_next(
2032 const git_index_entry
**out
,
2033 git_index_iterator
*it
)
2035 GIT_ASSERT_ARG(out
);
2038 if (it
->cur
>= git_vector_length(&it
->snap
))
2039 return GIT_ITEROVER
;
2041 *out
= (git_index_entry
*)git_vector_get(&it
->snap
, it
->cur
++);
2045 void git_index_iterator_free(git_index_iterator
*it
)
2050 git_index_snapshot_release(&it
->snap
, it
->index
);
2054 int git_index_conflict_iterator_new(
2055 git_index_conflict_iterator
**iterator_out
,
2058 git_index_conflict_iterator
*it
= NULL
;
2060 GIT_ASSERT_ARG(iterator_out
);
2061 GIT_ASSERT_ARG(index
);
2063 it
= git__calloc(1, sizeof(git_index_conflict_iterator
));
2064 GIT_ERROR_CHECK_ALLOC(it
);
2072 int git_index_conflict_next(
2073 const git_index_entry
**ancestor_out
,
2074 const git_index_entry
**our_out
,
2075 const git_index_entry
**their_out
,
2076 git_index_conflict_iterator
*iterator
)
2078 const git_index_entry
*entry
;
2081 GIT_ASSERT_ARG(ancestor_out
);
2082 GIT_ASSERT_ARG(our_out
);
2083 GIT_ASSERT_ARG(their_out
);
2084 GIT_ASSERT_ARG(iterator
);
2086 *ancestor_out
= NULL
;
2090 while (iterator
->cur
< iterator
->index
->entries
.length
) {
2091 entry
= git_index_get_byindex(iterator
->index
, iterator
->cur
);
2093 if (git_index_entry_is_conflict(entry
)) {
2094 if ((len
= index_conflict__get_byindex(
2099 iterator
->cur
)) < 0)
2102 iterator
->cur
+= len
;
2109 return GIT_ITEROVER
;
2112 void git_index_conflict_iterator_free(git_index_conflict_iterator
*iterator
)
2114 if (iterator
== NULL
)
2117 git__free(iterator
);
2120 size_t git_index_name_entrycount(git_index
*index
)
2122 GIT_ASSERT_ARG(index
);
2123 return index
->names
.length
;
2126 const git_index_name_entry
*git_index_name_get_byindex(
2127 git_index
*index
, size_t n
)
2129 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2131 git_vector_sort(&index
->names
);
2132 return git_vector_get(&index
->names
, n
);
2135 static void index_name_entry_free(git_index_name_entry
*ne
)
2139 git__free(ne
->ancestor
);
2140 git__free(ne
->ours
);
2141 git__free(ne
->theirs
);
2145 int git_index_name_add(git_index
*index
,
2146 const char *ancestor
, const char *ours
, const char *theirs
)
2148 git_index_name_entry
*conflict_name
;
2150 GIT_ASSERT_ARG((ancestor
&& ours
) || (ancestor
&& theirs
) || (ours
&& theirs
));
2152 conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2153 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2155 if ((ancestor
&& !(conflict_name
->ancestor
= git__strdup(ancestor
))) ||
2156 (ours
&& !(conflict_name
->ours
= git__strdup(ours
))) ||
2157 (theirs
&& !(conflict_name
->theirs
= git__strdup(theirs
))) ||
2158 git_vector_insert(&index
->names
, conflict_name
) < 0)
2160 index_name_entry_free(conflict_name
);
2168 int git_index_name_clear(git_index
*index
)
2171 git_index_name_entry
*conflict_name
;
2173 GIT_ASSERT_ARG(index
);
2175 git_vector_foreach(&index
->names
, i
, conflict_name
)
2176 index_name_entry_free(conflict_name
);
2178 git_vector_clear(&index
->names
);
2185 size_t git_index_reuc_entrycount(git_index
*index
)
2187 GIT_ASSERT_ARG(index
);
2188 return index
->reuc
.length
;
2191 static int index_reuc_on_dup(void **old
, void *new)
2193 index_entry_reuc_free(*old
);
2198 static int index_reuc_insert(
2200 git_index_reuc_entry
*reuc
)
2204 GIT_ASSERT_ARG(index
);
2205 GIT_ASSERT_ARG(reuc
&& reuc
->path
!= NULL
);
2206 GIT_ASSERT(git_vector_is_sorted(&index
->reuc
));
2208 res
= git_vector_insert_sorted(&index
->reuc
, reuc
, &index_reuc_on_dup
);
2211 return res
== GIT_EEXISTS
? 0 : res
;
2214 int git_index_reuc_add(git_index
*index
, const char *path
,
2215 int ancestor_mode
, const git_oid
*ancestor_oid
,
2216 int our_mode
, const git_oid
*our_oid
,
2217 int their_mode
, const git_oid
*their_oid
)
2219 git_index_reuc_entry
*reuc
= NULL
;
2222 GIT_ASSERT_ARG(index
);
2223 GIT_ASSERT_ARG(path
);
2225 if ((error
= index_entry_reuc_init(&reuc
, path
, ancestor_mode
,
2226 ancestor_oid
, our_mode
, our_oid
, their_mode
, their_oid
)) < 0 ||
2227 (error
= index_reuc_insert(index
, reuc
)) < 0)
2228 index_entry_reuc_free(reuc
);
2233 int git_index_reuc_find(size_t *at_pos
, git_index
*index
, const char *path
)
2235 return git_vector_bsearch2(at_pos
, &index
->reuc
, index
->reuc_search
, path
);
2238 const git_index_reuc_entry
*git_index_reuc_get_bypath(
2239 git_index
*index
, const char *path
)
2243 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2244 GIT_ASSERT_ARG_WITH_RETVAL(path
, NULL
);
2246 if (!index
->reuc
.length
)
2249 GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index
->reuc
), NULL
);
2251 if (git_index_reuc_find(&pos
, index
, path
) < 0)
2254 return git_vector_get(&index
->reuc
, pos
);
2257 const git_index_reuc_entry
*git_index_reuc_get_byindex(
2258 git_index
*index
, size_t n
)
2260 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2261 GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index
->reuc
), NULL
);
2263 return git_vector_get(&index
->reuc
, n
);
2266 int git_index_reuc_remove(git_index
*index
, size_t position
)
2269 git_index_reuc_entry
*reuc
;
2271 GIT_ASSERT_ARG(index
);
2272 GIT_ASSERT(git_vector_is_sorted(&index
->reuc
));
2274 reuc
= git_vector_get(&index
->reuc
, position
);
2275 error
= git_vector_remove(&index
->reuc
, position
);
2278 index_entry_reuc_free(reuc
);
2284 int git_index_reuc_clear(git_index
*index
)
2288 GIT_ASSERT_ARG(index
);
2290 for (i
= 0; i
< index
->reuc
.length
; ++i
)
2291 index_entry_reuc_free(git_atomic_swap(index
->reuc
.contents
[i
], NULL
));
2293 git_vector_clear(&index
->reuc
);
2300 static int index_error_invalid(const char *message
)
2302 git_error_set(GIT_ERROR_INDEX
, "invalid data in index - %s", message
);
2306 static int read_reuc(git_index
*index
, const char *buffer
, size_t size
)
2312 /* If called multiple times, the vector might already be initialized */
2313 if (index
->reuc
._alloc_size
== 0 &&
2314 git_vector_init(&index
->reuc
, 16, reuc_cmp
) < 0)
2318 git_index_reuc_entry
*lost
;
2320 len
= p_strnlen(buffer
, size
) + 1;
2322 return index_error_invalid("reading reuc entries");
2324 lost
= reuc_entry_alloc(buffer
);
2325 GIT_ERROR_CHECK_ALLOC(lost
);
2330 /* read 3 ASCII octal numbers for stage entries */
2331 for (i
= 0; i
< 3; i
++) {
2334 if (git__strntol64(&tmp
, buffer
, size
, &endptr
, 8) < 0 ||
2335 !endptr
|| endptr
== buffer
|| *endptr
||
2336 tmp
< 0 || tmp
> UINT32_MAX
) {
2337 index_entry_reuc_free(lost
);
2338 return index_error_invalid("reading reuc entry stage");
2341 lost
->mode
[i
] = (uint32_t)tmp
;
2343 len
= (endptr
+ 1) - buffer
;
2345 index_entry_reuc_free(lost
);
2346 return index_error_invalid("reading reuc entry stage");
2353 /* read up to 3 OIDs for stage entries */
2354 for (i
= 0; i
< 3; i
++) {
2358 index_entry_reuc_free(lost
);
2359 return index_error_invalid("reading reuc entry oid");
2362 git_oid_fromraw(&lost
->oid
[i
], (const unsigned char *) buffer
);
2367 /* entry was read successfully - insert into reuc vector */
2368 if (git_vector_insert(&index
->reuc
, lost
) < 0)
2372 /* entries are guaranteed to be sorted on-disk */
2373 git_vector_set_sorted(&index
->reuc
, true);
2379 static int read_conflict_names(git_index
*index
, const char *buffer
, size_t size
)
2383 /* This gets called multiple times, the vector might already be initialized */
2384 if (index
->names
._alloc_size
== 0 &&
2385 git_vector_init(&index
->names
, 16, conflict_name_cmp
) < 0)
2388 #define read_conflict_name(ptr) \
2389 len = p_strnlen(buffer, size) + 1; \
2391 index_error_invalid("reading conflict name entries"); \
2397 ptr = git__malloc(len); \
2398 GIT_ERROR_CHECK_ALLOC(ptr); \
2399 memcpy(ptr, buffer, len); \
2406 git_index_name_entry
*conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2407 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2409 read_conflict_name(conflict_name
->ancestor
);
2410 read_conflict_name(conflict_name
->ours
);
2411 read_conflict_name(conflict_name
->theirs
);
2413 if (git_vector_insert(&index
->names
, conflict_name
) < 0)
2419 git__free(conflict_name
->ancestor
);
2420 git__free(conflict_name
->ours
);
2421 git__free(conflict_name
->theirs
);
2422 git__free(conflict_name
);
2426 #undef read_conflict_name
2428 /* entries are guaranteed to be sorted on-disk */
2429 git_vector_set_sorted(&index
->names
, true);
2434 static size_t index_entry_size(size_t path_len
, size_t varint_len
, uint32_t flags
)
2437 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2438 return offsetof(struct entry_long
, path
) + path_len
+ 1 + varint_len
;
2440 return offsetof(struct entry_short
, path
) + path_len
+ 1 + varint_len
;
2442 #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
2443 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2444 return entry_size(struct entry_long
, path_len
);
2446 return entry_size(struct entry_short
, path_len
);
2451 static int read_entry(
2452 git_index_entry
**out
,
2459 size_t path_length
, entry_size
;
2460 const char *path_ptr
;
2461 struct entry_short source
;
2462 git_index_entry entry
= {{0}};
2463 bool compressed
= index
->version
>= INDEX_VERSION_NUMBER_COMP
;
2464 char *tmp_path
= NULL
;
2465 size_t checksum_size
= GIT_HASH_SHA1_SIZE
;
2467 if (checksum_size
+ minimal_entry_size
> buffer_size
)
2470 /* buffer is not guaranteed to be aligned */
2471 memcpy(&source
, buffer
, sizeof(struct entry_short
));
2473 entry
.ctime
.seconds
= (git_time_t
)ntohl(source
.ctime
.seconds
);
2474 entry
.ctime
.nanoseconds
= ntohl(source
.ctime
.nanoseconds
);
2475 entry
.mtime
.seconds
= (git_time_t
)ntohl(source
.mtime
.seconds
);
2476 entry
.mtime
.nanoseconds
= ntohl(source
.mtime
.nanoseconds
);
2477 entry
.dev
= ntohl(source
.dev
);
2478 entry
.ino
= ntohl(source
.ino
);
2479 entry
.mode
= ntohl(source
.mode
);
2480 entry
.uid
= ntohl(source
.uid
);
2481 entry
.gid
= ntohl(source
.gid
);
2482 entry
.file_size
= ntohl(source
.file_size
);
2483 git_oid_cpy(&entry
.id
, &source
.oid
);
2484 entry
.flags
= ntohs(source
.flags
);
2486 if (entry
.flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2488 size_t flags_offset
;
2490 flags_offset
= offsetof(struct entry_long
, flags_extended
);
2491 memcpy(&flags_raw
, (const char *) buffer
+ flags_offset
,
2493 flags_raw
= ntohs(flags_raw
);
2495 memcpy(&entry
.flags_extended
, &flags_raw
, sizeof(flags_raw
));
2496 path_ptr
= (const char *) buffer
+ offsetof(struct entry_long
, path
);
2498 path_ptr
= (const char *) buffer
+ offsetof(struct entry_short
, path
);
2501 path_length
= entry
.flags
& GIT_INDEX_ENTRY_NAMEMASK
;
2503 /* if this is a very long string, we must find its
2504 * real length without overflowing */
2505 if (path_length
== 0xFFF) {
2506 const char *path_end
;
2508 path_end
= memchr(path_ptr
, '\0', buffer_size
);
2509 if (path_end
== NULL
)
2512 path_length
= path_end
- path_ptr
;
2515 entry_size
= index_entry_size(path_length
, 0, entry
.flags
);
2516 entry
.path
= (char *)path_ptr
;
2518 size_t varint_len
, last_len
, prefix_len
, suffix_len
, path_len
;
2519 uintmax_t strip_len
;
2521 strip_len
= git_decode_varint((const unsigned char *)path_ptr
, &varint_len
);
2522 last_len
= strlen(last
);
2524 if (varint_len
== 0 || last_len
< strip_len
)
2525 return index_error_invalid("incorrect prefix length");
2527 prefix_len
= last_len
- (size_t)strip_len
;
2528 suffix_len
= strlen(path_ptr
+ varint_len
);
2530 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, prefix_len
, suffix_len
);
2531 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, path_len
, 1);
2533 if (path_len
> GIT_PATH_MAX
)
2534 return index_error_invalid("unreasonable path length");
2536 tmp_path
= git__malloc(path_len
);
2537 GIT_ERROR_CHECK_ALLOC(tmp_path
);
2539 memcpy(tmp_path
, last
, prefix_len
);
2540 memcpy(tmp_path
+ prefix_len
, path_ptr
+ varint_len
, suffix_len
+ 1);
2541 entry_size
= index_entry_size(suffix_len
, varint_len
, entry
.flags
);
2542 entry
.path
= tmp_path
;
2545 if (entry_size
== 0)
2548 if (checksum_size
+ entry_size
> buffer_size
)
2551 if (index_entry_dup(out
, index
, &entry
) < 0) {
2552 git__free(tmp_path
);
2556 git__free(tmp_path
);
2557 *out_size
= entry_size
;
2561 static int read_header(struct index_header
*dest
, const void *buffer
)
2563 const struct index_header
*source
= buffer
;
2565 dest
->signature
= ntohl(source
->signature
);
2566 if (dest
->signature
!= INDEX_HEADER_SIG
)
2567 return index_error_invalid("incorrect header signature");
2569 dest
->version
= ntohl(source
->version
);
2570 if (dest
->version
< INDEX_VERSION_NUMBER_LB
||
2571 dest
->version
> INDEX_VERSION_NUMBER_UB
)
2572 return index_error_invalid("incorrect header version");
2574 dest
->entry_count
= ntohl(source
->entry_count
);
2578 static int read_extension(size_t *read_len
, git_index
*index
, const char *buffer
, size_t buffer_size
)
2580 struct index_extension dest
;
2582 size_t checksum_size
= GIT_HASH_SHA1_SIZE
;
2584 /* buffer is not guaranteed to be aligned */
2585 memcpy(&dest
, buffer
, sizeof(struct index_extension
));
2586 dest
.extension_size
= ntohl(dest
.extension_size
);
2588 total_size
= dest
.extension_size
+ sizeof(struct index_extension
);
2590 if (dest
.extension_size
> total_size
||
2591 buffer_size
< total_size
||
2592 buffer_size
- total_size
< checksum_size
) {
2593 index_error_invalid("extension is truncated");
2597 /* optional extension */
2598 if (dest
.signature
[0] >= 'A' && dest
.signature
[0] <= 'Z') {
2600 if (memcmp(dest
.signature
, INDEX_EXT_TREECACHE_SIG
, 4) == 0) {
2601 if (git_tree_cache_read(&index
->tree
, buffer
+ 8, dest
.extension_size
, &index
->tree_pool
) < 0)
2603 } else if (memcmp(dest
.signature
, INDEX_EXT_UNMERGED_SIG
, 4) == 0) {
2604 if (read_reuc(index
, buffer
+ 8, dest
.extension_size
) < 0)
2606 } else if (memcmp(dest
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4) == 0) {
2607 if (read_conflict_names(index
, buffer
+ 8, dest
.extension_size
) < 0)
2610 /* else, unsupported extension. We cannot parse this, but we can skip
2611 * it by returning `total_size */
2613 /* we cannot handle non-ignorable extensions;
2614 * in fact they aren't even defined in the standard */
2615 git_error_set(GIT_ERROR_INDEX
, "unsupported mandatory extension: '%.4s'", dest
.signature
);
2619 *read_len
= total_size
;
2624 static int parse_index(git_index
*index
, const char *buffer
, size_t buffer_size
)
2628 struct index_header header
= { 0 };
2629 unsigned char checksum
[GIT_HASH_SHA1_SIZE
];
2630 size_t checksum_size
= GIT_HASH_SHA1_SIZE
;
2631 const char *last
= NULL
;
2632 const char *empty
= "";
2634 #define seek_forward(_increase) { \
2635 if (_increase >= buffer_size) { \
2636 error = index_error_invalid("ran out of data while parsing"); \
2638 buffer += _increase; \
2639 buffer_size -= _increase;\
2642 if (buffer_size
< INDEX_HEADER_SIZE
+ checksum_size
)
2643 return index_error_invalid("insufficient buffer space");
2645 /* Precalculate the SHA1 of the files's contents -- we'll match it to
2646 * the provided SHA1 in the footer */
2647 git_hash_buf(checksum
, buffer
, buffer_size
- checksum_size
, GIT_HASH_ALGORITHM_SHA1
);
2650 if ((error
= read_header(&header
, buffer
)) < 0)
2653 index
->version
= header
.version
;
2654 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2657 seek_forward(INDEX_HEADER_SIZE
);
2659 GIT_ASSERT(!index
->entries
.length
);
2661 if ((error
= index_map_resize(index
->entries_map
, header
.entry_count
, index
->ignore_case
)) < 0)
2664 /* Parse all the entries */
2665 for (i
= 0; i
< header
.entry_count
&& buffer_size
> checksum_size
; ++i
) {
2666 git_index_entry
*entry
= NULL
;
2669 if ((error
= read_entry(&entry
, &entry_size
, index
, buffer
, buffer_size
, last
)) < 0) {
2670 error
= index_error_invalid("invalid entry");
2674 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0) {
2675 index_entry_free(entry
);
2679 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0) {
2680 index_entry_free(entry
);
2685 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2688 seek_forward(entry_size
);
2691 if (i
!= header
.entry_count
) {
2692 error
= index_error_invalid("header entries changed while parsing");
2696 /* There's still space for some extensions! */
2697 while (buffer_size
> checksum_size
) {
2698 size_t extension_size
;
2700 if ((error
= read_extension(&extension_size
, index
, buffer
, buffer_size
)) < 0) {
2704 seek_forward(extension_size
);
2707 if (buffer_size
!= checksum_size
) {
2708 error
= index_error_invalid(
2709 "buffer size does not match index footer size");
2713 /* 160-bit SHA-1 over the content of the index file before this checksum. */
2714 if (memcmp(checksum
, buffer
, checksum_size
) != 0) {
2715 error
= index_error_invalid(
2716 "calculated checksum does not match expected");
2720 memcpy(index
->checksum
, checksum
, checksum_size
);
2724 /* Entries are stored case-sensitively on disk, so re-sort now if
2725 * in-memory index is supposed to be case-insensitive
2727 git_vector_set_sorted(&index
->entries
, !index
->ignore_case
);
2728 git_vector_sort(&index
->entries
);
2735 static bool is_index_extended(git_index
*index
)
2738 git_index_entry
*entry
;
2742 git_vector_foreach(&index
->entries
, i
, entry
) {
2743 entry
->flags
&= ~GIT_INDEX_ENTRY_EXTENDED
;
2744 if (entry
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
) {
2746 entry
->flags
|= GIT_INDEX_ENTRY_EXTENDED
;
2750 return (extended
> 0);
2753 static int write_disk_entry(git_filebuf
*file
, git_index_entry
*entry
, const char *last
)
2756 struct entry_short ondisk
;
2757 size_t path_len
, disk_size
;
2760 const char *path_start
= entry
->path
;
2761 size_t same_len
= 0;
2763 path_len
= ((struct entry_internal
*)entry
)->pathlen
;
2766 const char *last_c
= last
;
2768 while (*path_start
== *last_c
) {
2769 if (!*path_start
|| !*last_c
)
2775 path_len
-= same_len
;
2776 varint_len
= git_encode_varint(NULL
, 0, strlen(last
) - same_len
);
2779 disk_size
= index_entry_size(path_len
, varint_len
, entry
->flags
);
2781 if (git_filebuf_reserve(file
, &mem
, disk_size
) < 0)
2784 memset(mem
, 0x0, disk_size
);
2787 * Yes, we have to truncate.
2789 * The on-disk format for Index entries clearly defines
2790 * the time and size fields to be 4 bytes each -- so even if
2791 * we store these values with 8 bytes on-memory, they must
2792 * be truncated to 4 bytes before writing to disk.
2794 * In 2038 I will be either too dead or too rich to care about this
2796 ondisk
.ctime
.seconds
= htonl((uint32_t)entry
->ctime
.seconds
);
2797 ondisk
.mtime
.seconds
= htonl((uint32_t)entry
->mtime
.seconds
);
2798 ondisk
.ctime
.nanoseconds
= htonl(entry
->ctime
.nanoseconds
);
2799 ondisk
.mtime
.nanoseconds
= htonl(entry
->mtime
.nanoseconds
);
2800 ondisk
.dev
= htonl(entry
->dev
);
2801 ondisk
.ino
= htonl(entry
->ino
);
2802 ondisk
.mode
= htonl(entry
->mode
);
2803 ondisk
.uid
= htonl(entry
->uid
);
2804 ondisk
.gid
= htonl(entry
->gid
);
2805 ondisk
.file_size
= htonl((uint32_t)entry
->file_size
);
2807 git_oid_cpy(&ondisk
.oid
, &entry
->id
);
2809 ondisk
.flags
= htons(entry
->flags
);
2811 if (entry
->flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2812 const size_t path_offset
= offsetof(struct entry_long
, path
);
2813 struct entry_long ondisk_ext
;
2814 memcpy(&ondisk_ext
, &ondisk
, sizeof(struct entry_short
));
2815 ondisk_ext
.flags_extended
= htons(entry
->flags_extended
&
2816 GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
2817 memcpy(mem
, &ondisk_ext
, path_offset
);
2818 path
= (char *)mem
+ path_offset
;
2819 disk_size
-= path_offset
;
2821 const size_t path_offset
= offsetof(struct entry_short
, path
);
2822 memcpy(mem
, &ondisk
, path_offset
);
2823 path
= (char *)mem
+ path_offset
;
2824 disk_size
-= path_offset
;
2828 varint_len
= git_encode_varint((unsigned char *) path
,
2829 disk_size
, strlen(last
) - same_len
);
2830 GIT_ASSERT(varint_len
> 0);
2833 disk_size
-= varint_len
;
2836 * If using path compression, we are not allowed
2837 * to have additional trailing NULs.
2839 GIT_ASSERT(disk_size
== path_len
+ 1);
2842 * If no path compression is used, we do have
2843 * NULs as padding. As such, simply assert that
2844 * we have enough space left to write the path.
2846 GIT_ASSERT(disk_size
> path_len
);
2849 memcpy(path
, path_start
, path_len
+ 1);
2854 static int write_entries(git_index
*index
, git_filebuf
*file
)
2858 git_vector case_sorted
= GIT_VECTOR_INIT
, *entries
= NULL
;
2859 git_index_entry
*entry
;
2860 const char *last
= NULL
;
2862 /* If index->entries is sorted case-insensitively, then we need
2863 * to re-sort it case-sensitively before writing */
2864 if (index
->ignore_case
) {
2865 if ((error
= git_vector_dup(&case_sorted
, &index
->entries
, git_index_entry_cmp
)) < 0)
2868 git_vector_sort(&case_sorted
);
2869 entries
= &case_sorted
;
2871 entries
= &index
->entries
;
2874 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2877 git_vector_foreach(entries
, i
, entry
) {
2878 if ((error
= write_disk_entry(file
, entry
, last
)) < 0)
2880 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2885 git_vector_free(&case_sorted
);
2889 static int write_extension(git_filebuf
*file
, struct index_extension
*header
, git_str
*data
)
2891 struct index_extension ondisk
;
2893 memset(&ondisk
, 0x0, sizeof(struct index_extension
));
2894 memcpy(&ondisk
, header
, 4);
2895 ondisk
.extension_size
= htonl(header
->extension_size
);
2897 git_filebuf_write(file
, &ondisk
, sizeof(struct index_extension
));
2898 return git_filebuf_write(file
, data
->ptr
, data
->size
);
2901 static int create_name_extension_data(git_str
*name_buf
, git_index_name_entry
*conflict_name
)
2905 if (conflict_name
->ancestor
== NULL
)
2906 error
= git_str_put(name_buf
, "\0", 1);
2908 error
= git_str_put(name_buf
, conflict_name
->ancestor
, strlen(conflict_name
->ancestor
) + 1);
2913 if (conflict_name
->ours
== NULL
)
2914 error
= git_str_put(name_buf
, "\0", 1);
2916 error
= git_str_put(name_buf
, conflict_name
->ours
, strlen(conflict_name
->ours
) + 1);
2921 if (conflict_name
->theirs
== NULL
)
2922 error
= git_str_put(name_buf
, "\0", 1);
2924 error
= git_str_put(name_buf
, conflict_name
->theirs
, strlen(conflict_name
->theirs
) + 1);
2930 static int write_name_extension(git_index
*index
, git_filebuf
*file
)
2932 git_str name_buf
= GIT_STR_INIT
;
2933 git_vector
*out
= &index
->names
;
2934 git_index_name_entry
*conflict_name
;
2935 struct index_extension extension
;
2939 git_vector_foreach(out
, i
, conflict_name
) {
2940 if ((error
= create_name_extension_data(&name_buf
, conflict_name
)) < 0)
2944 memset(&extension
, 0x0, sizeof(struct index_extension
));
2945 memcpy(&extension
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4);
2946 extension
.extension_size
= (uint32_t)name_buf
.size
;
2948 error
= write_extension(file
, &extension
, &name_buf
);
2950 git_str_dispose(&name_buf
);
2956 static int create_reuc_extension_data(git_str
*reuc_buf
, git_index_reuc_entry
*reuc
)
2961 if ((error
= git_str_put(reuc_buf
, reuc
->path
, strlen(reuc
->path
) + 1)) < 0)
2964 for (i
= 0; i
< 3; i
++) {
2965 if ((error
= git_str_printf(reuc_buf
, "%o", reuc
->mode
[i
])) < 0 ||
2966 (error
= git_str_put(reuc_buf
, "\0", 1)) < 0)
2970 for (i
= 0; i
< 3; i
++) {
2971 if (reuc
->mode
[i
] && (error
= git_str_put(reuc_buf
, (char *)&reuc
->oid
[i
].id
, GIT_OID_RAWSZ
)) < 0)
2978 static int write_reuc_extension(git_index
*index
, git_filebuf
*file
)
2980 git_str reuc_buf
= GIT_STR_INIT
;
2981 git_vector
*out
= &index
->reuc
;
2982 git_index_reuc_entry
*reuc
;
2983 struct index_extension extension
;
2987 git_vector_foreach(out
, i
, reuc
) {
2988 if ((error
= create_reuc_extension_data(&reuc_buf
, reuc
)) < 0)
2992 memset(&extension
, 0x0, sizeof(struct index_extension
));
2993 memcpy(&extension
.signature
, INDEX_EXT_UNMERGED_SIG
, 4);
2994 extension
.extension_size
= (uint32_t)reuc_buf
.size
;
2996 error
= write_extension(file
, &extension
, &reuc_buf
);
2998 git_str_dispose(&reuc_buf
);
3004 static int write_tree_extension(git_index
*index
, git_filebuf
*file
)
3006 struct index_extension extension
;
3007 git_str buf
= GIT_STR_INIT
;
3010 if (index
->tree
== NULL
)
3013 if ((error
= git_tree_cache_write(&buf
, index
->tree
)) < 0)
3016 memset(&extension
, 0x0, sizeof(struct index_extension
));
3017 memcpy(&extension
.signature
, INDEX_EXT_TREECACHE_SIG
, 4);
3018 extension
.extension_size
= (uint32_t)buf
.size
;
3020 error
= write_extension(file
, &extension
, &buf
);
3022 git_str_dispose(&buf
);
3027 static void clear_uptodate(git_index
*index
)
3029 git_index_entry
*entry
;
3032 git_vector_foreach(&index
->entries
, i
, entry
)
3033 entry
->flags_extended
&= ~GIT_INDEX_ENTRY_UPTODATE
;
3036 static int write_index(
3037 unsigned char checksum
[GIT_HASH_SHA1_SIZE
],
3038 size_t *checksum_size
,
3042 struct index_header header
;
3044 uint32_t index_version_number
;
3046 GIT_ASSERT_ARG(index
);
3047 GIT_ASSERT_ARG(file
);
3049 *checksum_size
= GIT_HASH_SHA1_SIZE
;
3051 if (index
->version
<= INDEX_VERSION_NUMBER_EXT
) {
3052 is_extended
= is_index_extended(index
);
3053 index_version_number
= is_extended
? INDEX_VERSION_NUMBER_EXT
: INDEX_VERSION_NUMBER_LB
;
3055 index_version_number
= index
->version
;
3058 header
.signature
= htonl(INDEX_HEADER_SIG
);
3059 header
.version
= htonl(index_version_number
);
3060 header
.entry_count
= htonl((uint32_t)index
->entries
.length
);
3062 if (git_filebuf_write(file
, &header
, sizeof(struct index_header
)) < 0)
3065 if (write_entries(index
, file
) < 0)
3068 /* write the tree cache extension */
3069 if (index
->tree
!= NULL
&& write_tree_extension(index
, file
) < 0)
3072 /* write the rename conflict extension */
3073 if (index
->names
.length
> 0 && write_name_extension(index
, file
) < 0)
3076 /* write the reuc extension */
3077 if (index
->reuc
.length
> 0 && write_reuc_extension(index
, file
) < 0)
3080 /* get out the hash for all the contents we've appended to the file */
3081 git_filebuf_hash(checksum
, file
);
3083 /* write it at the end of the file */
3084 if (git_filebuf_write(file
, checksum
, *checksum_size
) < 0)
3087 /* file entries are no longer up to date */
3088 clear_uptodate(index
);
3093 int git_index_entry_stage(const git_index_entry
*entry
)
3095 return GIT_INDEX_ENTRY_STAGE(entry
);
3098 int git_index_entry_is_conflict(const git_index_entry
*entry
)
3100 return (GIT_INDEX_ENTRY_STAGE(entry
) > 0);
3103 typedef struct read_tree_data
{
3105 git_vector
*old_entries
;
3106 git_vector
*new_entries
;
3107 git_vector_cmp entry_cmp
;
3108 git_tree_cache
*tree
;
3111 static int read_tree_cb(
3112 const char *root
, const git_tree_entry
*tentry
, void *payload
)
3114 read_tree_data
*data
= payload
;
3115 git_index_entry
*entry
= NULL
, *old_entry
;
3116 git_str path
= GIT_STR_INIT
;
3119 if (git_tree_entry__is_tree(tentry
))
3122 if (git_str_joinpath(&path
, root
, tentry
->filename
) < 0)
3125 if (index_entry_create(&entry
, INDEX_OWNER(data
->index
), path
.ptr
, NULL
, false) < 0)
3128 entry
->mode
= tentry
->attr
;
3129 git_oid_cpy(&entry
->id
, git_tree_entry_id(tentry
));
3131 /* look for corresponding old entry and copy data to new entry */
3132 if (data
->old_entries
!= NULL
&&
3133 !index_find_in_entries(
3134 &pos
, data
->old_entries
, data
->entry_cmp
, path
.ptr
, 0, 0) &&
3135 (old_entry
= git_vector_get(data
->old_entries
, pos
)) != NULL
&&
3136 entry
->mode
== old_entry
->mode
&&
3137 git_oid_equal(&entry
->id
, &old_entry
->id
))
3139 index_entry_cpy(entry
, old_entry
);
3140 entry
->flags_extended
= 0;
3143 index_entry_adjust_namemask(entry
, path
.size
);
3144 git_str_dispose(&path
);
3146 if (git_vector_insert(data
->new_entries
, entry
) < 0) {
3147 index_entry_free(entry
);
3154 int git_index_read_tree(git_index
*index
, const git_tree
*tree
)
3157 git_vector entries
= GIT_VECTOR_INIT
;
3158 git_idxmap
*entries_map
;
3159 read_tree_data data
;
3163 if (git_idxmap_new(&entries_map
) < 0)
3166 git_vector_set_cmp(&entries
, index
->entries
._cmp
); /* match sort */
3169 data
.old_entries
= &index
->entries
;
3170 data
.new_entries
= &entries
;
3171 data
.entry_cmp
= index
->entries_search
;
3174 git_pool_clear(&index
->tree_pool
);
3176 git_vector_sort(&index
->entries
);
3178 if ((error
= git_tree_walk(tree
, GIT_TREEWALK_POST
, read_tree_cb
, &data
)) < 0)
3181 if ((error
= index_map_resize(entries_map
, entries
.length
, index
->ignore_case
)) < 0)
3184 git_vector_foreach(&entries
, i
, e
) {
3185 if ((error
= index_map_set(entries_map
, e
, index
->ignore_case
)) < 0) {
3186 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry into map");
3193 git_vector_sort(&entries
);
3195 if ((error
= git_index_clear(index
)) < 0) {
3196 /* well, this isn't good */;
3198 git_vector_swap(&entries
, &index
->entries
);
3199 entries_map
= git_atomic_swap(index
->entries_map
, entries_map
);
3205 git_vector_free(&entries
);
3206 git_idxmap_free(entries_map
);
3210 error
= git_tree_cache_read_tree(&index
->tree
, tree
, &index
->tree_pool
);
3215 static int git_index_read_iterator(
3217 git_iterator
*new_iterator
,
3218 size_t new_length_hint
)
3220 git_vector new_entries
= GIT_VECTOR_INIT
,
3221 remove_entries
= GIT_VECTOR_INIT
;
3222 git_idxmap
*new_entries_map
= NULL
;
3223 git_iterator
*index_iterator
= NULL
;
3224 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3225 const git_index_entry
*old_entry
, *new_entry
;
3226 git_index_entry
*entry
;
3230 GIT_ASSERT((new_iterator
->flags
& GIT_ITERATOR_DONT_IGNORE_CASE
));
3232 if ((error
= git_vector_init(&new_entries
, new_length_hint
, index
->entries
._cmp
)) < 0 ||
3233 (error
= git_vector_init(&remove_entries
, index
->entries
.length
, NULL
)) < 0 ||
3234 (error
= git_idxmap_new(&new_entries_map
)) < 0)
3237 if (new_length_hint
&& (error
= index_map_resize(new_entries_map
, new_length_hint
,
3238 index
->ignore_case
)) < 0)
3241 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3242 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3244 if ((error
= git_iterator_for_index(&index_iterator
,
3245 git_index_owner(index
), index
, &opts
)) < 0 ||
3246 ((error
= git_iterator_current(&old_entry
, index_iterator
)) < 0 &&
3247 error
!= GIT_ITEROVER
) ||
3248 ((error
= git_iterator_current(&new_entry
, new_iterator
)) < 0 &&
3249 error
!= GIT_ITEROVER
))
3256 *remove_entry
= NULL
;
3261 if (old_entry
&& new_entry
)
3262 diff
= git_index_entry_cmp(old_entry
, new_entry
);
3263 else if (!old_entry
&& new_entry
)
3265 else if (old_entry
&& !new_entry
)
3271 remove_entry
= (git_index_entry
*)old_entry
;
3272 } else if (diff
> 0) {
3273 dup_entry
= (git_index_entry
*)new_entry
;
3275 /* Path and stage are equal, if the OID is equal, keep it to
3276 * keep the stat cache data.
3278 if (git_oid_equal(&old_entry
->id
, &new_entry
->id
) &&
3279 old_entry
->mode
== new_entry
->mode
) {
3280 add_entry
= (git_index_entry
*)old_entry
;
3282 dup_entry
= (git_index_entry
*)new_entry
;
3283 remove_entry
= (git_index_entry
*)old_entry
;
3288 if ((error
= index_entry_dup_nocache(&add_entry
, index
, dup_entry
)) < 0)
3291 index_entry_adjust_namemask(add_entry
,
3292 ((struct entry_internal
*)add_entry
)->pathlen
);
3295 /* invalidate this path in the tree cache if this is new (to
3296 * invalidate the parent trees)
3298 if (dup_entry
&& !remove_entry
&& index
->tree
)
3299 git_tree_cache_invalidate_path(index
->tree
, dup_entry
->path
);
3302 if ((error
= git_vector_insert(&new_entries
, add_entry
)) == 0)
3303 error
= index_map_set(new_entries_map
, add_entry
,
3304 index
->ignore_case
);
3307 if (remove_entry
&& error
>= 0)
3308 error
= git_vector_insert(&remove_entries
, remove_entry
);
3311 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry");
3316 if ((error
= git_iterator_advance(&old_entry
, index_iterator
)) < 0 &&
3317 error
!= GIT_ITEROVER
)
3322 if ((error
= git_iterator_advance(&new_entry
, new_iterator
)) < 0 &&
3323 error
!= GIT_ITEROVER
)
3328 if ((error
= git_index_name_clear(index
)) < 0 ||
3329 (error
= git_index_reuc_clear(index
)) < 0)
3332 git_vector_swap(&new_entries
, &index
->entries
);
3333 new_entries_map
= git_atomic_swap(index
->entries_map
, new_entries_map
);
3335 git_vector_foreach(&remove_entries
, i
, entry
) {
3337 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
3339 index_entry_free(entry
);
3342 clear_uptodate(index
);
3348 git_idxmap_free(new_entries_map
);
3349 git_vector_free(&new_entries
);
3350 git_vector_free(&remove_entries
);
3351 git_iterator_free(index_iterator
);
3355 int git_index_read_index(
3357 const git_index
*new_index
)
3359 git_iterator
*new_iterator
= NULL
;
3360 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3363 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3364 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3366 if ((error
= git_iterator_for_index(&new_iterator
,
3367 git_index_owner(new_index
), (git_index
*)new_index
, &opts
)) < 0 ||
3368 (error
= git_index_read_iterator(index
, new_iterator
,
3369 new_index
->entries
.length
)) < 0)
3373 git_iterator_free(new_iterator
);
3377 git_repository
*git_index_owner(const git_index
*index
)
3379 return INDEX_OWNER(index
);
3383 INDEX_ACTION_NONE
= 0,
3384 INDEX_ACTION_UPDATE
= 1,
3385 INDEX_ACTION_REMOVE
= 2,
3386 INDEX_ACTION_ADDALL
= 3
3389 int git_index_add_all(
3391 const git_strarray
*paths
,
3393 git_index_matched_path_cb cb
,
3397 git_repository
*repo
;
3398 git_iterator
*wditer
= NULL
;
3400 bool no_fnmatch
= (flags
& GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
) != 0;
3402 GIT_ASSERT_ARG(index
);
3404 repo
= INDEX_OWNER(index
);
3405 if ((error
= git_repository__ensure_not_bare(repo
, "index add all")) < 0)
3408 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3411 /* optionally check that pathspec doesn't mention any ignored files */
3412 if ((flags
& GIT_INDEX_ADD_CHECK_PATHSPEC
) != 0 &&
3413 (flags
& GIT_INDEX_ADD_FORCE
) == 0 &&
3414 (error
= git_ignore__check_pathspec_for_exact_ignores(
3415 repo
, &ps
.pathspec
, no_fnmatch
)) < 0)
3418 error
= index_apply_to_wd_diff(index
, INDEX_ACTION_ADDALL
, paths
, flags
, cb
, payload
);
3421 git_error_set_after_callback(error
);
3424 git_iterator_free(wditer
);
3425 git_pathspec__clear(&ps
);
3430 struct foreach_diff_data
{
3432 const git_pathspec
*pathspec
;
3434 git_index_matched_path_cb cb
;
3438 static int apply_each_file(const git_diff_delta
*delta
, float progress
, void *payload
)
3440 struct foreach_diff_data
*data
= payload
;
3441 const char *match
, *path
;
3444 GIT_UNUSED(progress
);
3446 path
= delta
->old_file
.path
;
3448 /* We only want those which match the pathspecs */
3449 if (!git_pathspec__match(
3450 &data
->pathspec
->pathspec
, path
, false, (bool)data
->index
->ignore_case
,
3455 error
= data
->cb(path
, match
, data
->payload
);
3457 if (error
> 0) /* skip this entry */
3459 if (error
< 0) /* actual error */
3462 /* If the workdir item does not exist, remove it from the index. */
3463 if ((delta
->new_file
.flags
& GIT_DIFF_FLAG_EXISTS
) == 0)
3464 error
= git_index_remove_bypath(data
->index
, path
);
3466 error
= git_index_add_bypath(data
->index
, delta
->new_file
.path
);
3471 static int index_apply_to_wd_diff(git_index
*index
, int action
, const git_strarray
*paths
,
3473 git_index_matched_path_cb cb
, void *payload
)
3478 git_repository
*repo
;
3479 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
3480 struct foreach_diff_data data
= {
3488 GIT_ASSERT_ARG(index
);
3489 GIT_ASSERT_ARG(action
== INDEX_ACTION_UPDATE
|| action
== INDEX_ACTION_ADDALL
);
3491 repo
= INDEX_OWNER(index
);
3494 return create_index_error(-1,
3495 "cannot run update; the index is not backed up by a repository.");
3499 * We do the matching ourselves instead of passing the list to
3500 * diff because we want to tell the callback which one
3501 * matched, which we do not know if we ask diff to filter for us.
3503 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3506 opts
.flags
= GIT_DIFF_INCLUDE_TYPECHANGE
;
3507 if (action
== INDEX_ACTION_ADDALL
) {
3508 opts
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
|
3509 GIT_DIFF_RECURSE_UNTRACKED_DIRS
;
3511 if (flags
== GIT_INDEX_ADD_FORCE
)
3512 opts
.flags
|= GIT_DIFF_INCLUDE_IGNORED
;
3515 if ((error
= git_diff_index_to_workdir(&diff
, repo
, index
, &opts
)) < 0)
3518 data
.pathspec
= &ps
;
3519 error
= git_diff_foreach(diff
, apply_each_file
, NULL
, NULL
, NULL
, &data
);
3520 git_diff_free(diff
);
3522 if (error
) /* make sure error is set if callback stopped iteration */
3523 git_error_set_after_callback(error
);
3526 git_pathspec__clear(&ps
);
3530 static int index_apply_to_all(
3533 const git_strarray
*paths
,
3534 git_index_matched_path_cb cb
,
3541 git_str path
= GIT_STR_INIT
;
3543 GIT_ASSERT_ARG(index
);
3545 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3548 git_vector_sort(&index
->entries
);
3550 for (i
= 0; !error
&& i
< index
->entries
.length
; ++i
) {
3551 git_index_entry
*entry
= git_vector_get(&index
->entries
, i
);
3553 /* check if path actually matches */
3554 if (!git_pathspec__match(
3555 &ps
.pathspec
, entry
->path
, false, (bool)index
->ignore_case
,
3559 /* issue notification callback if requested */
3560 if (cb
&& (error
= cb(entry
->path
, match
, payload
)) != 0) {
3561 if (error
> 0) { /* return > 0 means skip this one */
3565 if (error
< 0) /* return < 0 means abort */
3569 /* index manipulation may alter entry, so don't depend on it */
3570 if ((error
= git_str_sets(&path
, entry
->path
)) < 0)
3574 case INDEX_ACTION_NONE
:
3576 case INDEX_ACTION_UPDATE
:
3577 error
= git_index_add_bypath(index
, path
.ptr
);
3579 if (error
== GIT_ENOTFOUND
) {
3582 error
= git_index_remove_bypath(index
, path
.ptr
);
3584 if (!error
) /* back up foreach if we removed this */
3588 case INDEX_ACTION_REMOVE
:
3589 if (!(error
= git_index_remove_bypath(index
, path
.ptr
)))
3590 i
--; /* back up foreach if we removed this */
3593 git_error_set(GIT_ERROR_INVALID
, "unknown index action %d", action
);
3599 git_str_dispose(&path
);
3600 git_pathspec__clear(&ps
);
3605 int git_index_remove_all(
3607 const git_strarray
*pathspec
,
3608 git_index_matched_path_cb cb
,
3611 int error
= index_apply_to_all(
3612 index
, INDEX_ACTION_REMOVE
, pathspec
, cb
, payload
);
3614 if (error
) /* make sure error is set if callback stopped iteration */
3615 git_error_set_after_callback(error
);
3620 int git_index_update_all(
3622 const git_strarray
*pathspec
,
3623 git_index_matched_path_cb cb
,
3626 int error
= index_apply_to_wd_diff(index
, INDEX_ACTION_UPDATE
, pathspec
, 0, cb
, payload
);
3627 if (error
) /* make sure error is set if callback stopped iteration */
3628 git_error_set_after_callback(error
);
3633 int git_index_snapshot_new(git_vector
*snap
, git_index
*index
)
3637 GIT_REFCOUNT_INC(index
);
3639 git_atomic32_inc(&index
->readers
);
3640 git_vector_sort(&index
->entries
);
3642 error
= git_vector_dup(snap
, &index
->entries
, index
->entries
._cmp
);
3645 git_index_snapshot_release(snap
, index
);
3650 void git_index_snapshot_release(git_vector
*snap
, git_index
*index
)
3652 git_vector_free(snap
);
3654 git_atomic32_dec(&index
->readers
);
3656 git_index_free(index
);
3659 int git_index_snapshot_find(
3660 size_t *out
, git_vector
*entries
, git_vector_cmp entry_srch
,
3661 const char *path
, size_t path_len
, int stage
)
3663 return index_find_in_entries(out
, entries
, entry_srch
, path
, path_len
, stage
);
3666 int git_indexwriter_init(
3667 git_indexwriter
*writer
,
3672 GIT_REFCOUNT_INC(index
);
3674 writer
->index
= index
;
3676 if (!index
->index_file_path
)
3677 return create_index_error(-1,
3678 "failed to write index: The index is in-memory only");
3680 if ((error
= git_filebuf_open(
3681 &writer
->file
, index
->index_file_path
, GIT_FILEBUF_HASH_CONTENTS
, GIT_INDEX_FILE_MODE
)) < 0) {
3683 if (error
== GIT_ELOCKED
)
3684 git_error_set(GIT_ERROR_INDEX
, "the index is locked; this might be due to a concurrent or crashed process");
3689 writer
->should_write
= 1;
3694 int git_indexwriter_init_for_operation(
3695 git_indexwriter
*writer
,
3696 git_repository
*repo
,
3697 unsigned int *checkout_strategy
)
3702 if ((error
= git_repository_index__weakptr(&index
, repo
)) < 0 ||
3703 (error
= git_indexwriter_init(writer
, index
)) < 0)
3706 writer
->should_write
= (*checkout_strategy
& GIT_CHECKOUT_DONT_WRITE_INDEX
) == 0;
3707 *checkout_strategy
|= GIT_CHECKOUT_DONT_WRITE_INDEX
;
3712 int git_indexwriter_commit(git_indexwriter
*writer
)
3714 unsigned char checksum
[GIT_HASH_SHA1_SIZE
];
3715 size_t checksum_size
;
3718 if (!writer
->should_write
)
3721 git_vector_sort(&writer
->index
->entries
);
3722 git_vector_sort(&writer
->index
->reuc
);
3724 if ((error
= write_index(checksum
, &checksum_size
, writer
->index
, &writer
->file
)) < 0) {
3725 git_indexwriter_cleanup(writer
);
3729 if ((error
= git_filebuf_commit(&writer
->file
)) < 0)
3732 if ((error
= git_futils_filestamp_check(
3733 &writer
->index
->stamp
, writer
->index
->index_file_path
)) < 0) {
3734 git_error_set(GIT_ERROR_OS
, "could not read index timestamp");
3738 writer
->index
->dirty
= 0;
3739 writer
->index
->on_disk
= 1;
3740 memcpy(writer
->index
->checksum
, checksum
, checksum_size
);
3742 git_index_free(writer
->index
);
3743 writer
->index
= NULL
;
3748 void git_indexwriter_cleanup(git_indexwriter
*writer
)
3750 git_filebuf_cleanup(&writer
->file
);
3752 git_index_free(writer
->index
);
3753 writer
->index
= NULL
;
3756 /* Deprecated functions */
3758 #ifndef GIT_DEPRECATE_HARD
3759 int git_index_add_frombuffer(
3760 git_index
*index
, const git_index_entry
*source_entry
,
3761 const void *buffer
, size_t len
)
3763 return git_index_add_from_buffer(index
, source_entry
, buffer
, len
);