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"
26 #include "git2/blob.h"
27 #include "git2/config.h"
28 #include "git2/sys/index.h"
30 static int index_apply_to_wd_diff(git_index
*index
, int action
, const git_strarray
*paths
,
32 git_index_matched_path_cb cb
, void *payload
);
34 #define minimal_entry_size (offsetof(struct entry_short, path))
36 static const size_t INDEX_FOOTER_SIZE
= GIT_OID_RAWSZ
;
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(git_oid
*checksum
, 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_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 const git_oid
*git_index_checksum(git_index
*index
)
611 return &index
->checksum
;
615 * Returns 1 for changed, 0 for not changed and <0 for errors
617 static int compare_checksum(git_index
*index
)
621 git_oid checksum
= {{ 0 }};
623 if ((fd
= p_open(index
->index_file_path
, O_RDONLY
)) < 0)
626 if (p_lseek(fd
, -20, SEEK_END
) < 0) {
628 git_error_set(GIT_ERROR_OS
, "failed to seek to end of file");
632 bytes_read
= p_read(fd
, &checksum
, GIT_OID_RAWSZ
);
638 return !!git_oid_cmp(&checksum
, &index
->checksum
);
641 int git_index_read(git_index
*index
, int force
)
643 int error
= 0, updated
;
644 git_buf buffer
= GIT_BUF_INIT
;
645 git_futils_filestamp stamp
= index
->stamp
;
647 if (!index
->index_file_path
)
648 return create_index_error(-1,
649 "failed to read index: The index is in-memory only");
651 index
->on_disk
= git_path_exists(index
->index_file_path
);
653 if (!index
->on_disk
) {
654 if (force
&& (error
= git_index_clear(index
)) < 0)
661 if ((updated
= git_futils_filestamp_check(&stamp
, index
->index_file_path
) < 0) ||
662 ((updated
= compare_checksum(index
)) < 0)) {
665 "failed to read index: '%s' no longer exists",
666 index
->index_file_path
);
670 if (!updated
&& !force
)
673 error
= git_futils_readbuffer(&buffer
, index
->index_file_path
);
678 git_pool_clear(&index
->tree_pool
);
680 error
= git_index_clear(index
);
683 error
= parse_index(index
, buffer
.ptr
, buffer
.size
);
686 git_futils_filestamp_set(&index
->stamp
, &stamp
);
690 git_buf_dispose(&buffer
);
694 int git_index_read_safely(git_index
*index
)
696 if (git_index__enforce_unsaved_safety
&& index
->dirty
) {
697 git_error_set(GIT_ERROR_INDEX
,
698 "the index has unsaved changes that would be overwritten by this operation");
699 return GIT_EINDEXDIRTY
;
702 return git_index_read(index
, false);
705 int git_index__changed_relative_to(
706 git_index
*index
, const git_oid
*checksum
)
708 /* attempt to update index (ignoring errors) */
709 if (git_index_read(index
, false) < 0)
712 return !!git_oid_cmp(&index
->checksum
, checksum
);
715 static bool is_racy_entry(git_index
*index
, const git_index_entry
*entry
)
717 /* Git special-cases submodules in the check */
718 if (S_ISGITLINK(entry
->mode
))
721 return git_index_entry_newer_than_index(entry
, index
);
725 * Force the next diff to take a look at those entries which have the
726 * same timestamp as the current index.
728 static int truncate_racily_clean(git_index
*index
)
732 git_index_entry
*entry
;
733 git_diff_options diff_opts
= GIT_DIFF_OPTIONS_INIT
;
734 git_diff
*diff
= NULL
;
735 git_vector paths
= GIT_VECTOR_INIT
;
736 git_diff_delta
*delta
;
738 /* Nothing to do if there's no repo to talk about */
739 if (!INDEX_OWNER(index
))
742 /* If there's no workdir, we can't know where to even check */
743 if (!git_repository_workdir(INDEX_OWNER(index
)))
746 diff_opts
.flags
|= GIT_DIFF_INCLUDE_TYPECHANGE
| GIT_DIFF_IGNORE_SUBMODULES
| GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
747 git_vector_foreach(&index
->entries
, i
, entry
) {
748 if ((entry
->flags_extended
& GIT_INDEX_ENTRY_UPTODATE
) == 0 &&
749 is_racy_entry(index
, entry
))
750 git_vector_insert(&paths
, (char *)entry
->path
);
753 if (paths
.length
== 0)
756 diff_opts
.pathspec
.count
= paths
.length
;
757 diff_opts
.pathspec
.strings
= (char **)paths
.contents
;
759 if ((error
= git_diff_index_to_workdir(&diff
, INDEX_OWNER(index
), index
, &diff_opts
)) < 0)
762 git_vector_foreach(&diff
->deltas
, i
, delta
) {
763 entry
= (git_index_entry
*)git_index_get_bypath(index
, delta
->old_file
.path
, 0);
765 /* Ensure that we have a stage 0 for this file (ie, it's not a
766 * conflict), otherwise smudging it is quite pointless.
769 entry
->file_size
= 0;
776 git_vector_free(&paths
);
780 unsigned git_index_version(git_index
*index
)
782 GIT_ASSERT_ARG(index
);
784 return index
->version
;
787 int git_index_set_version(git_index
*index
, unsigned int version
)
789 GIT_ASSERT_ARG(index
);
791 if (version
< INDEX_VERSION_NUMBER_LB
||
792 version
> INDEX_VERSION_NUMBER_UB
) {
793 git_error_set(GIT_ERROR_INDEX
, "invalid version number");
797 index
->version
= version
;
802 int git_index_write(git_index
*index
)
804 git_indexwriter writer
= GIT_INDEXWRITER_INIT
;
807 truncate_racily_clean(index
);
809 if ((error
= git_indexwriter_init(&writer
, index
)) == 0 &&
810 (error
= git_indexwriter_commit(&writer
)) == 0)
813 git_indexwriter_cleanup(&writer
);
818 const char *git_index_path(const git_index
*index
)
820 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
821 return index
->index_file_path
;
824 int git_index_write_tree(git_oid
*oid
, git_index
*index
)
826 git_repository
*repo
;
829 GIT_ASSERT_ARG(index
);
831 repo
= INDEX_OWNER(index
);
834 return create_index_error(-1, "Failed to write tree. "
835 "the index file is not backed up by an existing repository");
837 return git_tree__write_index(oid
, index
, repo
);
840 int git_index_write_tree_to(
841 git_oid
*oid
, git_index
*index
, git_repository
*repo
)
844 GIT_ASSERT_ARG(index
);
845 GIT_ASSERT_ARG(repo
);
847 return git_tree__write_index(oid
, index
, repo
);
850 size_t git_index_entrycount(const git_index
*index
)
852 GIT_ASSERT_ARG(index
);
854 return index
->entries
.length
;
857 const git_index_entry
*git_index_get_byindex(
858 git_index
*index
, size_t n
)
860 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
862 git_vector_sort(&index
->entries
);
863 return git_vector_get(&index
->entries
, n
);
866 const git_index_entry
*git_index_get_bypath(
867 git_index
*index
, const char *path
, int stage
)
869 git_index_entry key
= {{ 0 }};
870 git_index_entry
*value
;
872 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
875 GIT_INDEX_ENTRY_STAGE_SET(&key
, stage
);
877 if (index
->ignore_case
)
878 value
= git_idxmap_icase_get((git_idxmap_icase
*) index
->entries_map
, &key
);
880 value
= git_idxmap_get(index
->entries_map
, &key
);
883 git_error_set(GIT_ERROR_INDEX
, "index does not contain '%s'", path
);
890 void git_index_entry__init_from_stat(
891 git_index_entry
*entry
, struct stat
*st
, bool trust_mode
)
893 entry
->ctime
.seconds
= (int32_t)st
->st_ctime
;
894 entry
->mtime
.seconds
= (int32_t)st
->st_mtime
;
895 #if defined(GIT_USE_NSEC)
896 entry
->mtime
.nanoseconds
= st
->st_mtime_nsec
;
897 entry
->ctime
.nanoseconds
= st
->st_ctime_nsec
;
899 entry
->dev
= st
->st_rdev
;
900 entry
->ino
= st
->st_ino
;
901 entry
->mode
= (!trust_mode
&& S_ISREG(st
->st_mode
)) ?
902 git_index__create_mode(0666) : git_index__create_mode(st
->st_mode
);
903 entry
->uid
= st
->st_uid
;
904 entry
->gid
= st
->st_gid
;
905 entry
->file_size
= (uint32_t)st
->st_size
;
908 static void index_entry_adjust_namemask(
909 git_index_entry
*entry
,
912 entry
->flags
&= ~GIT_INDEX_ENTRY_NAMEMASK
;
914 if (path_length
< GIT_INDEX_ENTRY_NAMEMASK
)
915 entry
->flags
|= path_length
& GIT_INDEX_ENTRY_NAMEMASK
;
917 entry
->flags
|= GIT_INDEX_ENTRY_NAMEMASK
;
920 /* When `from_workdir` is true, we will validate the paths to avoid placing
921 * paths that are invalid for the working directory on the current filesystem
922 * (eg, on Windows, we will disallow `GIT~1`, `AUX`, `COM1`, etc). This
923 * function will *always* prevent `.git` and directory traversal `../` from
924 * being added to the index.
926 static int index_entry_create(
927 git_index_entry
**out
,
928 git_repository
*repo
,
933 size_t pathlen
= strlen(path
), alloclen
;
934 struct entry_internal
*entry
;
935 unsigned int path_valid_flags
= GIT_PATH_REJECT_INDEX_DEFAULTS
;
938 /* always reject placing `.git` in the index and directory traversal.
939 * when requested, disallow platform-specific filenames and upgrade to
940 * the platform-specific `.git` tests (eg, `git~1`, etc).
943 path_valid_flags
|= GIT_PATH_REJECT_WORKDIR_DEFAULTS
;
947 if (!git_path_validate(repo
, path
, mode
, path_valid_flags
)) {
948 git_error_set(GIT_ERROR_INDEX
, "invalid path: '%s'", path
);
952 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, sizeof(struct entry_internal
), pathlen
);
953 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, alloclen
, 1);
954 entry
= git__calloc(1, alloclen
);
955 GIT_ERROR_CHECK_ALLOC(entry
);
957 entry
->pathlen
= pathlen
;
958 memcpy(entry
->path
, path
, pathlen
);
959 entry
->entry
.path
= entry
->path
;
961 *out
= (git_index_entry
*)entry
;
965 static int index_entry_init(
966 git_index_entry
**entry_out
,
968 const char *rel_path
)
971 git_index_entry
*entry
= NULL
;
972 git_buf path
= GIT_BUF_INIT
;
975 git_repository
*repo
;
977 if (INDEX_OWNER(index
) == NULL
)
978 return create_index_error(-1,
979 "could not initialize index entry. "
980 "Index is not backed up by an existing repository.");
983 * FIXME: this is duplicated with the work in
984 * git_blob__create_from_paths. It should accept an optional stat
985 * structure so we can pass in the one we have to do here.
987 repo
= INDEX_OWNER(index
);
988 if (git_repository__ensure_not_bare(repo
, "create blob from file") < 0)
989 return GIT_EBAREREPO
;
991 if (git_repository_workdir_path(&path
, repo
, rel_path
) < 0)
994 error
= git_path_lstat(path
.ptr
, &st
);
995 git_buf_dispose(&path
);
1000 if (index_entry_create(&entry
, INDEX_OWNER(index
), rel_path
, &st
, true) < 0)
1003 /* write the blob to disk and get the oid and stat info */
1004 error
= git_blob__create_from_paths(
1005 &oid
, &st
, INDEX_OWNER(index
), NULL
, rel_path
, 0, true);
1008 index_entry_free(entry
);
1013 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1015 *entry_out
= (git_index_entry
*)entry
;
1019 static git_index_reuc_entry
*reuc_entry_alloc(const char *path
)
1021 size_t pathlen
= strlen(path
),
1022 structlen
= sizeof(struct reuc_entry_internal
),
1024 struct reuc_entry_internal
*entry
;
1026 if (GIT_ADD_SIZET_OVERFLOW(&alloclen
, structlen
, pathlen
) ||
1027 GIT_ADD_SIZET_OVERFLOW(&alloclen
, alloclen
, 1))
1030 entry
= git__calloc(1, alloclen
);
1034 entry
->pathlen
= pathlen
;
1035 memcpy(entry
->path
, path
, pathlen
);
1036 entry
->entry
.path
= entry
->path
;
1038 return (git_index_reuc_entry
*)entry
;
1041 static int index_entry_reuc_init(git_index_reuc_entry
**reuc_out
,
1043 int ancestor_mode
, const git_oid
*ancestor_oid
,
1044 int our_mode
, const git_oid
*our_oid
,
1045 int their_mode
, const git_oid
*their_oid
)
1047 git_index_reuc_entry
*reuc
= NULL
;
1049 GIT_ASSERT_ARG(reuc_out
);
1050 GIT_ASSERT_ARG(path
);
1052 *reuc_out
= reuc
= reuc_entry_alloc(path
);
1053 GIT_ERROR_CHECK_ALLOC(reuc
);
1055 if ((reuc
->mode
[0] = ancestor_mode
) > 0) {
1056 GIT_ASSERT(ancestor_oid
);
1057 git_oid_cpy(&reuc
->oid
[0], ancestor_oid
);
1060 if ((reuc
->mode
[1] = our_mode
) > 0) {
1061 GIT_ASSERT(our_oid
);
1062 git_oid_cpy(&reuc
->oid
[1], our_oid
);
1065 if ((reuc
->mode
[2] = their_mode
) > 0) {
1066 GIT_ASSERT(their_oid
);
1067 git_oid_cpy(&reuc
->oid
[2], their_oid
);
1073 static void index_entry_cpy(
1074 git_index_entry
*tgt
,
1075 const git_index_entry
*src
)
1077 const char *tgt_path
= tgt
->path
;
1078 memcpy(tgt
, src
, sizeof(*tgt
));
1079 tgt
->path
= tgt_path
;
1082 static int index_entry_dup(
1083 git_index_entry
**out
,
1085 const git_index_entry
*src
)
1087 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1090 index_entry_cpy(*out
, src
);
1094 static void index_entry_cpy_nocache(
1095 git_index_entry
*tgt
,
1096 const git_index_entry
*src
)
1098 git_oid_cpy(&tgt
->id
, &src
->id
);
1099 tgt
->mode
= src
->mode
;
1100 tgt
->flags
= src
->flags
;
1101 tgt
->flags_extended
= (src
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
1104 static int index_entry_dup_nocache(
1105 git_index_entry
**out
,
1107 const git_index_entry
*src
)
1109 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1112 index_entry_cpy_nocache(*out
, src
);
1116 static int has_file_name(git_index
*index
,
1117 const git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1119 size_t len
= strlen(entry
->path
);
1120 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1121 const char *name
= entry
->path
;
1123 while (pos
< index
->entries
.length
) {
1124 struct entry_internal
*p
= index
->entries
.contents
[pos
++];
1126 if (len
>= p
->pathlen
)
1128 if (memcmp(name
, p
->path
, len
))
1130 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) != stage
)
1132 if (p
->path
[len
] != '/')
1137 if (index_remove_entry(index
, --pos
) < 0)
1144 * Do we have another file with a pathname that is a proper
1145 * subset of the name we're trying to add?
1147 static int has_dir_name(git_index
*index
,
1148 const git_index_entry
*entry
, int ok_to_replace
)
1150 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1151 const char *name
= entry
->path
;
1152 const char *slash
= name
+ strlen(name
);
1158 if (*--slash
== '/')
1160 if (slash
<= entry
->path
)
1165 if (!index_find(&pos
, index
, name
, len
, stage
)) {
1169 if (index_remove_entry(index
, pos
) < 0)
1175 * Trivial optimization: if we find an entry that
1176 * already matches the sub-directory, then we know
1177 * we're ok, and we can exit.
1179 for (; pos
< index
->entries
.length
; ++pos
) {
1180 struct entry_internal
*p
= index
->entries
.contents
[pos
];
1182 if (p
->pathlen
<= len
||
1183 p
->path
[len
] != '/' ||
1184 memcmp(p
->path
, name
, len
))
1185 break; /* not our subdirectory */
1187 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) == stage
)
1195 static int check_file_directory_collision(git_index
*index
,
1196 git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1198 if (has_file_name(index
, entry
, pos
, ok_to_replace
) < 0 ||
1199 has_dir_name(index
, entry
, ok_to_replace
) < 0) {
1200 git_error_set(GIT_ERROR_INDEX
,
1201 "'%s' appears as both a file and a directory", entry
->path
);
1208 static int canonicalize_directory_path(
1210 git_index_entry
*entry
,
1211 git_index_entry
*existing
)
1213 const git_index_entry
*match
, *best
= NULL
;
1215 size_t pos
, search_len
, best_len
;
1217 if (!index
->ignore_case
)
1220 /* item already exists in the index, simply re-use the existing case */
1222 memcpy((char *)entry
->path
, existing
->path
, strlen(existing
->path
));
1227 if (strchr(entry
->path
, '/') == NULL
)
1230 if ((search
= git__strdup(entry
->path
)) == NULL
)
1233 /* starting at the parent directory and descending to the root, find the
1234 * common parent directory.
1236 while (!best
&& (sep
= strrchr(search
, '/'))) {
1239 search_len
= strlen(search
);
1241 git_vector_bsearch2(
1242 &pos
, &index
->entries
, index
->entries_search_path
, search
);
1244 while ((match
= git_vector_get(&index
->entries
, pos
))) {
1245 if (GIT_INDEX_ENTRY_STAGE(match
) != 0) {
1246 /* conflicts do not contribute to canonical paths */
1247 } else if (strncmp(search
, match
->path
, search_len
) == 0) {
1248 /* prefer an exact match to the input filename */
1250 best_len
= search_len
;
1252 } else if (strncasecmp(search
, match
->path
, search_len
) == 0) {
1253 /* continue walking, there may be a path with an exact
1254 * (case sensitive) match later in the index, but use this
1255 * as the best match until that happens.
1259 best_len
= search_len
;
1272 memcpy((char *)entry
->path
, best
->path
, best_len
);
1278 static int index_no_dups(void **old
, void *new)
1280 const git_index_entry
*entry
= new;
1282 git_error_set(GIT_ERROR_INDEX
, "'%s' appears multiple times at stage %d",
1283 entry
->path
, GIT_INDEX_ENTRY_STAGE(entry
));
1287 static void index_existing_and_best(
1288 git_index_entry
**existing
,
1289 size_t *existing_position
,
1290 git_index_entry
**best
,
1292 const git_index_entry
*entry
)
1298 error
= index_find(&pos
,
1299 index
, entry
->path
, 0, GIT_INDEX_ENTRY_STAGE(entry
));
1302 *existing
= index
->entries
.contents
[pos
];
1303 *existing_position
= pos
;
1304 *best
= index
->entries
.contents
[pos
];
1309 *existing_position
= 0;
1312 if (GIT_INDEX_ENTRY_STAGE(entry
) == 0) {
1313 for (; pos
< index
->entries
.length
; pos
++) {
1314 int (*strcomp
)(const char *a
, const char *b
) =
1315 index
->ignore_case
? git__strcasecmp
: git__strcmp
;
1317 e
= index
->entries
.contents
[pos
];
1319 if (strcomp(entry
->path
, e
->path
) != 0)
1322 if (GIT_INDEX_ENTRY_STAGE(e
) == GIT_INDEX_STAGE_ANCESTOR
) {
1333 /* index_insert takes ownership of the new entry - if it can't insert
1334 * it, then it will return an error **and also free the entry**. When
1335 * it replaces an existing entry, it will update the entry_ptr with the
1336 * actual entry in the index (and free the passed in one).
1338 * trust_path is whether we use the given path, or whether (on case
1339 * insensitive systems only) we try to canonicalize the given path to
1340 * be within an existing directory.
1342 * trust_mode is whether we trust the mode in entry_ptr.
1344 * trust_id is whether we trust the id or it should be validated.
1346 static int index_insert(
1348 git_index_entry
**entry_ptr
,
1354 git_index_entry
*existing
, *best
, *entry
;
1355 size_t path_length
, position
;
1358 GIT_ASSERT_ARG(index
);
1359 GIT_ASSERT_ARG(entry_ptr
);
1363 /* Make sure that the path length flag is correct */
1364 path_length
= ((struct entry_internal
*)entry
)->pathlen
;
1365 index_entry_adjust_namemask(entry
, path_length
);
1367 /* This entry is now up-to-date and should not be checked for raciness */
1368 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1370 git_vector_sort(&index
->entries
);
1373 * Look if an entry with this path already exists, either staged, or (if
1374 * this entry is a regular staged item) as the "ours" side of a conflict.
1376 index_existing_and_best(&existing
, &position
, &best
, index
, entry
);
1378 /* Update the file mode */
1379 entry
->mode
= trust_mode
?
1380 git_index__create_mode(entry
->mode
) :
1381 index_merge_mode(index
, best
, entry
->mode
);
1383 /* Canonicalize the directory name */
1384 if (!trust_path
&& (error
= canonicalize_directory_path(index
, entry
, best
)) < 0)
1387 /* Ensure that the given id exists (unless it's a submodule) */
1388 if (!trust_id
&& INDEX_OWNER(index
) &&
1389 (entry
->mode
& GIT_FILEMODE_COMMIT
) != GIT_FILEMODE_COMMIT
) {
1391 if (!git_object__is_valid(INDEX_OWNER(index
), &entry
->id
,
1392 git_object__type_from_filemode(entry
->mode
))) {
1398 /* Look for tree / blob name collisions, removing conflicts if requested */
1399 if ((error
= check_file_directory_collision(index
, entry
, position
, replace
)) < 0)
1403 * If we are replacing an existing item, overwrite the existing entry
1404 * and return it in place of the passed in one.
1408 index_entry_cpy(existing
, entry
);
1411 memcpy((char *)existing
->path
, entry
->path
, strlen(entry
->path
));
1414 index_entry_free(entry
);
1415 *entry_ptr
= existing
;
1418 * If replace is not requested or no existing entry exists, insert
1419 * at the sorted position. (Since we re-sort after each insert to
1420 * check for dups, this is actually cheaper in the long run.)
1422 if ((error
= git_vector_insert_sorted(&index
->entries
, entry
, index_no_dups
)) < 0 ||
1423 (error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1431 index_entry_free(*entry_ptr
);
1438 static int index_conflict_to_reuc(git_index
*index
, const char *path
)
1440 const git_index_entry
*conflict_entries
[3];
1441 int ancestor_mode
, our_mode
, their_mode
;
1442 git_oid
const *ancestor_oid
, *our_oid
, *their_oid
;
1445 if ((ret
= git_index_conflict_get(&conflict_entries
[0],
1446 &conflict_entries
[1], &conflict_entries
[2], index
, path
)) < 0)
1449 ancestor_mode
= conflict_entries
[0] == NULL
? 0 : conflict_entries
[0]->mode
;
1450 our_mode
= conflict_entries
[1] == NULL
? 0 : conflict_entries
[1]->mode
;
1451 their_mode
= conflict_entries
[2] == NULL
? 0 : conflict_entries
[2]->mode
;
1453 ancestor_oid
= conflict_entries
[0] == NULL
? NULL
: &conflict_entries
[0]->id
;
1454 our_oid
= conflict_entries
[1] == NULL
? NULL
: &conflict_entries
[1]->id
;
1455 their_oid
= conflict_entries
[2] == NULL
? NULL
: &conflict_entries
[2]->id
;
1457 if ((ret
= git_index_reuc_add(index
, path
, ancestor_mode
, ancestor_oid
,
1458 our_mode
, our_oid
, their_mode
, their_oid
)) >= 0)
1459 ret
= git_index_conflict_remove(index
, path
);
1464 GIT_INLINE(bool) is_file_or_link(const int filemode
)
1466 return (filemode
== GIT_FILEMODE_BLOB
||
1467 filemode
== GIT_FILEMODE_BLOB_EXECUTABLE
||
1468 filemode
== GIT_FILEMODE_LINK
);
1471 GIT_INLINE(bool) valid_filemode(const int filemode
)
1473 return (is_file_or_link(filemode
) || filemode
== GIT_FILEMODE_COMMIT
);
1476 int git_index_add_from_buffer(
1477 git_index
*index
, const git_index_entry
*source_entry
,
1478 const void *buffer
, size_t len
)
1480 git_index_entry
*entry
= NULL
;
1484 GIT_ASSERT_ARG(index
);
1485 GIT_ASSERT_ARG(source_entry
&& source_entry
->path
);
1487 if (INDEX_OWNER(index
) == NULL
)
1488 return create_index_error(-1,
1489 "could not initialize index entry. "
1490 "Index is not backed up by an existing repository.");
1492 if (!is_file_or_link(source_entry
->mode
)) {
1493 git_error_set(GIT_ERROR_INDEX
, "invalid filemode");
1497 if (len
> UINT32_MAX
) {
1498 git_error_set(GIT_ERROR_INDEX
, "buffer is too large");
1502 if (index_entry_dup(&entry
, index
, source_entry
) < 0)
1505 error
= git_blob_create_from_buffer(&id
, INDEX_OWNER(index
), buffer
, len
);
1507 index_entry_free(entry
);
1511 git_oid_cpy(&entry
->id
, &id
);
1512 entry
->file_size
= (uint32_t)len
;
1514 if ((error
= index_insert(index
, &entry
, 1, true, true, true)) < 0)
1517 /* Adding implies conflict was resolved, move conflict entries to REUC */
1518 if ((error
= index_conflict_to_reuc(index
, entry
->path
)) < 0 && error
!= GIT_ENOTFOUND
)
1521 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1525 static int add_repo_as_submodule(git_index_entry
**out
, git_index
*index
, const char *path
)
1527 git_repository
*sub
;
1528 git_buf abspath
= GIT_BUF_INIT
;
1529 git_repository
*repo
= INDEX_OWNER(index
);
1530 git_reference
*head
;
1531 git_index_entry
*entry
;
1535 if ((error
= git_repository_workdir_path(&abspath
, repo
, path
)) < 0)
1538 if ((error
= p_stat(abspath
.ptr
, &st
)) < 0) {
1539 git_error_set(GIT_ERROR_OS
, "failed to stat repository dir");
1543 if (index_entry_create(&entry
, INDEX_OWNER(index
), path
, &st
, true) < 0)
1546 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1548 if ((error
= git_repository_open(&sub
, abspath
.ptr
)) < 0)
1551 if ((error
= git_repository_head(&head
, sub
)) < 0)
1554 git_oid_cpy(&entry
->id
, git_reference_target(head
));
1555 entry
->mode
= GIT_FILEMODE_COMMIT
;
1557 git_reference_free(head
);
1558 git_repository_free(sub
);
1559 git_buf_dispose(&abspath
);
1565 int git_index_add_bypath(git_index
*index
, const char *path
)
1567 git_index_entry
*entry
= NULL
;
1570 GIT_ASSERT_ARG(index
);
1571 GIT_ASSERT_ARG(path
);
1573 if ((ret
= index_entry_init(&entry
, index
, path
)) == 0)
1574 ret
= index_insert(index
, &entry
, 1, false, false, true);
1576 /* If we were given a directory, let's see if it's a submodule */
1577 if (ret
< 0 && ret
!= GIT_EDIRECTORY
)
1580 if (ret
== GIT_EDIRECTORY
) {
1582 git_error_state err
;
1584 git_error_state_capture(&err
, ret
);
1586 ret
= git_submodule_lookup(&sm
, INDEX_OWNER(index
), path
);
1587 if (ret
== GIT_ENOTFOUND
)
1588 return git_error_state_restore(&err
);
1590 git_error_state_free(&err
);
1593 * EEXISTS means that there is a repository at that path, but it's not known
1594 * as a submodule. We add its HEAD as an entry and don't register it.
1596 if (ret
== GIT_EEXISTS
) {
1597 if ((ret
= add_repo_as_submodule(&entry
, index
, path
)) < 0)
1600 if ((ret
= index_insert(index
, &entry
, 1, false, false, true)) < 0)
1602 } else if (ret
< 0) {
1605 ret
= git_submodule_add_to_index(sm
, false);
1606 git_submodule_free(sm
);
1611 /* Adding implies conflict was resolved, move conflict entries to REUC */
1612 if ((ret
= index_conflict_to_reuc(index
, path
)) < 0 && ret
!= GIT_ENOTFOUND
)
1615 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1619 int git_index_remove_bypath(git_index
*index
, const char *path
)
1623 GIT_ASSERT_ARG(index
);
1624 GIT_ASSERT_ARG(path
);
1626 if (((ret
= git_index_remove(index
, path
, 0)) < 0 &&
1627 ret
!= GIT_ENOTFOUND
) ||
1628 ((ret
= index_conflict_to_reuc(index
, path
)) < 0 &&
1629 ret
!= GIT_ENOTFOUND
))
1632 if (ret
== GIT_ENOTFOUND
)
1638 int git_index__fill(git_index
*index
, const git_vector
*source_entries
)
1640 const git_index_entry
*source_entry
= NULL
;
1644 GIT_ASSERT_ARG(index
);
1646 if (!source_entries
->length
)
1649 if (git_vector_size_hint(&index
->entries
, source_entries
->length
) < 0 ||
1650 index_map_resize(index
->entries_map
, (size_t)(source_entries
->length
* 1.3),
1651 index
->ignore_case
) < 0)
1654 git_vector_foreach(source_entries
, i
, source_entry
) {
1655 git_index_entry
*entry
= NULL
;
1657 if ((error
= index_entry_dup(&entry
, index
, source_entry
)) < 0)
1660 index_entry_adjust_namemask(entry
, ((struct entry_internal
*)entry
)->pathlen
);
1661 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1662 entry
->mode
= git_index__create_mode(entry
->mode
);
1664 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0)
1667 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1674 git_vector_sort(&index
->entries
);
1680 int git_index_add(git_index
*index
, const git_index_entry
*source_entry
)
1682 git_index_entry
*entry
= NULL
;
1685 GIT_ASSERT_ARG(index
);
1686 GIT_ASSERT_ARG(source_entry
&& source_entry
->path
);
1688 if (!valid_filemode(source_entry
->mode
)) {
1689 git_error_set(GIT_ERROR_INDEX
, "invalid entry mode");
1693 if ((ret
= index_entry_dup(&entry
, index
, source_entry
)) < 0 ||
1694 (ret
= index_insert(index
, &entry
, 1, true, true, false)) < 0)
1697 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1701 int git_index_remove(git_index
*index
, const char *path
, int stage
)
1705 git_index_entry remove_key
= {{ 0 }};
1707 remove_key
.path
= path
;
1708 GIT_INDEX_ENTRY_STAGE_SET(&remove_key
, stage
);
1710 index_map_delete(index
->entries_map
, &remove_key
, index
->ignore_case
);
1712 if (index_find(&position
, index
, path
, 0, stage
) < 0) {
1714 GIT_ERROR_INDEX
, "index does not contain %s at stage %d", path
, stage
);
1715 error
= GIT_ENOTFOUND
;
1717 error
= index_remove_entry(index
, position
);
1723 int git_index_remove_directory(git_index
*index
, const char *dir
, int stage
)
1725 git_buf pfx
= GIT_BUF_INIT
;
1728 git_index_entry
*entry
;
1730 if (!(error
= git_buf_sets(&pfx
, dir
)) &&
1731 !(error
= git_path_to_dir(&pfx
)))
1732 index_find(&pos
, index
, pfx
.ptr
, pfx
.size
, GIT_INDEX_STAGE_ANY
);
1735 entry
= git_vector_get(&index
->entries
, pos
);
1736 if (!entry
|| git__prefixcmp(entry
->path
, pfx
.ptr
) != 0)
1739 if (GIT_INDEX_ENTRY_STAGE(entry
) != stage
) {
1744 error
= index_remove_entry(index
, pos
);
1746 /* removed entry at 'pos' so we don't need to increment */
1749 git_buf_dispose(&pfx
);
1754 int git_index_find_prefix(size_t *at_pos
, git_index
*index
, const char *prefix
)
1758 const git_index_entry
*entry
;
1760 index_find(&pos
, index
, prefix
, strlen(prefix
), GIT_INDEX_STAGE_ANY
);
1761 entry
= git_vector_get(&index
->entries
, pos
);
1762 if (!entry
|| git__prefixcmp(entry
->path
, prefix
) != 0)
1763 error
= GIT_ENOTFOUND
;
1765 if (!error
&& at_pos
)
1771 int git_index__find_pos(
1772 size_t *out
, git_index
*index
, const char *path
, size_t path_len
, int stage
)
1774 GIT_ASSERT_ARG(index
);
1775 GIT_ASSERT_ARG(path
);
1776 return index_find(out
, index
, path
, path_len
, stage
);
1779 int git_index_find(size_t *at_pos
, git_index
*index
, const char *path
)
1783 GIT_ASSERT_ARG(index
);
1784 GIT_ASSERT_ARG(path
);
1786 if (git_vector_bsearch2(
1787 &pos
, &index
->entries
, index
->entries_search_path
, path
) < 0) {
1788 git_error_set(GIT_ERROR_INDEX
, "index does not contain %s", path
);
1789 return GIT_ENOTFOUND
;
1792 /* Since our binary search only looked at path, we may be in the
1793 * middle of a list of stages.
1795 for (; pos
> 0; --pos
) {
1796 const git_index_entry
*prev
= git_vector_get(&index
->entries
, pos
- 1);
1798 if (index
->entries_cmp_path(prev
->path
, path
) != 0)
1808 int git_index_conflict_add(git_index
*index
,
1809 const git_index_entry
*ancestor_entry
,
1810 const git_index_entry
*our_entry
,
1811 const git_index_entry
*their_entry
)
1813 git_index_entry
*entries
[3] = { 0 };
1817 GIT_ASSERT_ARG(index
);
1819 if ((ancestor_entry
&&
1820 (ret
= index_entry_dup(&entries
[0], index
, ancestor_entry
)) < 0) ||
1822 (ret
= index_entry_dup(&entries
[1], index
, our_entry
)) < 0) ||
1824 (ret
= index_entry_dup(&entries
[2], index
, their_entry
)) < 0))
1827 /* Validate entries */
1828 for (i
= 0; i
< 3; i
++) {
1829 if (entries
[i
] && !valid_filemode(entries
[i
]->mode
)) {
1830 git_error_set(GIT_ERROR_INDEX
, "invalid filemode for stage %d entry",
1837 /* Remove existing index entries for each path */
1838 for (i
= 0; i
< 3; i
++) {
1839 if (entries
[i
] == NULL
)
1842 if ((ret
= git_index_remove(index
, entries
[i
]->path
, 0)) != 0) {
1843 if (ret
!= GIT_ENOTFOUND
)
1851 /* Add the conflict entries */
1852 for (i
= 0; i
< 3; i
++) {
1853 if (entries
[i
] == NULL
)
1856 /* Make sure stage is correct */
1857 GIT_INDEX_ENTRY_STAGE_SET(entries
[i
], i
+ 1);
1859 if ((ret
= index_insert(index
, &entries
[i
], 1, true, true, false)) < 0)
1862 entries
[i
] = NULL
; /* don't free if later entry fails */
1868 for (i
= 0; i
< 3; i
++) {
1869 if (entries
[i
] != NULL
)
1870 index_entry_free(entries
[i
]);
1876 static int index_conflict__get_byindex(
1877 const git_index_entry
**ancestor_out
,
1878 const git_index_entry
**our_out
,
1879 const git_index_entry
**their_out
,
1883 const git_index_entry
*conflict_entry
;
1884 const char *path
= NULL
;
1888 GIT_ASSERT_ARG(ancestor_out
);
1889 GIT_ASSERT_ARG(our_out
);
1890 GIT_ASSERT_ARG(their_out
);
1891 GIT_ASSERT_ARG(index
);
1893 *ancestor_out
= NULL
;
1897 for (count
= git_index_entrycount(index
); n
< count
; ++n
) {
1898 conflict_entry
= git_vector_get(&index
->entries
, n
);
1900 if (path
&& index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1903 stage
= GIT_INDEX_ENTRY_STAGE(conflict_entry
);
1904 path
= conflict_entry
->path
;
1908 *their_out
= conflict_entry
;
1912 *our_out
= conflict_entry
;
1916 *ancestor_out
= conflict_entry
;
1927 int git_index_conflict_get(
1928 const git_index_entry
**ancestor_out
,
1929 const git_index_entry
**our_out
,
1930 const git_index_entry
**their_out
,
1937 GIT_ASSERT_ARG(ancestor_out
);
1938 GIT_ASSERT_ARG(our_out
);
1939 GIT_ASSERT_ARG(their_out
);
1940 GIT_ASSERT_ARG(index
);
1941 GIT_ASSERT_ARG(path
);
1943 *ancestor_out
= NULL
;
1947 if (git_index_find(&pos
, index
, path
) < 0)
1948 return GIT_ENOTFOUND
;
1950 if ((len
= index_conflict__get_byindex(
1951 ancestor_out
, our_out
, their_out
, index
, pos
)) < 0)
1954 return GIT_ENOTFOUND
;
1959 static int index_conflict_remove(git_index
*index
, const char *path
)
1962 git_index_entry
*conflict_entry
;
1965 if (path
!= NULL
&& git_index_find(&pos
, index
, path
) < 0)
1966 return GIT_ENOTFOUND
;
1968 while ((conflict_entry
= git_vector_get(&index
->entries
, pos
)) != NULL
) {
1971 index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1974 if (GIT_INDEX_ENTRY_STAGE(conflict_entry
) == 0) {
1979 if ((error
= index_remove_entry(index
, pos
)) < 0)
1986 int git_index_conflict_remove(git_index
*index
, const char *path
)
1988 GIT_ASSERT_ARG(index
);
1989 GIT_ASSERT_ARG(path
);
1990 return index_conflict_remove(index
, path
);
1993 int git_index_conflict_cleanup(git_index
*index
)
1995 GIT_ASSERT_ARG(index
);
1996 return index_conflict_remove(index
, NULL
);
1999 int git_index_has_conflicts(const git_index
*index
)
2002 git_index_entry
*entry
;
2004 GIT_ASSERT_ARG(index
);
2006 git_vector_foreach(&index
->entries
, i
, entry
) {
2007 if (GIT_INDEX_ENTRY_STAGE(entry
) > 0)
2014 int git_index_iterator_new(
2015 git_index_iterator
**iterator_out
,
2018 git_index_iterator
*it
;
2021 GIT_ASSERT_ARG(iterator_out
);
2022 GIT_ASSERT_ARG(index
);
2024 it
= git__calloc(1, sizeof(git_index_iterator
));
2025 GIT_ERROR_CHECK_ALLOC(it
);
2027 if ((error
= git_index_snapshot_new(&it
->snap
, index
)) < 0) {
2038 int git_index_iterator_next(
2039 const git_index_entry
**out
,
2040 git_index_iterator
*it
)
2042 GIT_ASSERT_ARG(out
);
2045 if (it
->cur
>= git_vector_length(&it
->snap
))
2046 return GIT_ITEROVER
;
2048 *out
= (git_index_entry
*)git_vector_get(&it
->snap
, it
->cur
++);
2052 void git_index_iterator_free(git_index_iterator
*it
)
2057 git_index_snapshot_release(&it
->snap
, it
->index
);
2061 int git_index_conflict_iterator_new(
2062 git_index_conflict_iterator
**iterator_out
,
2065 git_index_conflict_iterator
*it
= NULL
;
2067 GIT_ASSERT_ARG(iterator_out
);
2068 GIT_ASSERT_ARG(index
);
2070 it
= git__calloc(1, sizeof(git_index_conflict_iterator
));
2071 GIT_ERROR_CHECK_ALLOC(it
);
2079 int git_index_conflict_next(
2080 const git_index_entry
**ancestor_out
,
2081 const git_index_entry
**our_out
,
2082 const git_index_entry
**their_out
,
2083 git_index_conflict_iterator
*iterator
)
2085 const git_index_entry
*entry
;
2088 GIT_ASSERT_ARG(ancestor_out
);
2089 GIT_ASSERT_ARG(our_out
);
2090 GIT_ASSERT_ARG(their_out
);
2091 GIT_ASSERT_ARG(iterator
);
2093 *ancestor_out
= NULL
;
2097 while (iterator
->cur
< iterator
->index
->entries
.length
) {
2098 entry
= git_index_get_byindex(iterator
->index
, iterator
->cur
);
2100 if (git_index_entry_is_conflict(entry
)) {
2101 if ((len
= index_conflict__get_byindex(
2106 iterator
->cur
)) < 0)
2109 iterator
->cur
+= len
;
2116 return GIT_ITEROVER
;
2119 void git_index_conflict_iterator_free(git_index_conflict_iterator
*iterator
)
2121 if (iterator
== NULL
)
2124 git__free(iterator
);
2127 size_t git_index_name_entrycount(git_index
*index
)
2129 GIT_ASSERT_ARG(index
);
2130 return index
->names
.length
;
2133 const git_index_name_entry
*git_index_name_get_byindex(
2134 git_index
*index
, size_t n
)
2136 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2138 git_vector_sort(&index
->names
);
2139 return git_vector_get(&index
->names
, n
);
2142 static void index_name_entry_free(git_index_name_entry
*ne
)
2146 git__free(ne
->ancestor
);
2147 git__free(ne
->ours
);
2148 git__free(ne
->theirs
);
2152 int git_index_name_add(git_index
*index
,
2153 const char *ancestor
, const char *ours
, const char *theirs
)
2155 git_index_name_entry
*conflict_name
;
2157 GIT_ASSERT_ARG((ancestor
&& ours
) || (ancestor
&& theirs
) || (ours
&& theirs
));
2159 conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2160 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2162 if ((ancestor
&& !(conflict_name
->ancestor
= git__strdup(ancestor
))) ||
2163 (ours
&& !(conflict_name
->ours
= git__strdup(ours
))) ||
2164 (theirs
&& !(conflict_name
->theirs
= git__strdup(theirs
))) ||
2165 git_vector_insert(&index
->names
, conflict_name
) < 0)
2167 index_name_entry_free(conflict_name
);
2175 int git_index_name_clear(git_index
*index
)
2178 git_index_name_entry
*conflict_name
;
2180 GIT_ASSERT_ARG(index
);
2182 git_vector_foreach(&index
->names
, i
, conflict_name
)
2183 index_name_entry_free(conflict_name
);
2185 git_vector_clear(&index
->names
);
2192 size_t git_index_reuc_entrycount(git_index
*index
)
2194 GIT_ASSERT_ARG(index
);
2195 return index
->reuc
.length
;
2198 static int index_reuc_on_dup(void **old
, void *new)
2200 index_entry_reuc_free(*old
);
2205 static int index_reuc_insert(
2207 git_index_reuc_entry
*reuc
)
2211 GIT_ASSERT_ARG(index
);
2212 GIT_ASSERT_ARG(reuc
&& reuc
->path
!= NULL
);
2213 GIT_ASSERT(git_vector_is_sorted(&index
->reuc
));
2215 res
= git_vector_insert_sorted(&index
->reuc
, reuc
, &index_reuc_on_dup
);
2218 return res
== GIT_EEXISTS
? 0 : res
;
2221 int git_index_reuc_add(git_index
*index
, const char *path
,
2222 int ancestor_mode
, const git_oid
*ancestor_oid
,
2223 int our_mode
, const git_oid
*our_oid
,
2224 int their_mode
, const git_oid
*their_oid
)
2226 git_index_reuc_entry
*reuc
= NULL
;
2229 GIT_ASSERT_ARG(index
);
2230 GIT_ASSERT_ARG(path
);
2232 if ((error
= index_entry_reuc_init(&reuc
, path
, ancestor_mode
,
2233 ancestor_oid
, our_mode
, our_oid
, their_mode
, their_oid
)) < 0 ||
2234 (error
= index_reuc_insert(index
, reuc
)) < 0)
2235 index_entry_reuc_free(reuc
);
2240 int git_index_reuc_find(size_t *at_pos
, git_index
*index
, const char *path
)
2242 return git_vector_bsearch2(at_pos
, &index
->reuc
, index
->reuc_search
, path
);
2245 const git_index_reuc_entry
*git_index_reuc_get_bypath(
2246 git_index
*index
, const char *path
)
2250 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2251 GIT_ASSERT_ARG_WITH_RETVAL(path
, NULL
);
2253 if (!index
->reuc
.length
)
2256 GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index
->reuc
), NULL
);
2258 if (git_index_reuc_find(&pos
, index
, path
) < 0)
2261 return git_vector_get(&index
->reuc
, pos
);
2264 const git_index_reuc_entry
*git_index_reuc_get_byindex(
2265 git_index
*index
, size_t n
)
2267 GIT_ASSERT_ARG_WITH_RETVAL(index
, NULL
);
2268 GIT_ASSERT_WITH_RETVAL(git_vector_is_sorted(&index
->reuc
), NULL
);
2270 return git_vector_get(&index
->reuc
, n
);
2273 int git_index_reuc_remove(git_index
*index
, size_t position
)
2276 git_index_reuc_entry
*reuc
;
2278 GIT_ASSERT_ARG(index
);
2279 GIT_ASSERT(git_vector_is_sorted(&index
->reuc
));
2281 reuc
= git_vector_get(&index
->reuc
, position
);
2282 error
= git_vector_remove(&index
->reuc
, position
);
2285 index_entry_reuc_free(reuc
);
2291 int git_index_reuc_clear(git_index
*index
)
2295 GIT_ASSERT_ARG(index
);
2297 for (i
= 0; i
< index
->reuc
.length
; ++i
)
2298 index_entry_reuc_free(git_atomic_swap(index
->reuc
.contents
[i
], NULL
));
2300 git_vector_clear(&index
->reuc
);
2307 static int index_error_invalid(const char *message
)
2309 git_error_set(GIT_ERROR_INDEX
, "invalid data in index - %s", message
);
2313 static int read_reuc(git_index
*index
, const char *buffer
, size_t size
)
2319 /* If called multiple times, the vector might already be initialized */
2320 if (index
->reuc
._alloc_size
== 0 &&
2321 git_vector_init(&index
->reuc
, 16, reuc_cmp
) < 0)
2325 git_index_reuc_entry
*lost
;
2327 len
= p_strnlen(buffer
, size
) + 1;
2329 return index_error_invalid("reading reuc entries");
2331 lost
= reuc_entry_alloc(buffer
);
2332 GIT_ERROR_CHECK_ALLOC(lost
);
2337 /* read 3 ASCII octal numbers for stage entries */
2338 for (i
= 0; i
< 3; i
++) {
2341 if (git__strntol64(&tmp
, buffer
, size
, &endptr
, 8) < 0 ||
2342 !endptr
|| endptr
== buffer
|| *endptr
||
2343 tmp
< 0 || tmp
> UINT32_MAX
) {
2344 index_entry_reuc_free(lost
);
2345 return index_error_invalid("reading reuc entry stage");
2348 lost
->mode
[i
] = (uint32_t)tmp
;
2350 len
= (endptr
+ 1) - buffer
;
2352 index_entry_reuc_free(lost
);
2353 return index_error_invalid("reading reuc entry stage");
2360 /* read up to 3 OIDs for stage entries */
2361 for (i
= 0; i
< 3; i
++) {
2365 index_entry_reuc_free(lost
);
2366 return index_error_invalid("reading reuc entry oid");
2369 git_oid_fromraw(&lost
->oid
[i
], (const unsigned char *) buffer
);
2374 /* entry was read successfully - insert into reuc vector */
2375 if (git_vector_insert(&index
->reuc
, lost
) < 0)
2379 /* entries are guaranteed to be sorted on-disk */
2380 git_vector_set_sorted(&index
->reuc
, true);
2386 static int read_conflict_names(git_index
*index
, const char *buffer
, size_t size
)
2390 /* This gets called multiple times, the vector might already be initialized */
2391 if (index
->names
._alloc_size
== 0 &&
2392 git_vector_init(&index
->names
, 16, conflict_name_cmp
) < 0)
2395 #define read_conflict_name(ptr) \
2396 len = p_strnlen(buffer, size) + 1; \
2398 index_error_invalid("reading conflict name entries"); \
2404 ptr = git__malloc(len); \
2405 GIT_ERROR_CHECK_ALLOC(ptr); \
2406 memcpy(ptr, buffer, len); \
2413 git_index_name_entry
*conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2414 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2416 read_conflict_name(conflict_name
->ancestor
);
2417 read_conflict_name(conflict_name
->ours
);
2418 read_conflict_name(conflict_name
->theirs
);
2420 if (git_vector_insert(&index
->names
, conflict_name
) < 0)
2426 git__free(conflict_name
->ancestor
);
2427 git__free(conflict_name
->ours
);
2428 git__free(conflict_name
->theirs
);
2429 git__free(conflict_name
);
2433 #undef read_conflict_name
2435 /* entries are guaranteed to be sorted on-disk */
2436 git_vector_set_sorted(&index
->names
, true);
2441 static size_t index_entry_size(size_t path_len
, size_t varint_len
, uint32_t flags
)
2444 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2445 return offsetof(struct entry_long
, path
) + path_len
+ 1 + varint_len
;
2447 return offsetof(struct entry_short
, path
) + path_len
+ 1 + varint_len
;
2449 #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
2450 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2451 return entry_size(struct entry_long
, path_len
);
2453 return entry_size(struct entry_short
, path_len
);
2458 static int read_entry(
2459 git_index_entry
**out
,
2466 size_t path_length
, entry_size
;
2467 const char *path_ptr
;
2468 struct entry_short source
;
2469 git_index_entry entry
= {{0}};
2470 bool compressed
= index
->version
>= INDEX_VERSION_NUMBER_COMP
;
2471 char *tmp_path
= NULL
;
2473 if (INDEX_FOOTER_SIZE
+ minimal_entry_size
> buffer_size
)
2476 /* buffer is not guaranteed to be aligned */
2477 memcpy(&source
, buffer
, sizeof(struct entry_short
));
2479 entry
.ctime
.seconds
= (git_time_t
)ntohl(source
.ctime
.seconds
);
2480 entry
.ctime
.nanoseconds
= ntohl(source
.ctime
.nanoseconds
);
2481 entry
.mtime
.seconds
= (git_time_t
)ntohl(source
.mtime
.seconds
);
2482 entry
.mtime
.nanoseconds
= ntohl(source
.mtime
.nanoseconds
);
2483 entry
.dev
= ntohl(source
.dev
);
2484 entry
.ino
= ntohl(source
.ino
);
2485 entry
.mode
= ntohl(source
.mode
);
2486 entry
.uid
= ntohl(source
.uid
);
2487 entry
.gid
= ntohl(source
.gid
);
2488 entry
.file_size
= ntohl(source
.file_size
);
2489 git_oid_cpy(&entry
.id
, &source
.oid
);
2490 entry
.flags
= ntohs(source
.flags
);
2492 if (entry
.flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2494 size_t flags_offset
;
2496 flags_offset
= offsetof(struct entry_long
, flags_extended
);
2497 memcpy(&flags_raw
, (const char *) buffer
+ flags_offset
,
2499 flags_raw
= ntohs(flags_raw
);
2501 memcpy(&entry
.flags_extended
, &flags_raw
, sizeof(flags_raw
));
2502 path_ptr
= (const char *) buffer
+ offsetof(struct entry_long
, path
);
2504 path_ptr
= (const char *) buffer
+ offsetof(struct entry_short
, path
);
2507 path_length
= entry
.flags
& GIT_INDEX_ENTRY_NAMEMASK
;
2509 /* if this is a very long string, we must find its
2510 * real length without overflowing */
2511 if (path_length
== 0xFFF) {
2512 const char *path_end
;
2514 path_end
= memchr(path_ptr
, '\0', buffer_size
);
2515 if (path_end
== NULL
)
2518 path_length
= path_end
- path_ptr
;
2521 entry_size
= index_entry_size(path_length
, 0, entry
.flags
);
2522 entry
.path
= (char *)path_ptr
;
2524 size_t varint_len
, last_len
, prefix_len
, suffix_len
, path_len
;
2525 uintmax_t strip_len
;
2527 strip_len
= git_decode_varint((const unsigned char *)path_ptr
, &varint_len
);
2528 last_len
= strlen(last
);
2530 if (varint_len
== 0 || last_len
< strip_len
)
2531 return index_error_invalid("incorrect prefix length");
2533 prefix_len
= last_len
- (size_t)strip_len
;
2534 suffix_len
= strlen(path_ptr
+ varint_len
);
2536 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, prefix_len
, suffix_len
);
2537 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, path_len
, 1);
2539 if (path_len
> GIT_PATH_MAX
)
2540 return index_error_invalid("unreasonable path length");
2542 tmp_path
= git__malloc(path_len
);
2543 GIT_ERROR_CHECK_ALLOC(tmp_path
);
2545 memcpy(tmp_path
, last
, prefix_len
);
2546 memcpy(tmp_path
+ prefix_len
, path_ptr
+ varint_len
, suffix_len
+ 1);
2547 entry_size
= index_entry_size(suffix_len
, varint_len
, entry
.flags
);
2548 entry
.path
= tmp_path
;
2551 if (entry_size
== 0)
2554 if (INDEX_FOOTER_SIZE
+ entry_size
> buffer_size
)
2557 if (index_entry_dup(out
, index
, &entry
) < 0) {
2558 git__free(tmp_path
);
2562 git__free(tmp_path
);
2563 *out_size
= entry_size
;
2567 static int read_header(struct index_header
*dest
, const void *buffer
)
2569 const struct index_header
*source
= buffer
;
2571 dest
->signature
= ntohl(source
->signature
);
2572 if (dest
->signature
!= INDEX_HEADER_SIG
)
2573 return index_error_invalid("incorrect header signature");
2575 dest
->version
= ntohl(source
->version
);
2576 if (dest
->version
< INDEX_VERSION_NUMBER_LB
||
2577 dest
->version
> INDEX_VERSION_NUMBER_UB
)
2578 return index_error_invalid("incorrect header version");
2580 dest
->entry_count
= ntohl(source
->entry_count
);
2584 static int read_extension(size_t *read_len
, git_index
*index
, const char *buffer
, size_t buffer_size
)
2586 struct index_extension dest
;
2589 /* buffer is not guaranteed to be aligned */
2590 memcpy(&dest
, buffer
, sizeof(struct index_extension
));
2591 dest
.extension_size
= ntohl(dest
.extension_size
);
2593 total_size
= dest
.extension_size
+ sizeof(struct index_extension
);
2595 if (dest
.extension_size
> total_size
||
2596 buffer_size
< total_size
||
2597 buffer_size
- total_size
< INDEX_FOOTER_SIZE
) {
2598 index_error_invalid("extension is truncated");
2602 /* optional extension */
2603 if (dest
.signature
[0] >= 'A' && dest
.signature
[0] <= 'Z') {
2605 if (memcmp(dest
.signature
, INDEX_EXT_TREECACHE_SIG
, 4) == 0) {
2606 if (git_tree_cache_read(&index
->tree
, buffer
+ 8, dest
.extension_size
, &index
->tree_pool
) < 0)
2608 } else if (memcmp(dest
.signature
, INDEX_EXT_UNMERGED_SIG
, 4) == 0) {
2609 if (read_reuc(index
, buffer
+ 8, dest
.extension_size
) < 0)
2611 } else if (memcmp(dest
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4) == 0) {
2612 if (read_conflict_names(index
, buffer
+ 8, dest
.extension_size
) < 0)
2615 /* else, unsupported extension. We cannot parse this, but we can skip
2616 * it by returning `total_size */
2618 /* we cannot handle non-ignorable extensions;
2619 * in fact they aren't even defined in the standard */
2620 git_error_set(GIT_ERROR_INDEX
, "unsupported mandatory extension: '%.4s'", dest
.signature
);
2624 *read_len
= total_size
;
2629 static int parse_index(git_index
*index
, const char *buffer
, size_t buffer_size
)
2633 struct index_header header
= { 0 };
2634 git_oid checksum_calculated
, checksum_expected
;
2635 const char *last
= NULL
;
2636 const char *empty
= "";
2638 #define seek_forward(_increase) { \
2639 if (_increase >= buffer_size) { \
2640 error = index_error_invalid("ran out of data while parsing"); \
2642 buffer += _increase; \
2643 buffer_size -= _increase;\
2646 if (buffer_size
< INDEX_HEADER_SIZE
+ INDEX_FOOTER_SIZE
)
2647 return index_error_invalid("insufficient buffer space");
2649 /* Precalculate the SHA1 of the files's contents -- we'll match it to
2650 * the provided SHA1 in the footer */
2651 git_hash_buf(&checksum_calculated
, buffer
, buffer_size
- INDEX_FOOTER_SIZE
);
2654 if ((error
= read_header(&header
, buffer
)) < 0)
2657 index
->version
= header
.version
;
2658 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2661 seek_forward(INDEX_HEADER_SIZE
);
2663 GIT_ASSERT(!index
->entries
.length
);
2665 if ((error
= index_map_resize(index
->entries_map
, header
.entry_count
, index
->ignore_case
)) < 0)
2668 /* Parse all the entries */
2669 for (i
= 0; i
< header
.entry_count
&& buffer_size
> INDEX_FOOTER_SIZE
; ++i
) {
2670 git_index_entry
*entry
= NULL
;
2673 if ((error
= read_entry(&entry
, &entry_size
, index
, buffer
, buffer_size
, last
)) < 0) {
2674 error
= index_error_invalid("invalid entry");
2678 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0) {
2679 index_entry_free(entry
);
2683 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0) {
2684 index_entry_free(entry
);
2689 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2692 seek_forward(entry_size
);
2695 if (i
!= header
.entry_count
) {
2696 error
= index_error_invalid("header entries changed while parsing");
2700 /* There's still space for some extensions! */
2701 while (buffer_size
> INDEX_FOOTER_SIZE
) {
2702 size_t extension_size
;
2704 if ((error
= read_extension(&extension_size
, index
, buffer
, buffer_size
)) < 0) {
2708 seek_forward(extension_size
);
2711 if (buffer_size
!= INDEX_FOOTER_SIZE
) {
2712 error
= index_error_invalid(
2713 "buffer size does not match index footer size");
2717 /* 160-bit SHA-1 over the content of the index file before this checksum. */
2718 git_oid_fromraw(&checksum_expected
, (const unsigned char *)buffer
);
2720 if (git_oid__cmp(&checksum_calculated
, &checksum_expected
) != 0) {
2721 error
= index_error_invalid(
2722 "calculated checksum does not match expected");
2726 git_oid_cpy(&index
->checksum
, &checksum_calculated
);
2730 /* Entries are stored case-sensitively on disk, so re-sort now if
2731 * in-memory index is supposed to be case-insensitive
2733 git_vector_set_sorted(&index
->entries
, !index
->ignore_case
);
2734 git_vector_sort(&index
->entries
);
2741 static bool is_index_extended(git_index
*index
)
2744 git_index_entry
*entry
;
2748 git_vector_foreach(&index
->entries
, i
, entry
) {
2749 entry
->flags
&= ~GIT_INDEX_ENTRY_EXTENDED
;
2750 if (entry
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
) {
2752 entry
->flags
|= GIT_INDEX_ENTRY_EXTENDED
;
2756 return (extended
> 0);
2759 static int write_disk_entry(git_filebuf
*file
, git_index_entry
*entry
, const char *last
)
2762 struct entry_short ondisk
;
2763 size_t path_len
, disk_size
;
2766 const char *path_start
= entry
->path
;
2767 size_t same_len
= 0;
2769 path_len
= ((struct entry_internal
*)entry
)->pathlen
;
2772 const char *last_c
= last
;
2774 while (*path_start
== *last_c
) {
2775 if (!*path_start
|| !*last_c
)
2781 path_len
-= same_len
;
2782 varint_len
= git_encode_varint(NULL
, 0, strlen(last
) - same_len
);
2785 disk_size
= index_entry_size(path_len
, varint_len
, entry
->flags
);
2787 if (git_filebuf_reserve(file
, &mem
, disk_size
) < 0)
2790 memset(mem
, 0x0, disk_size
);
2793 * Yes, we have to truncate.
2795 * The on-disk format for Index entries clearly defines
2796 * the time and size fields to be 4 bytes each -- so even if
2797 * we store these values with 8 bytes on-memory, they must
2798 * be truncated to 4 bytes before writing to disk.
2800 * In 2038 I will be either too dead or too rich to care about this
2802 ondisk
.ctime
.seconds
= htonl((uint32_t)entry
->ctime
.seconds
);
2803 ondisk
.mtime
.seconds
= htonl((uint32_t)entry
->mtime
.seconds
);
2804 ondisk
.ctime
.nanoseconds
= htonl(entry
->ctime
.nanoseconds
);
2805 ondisk
.mtime
.nanoseconds
= htonl(entry
->mtime
.nanoseconds
);
2806 ondisk
.dev
= htonl(entry
->dev
);
2807 ondisk
.ino
= htonl(entry
->ino
);
2808 ondisk
.mode
= htonl(entry
->mode
);
2809 ondisk
.uid
= htonl(entry
->uid
);
2810 ondisk
.gid
= htonl(entry
->gid
);
2811 ondisk
.file_size
= htonl((uint32_t)entry
->file_size
);
2813 git_oid_cpy(&ondisk
.oid
, &entry
->id
);
2815 ondisk
.flags
= htons(entry
->flags
);
2817 if (entry
->flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2818 const size_t path_offset
= offsetof(struct entry_long
, path
);
2819 struct entry_long ondisk_ext
;
2820 memcpy(&ondisk_ext
, &ondisk
, sizeof(struct entry_short
));
2821 ondisk_ext
.flags_extended
= htons(entry
->flags_extended
&
2822 GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
2823 memcpy(mem
, &ondisk_ext
, path_offset
);
2824 path
= (char *)mem
+ path_offset
;
2825 disk_size
-= path_offset
;
2827 const size_t path_offset
= offsetof(struct entry_short
, path
);
2828 memcpy(mem
, &ondisk
, path_offset
);
2829 path
= (char *)mem
+ path_offset
;
2830 disk_size
-= path_offset
;
2834 varint_len
= git_encode_varint((unsigned char *) path
,
2835 disk_size
, strlen(last
) - same_len
);
2836 GIT_ASSERT(varint_len
> 0);
2839 disk_size
-= varint_len
;
2842 * If using path compression, we are not allowed
2843 * to have additional trailing NULs.
2845 GIT_ASSERT(disk_size
== path_len
+ 1);
2848 * If no path compression is used, we do have
2849 * NULs as padding. As such, simply assert that
2850 * we have enough space left to write the path.
2852 GIT_ASSERT(disk_size
> path_len
);
2855 memcpy(path
, path_start
, path_len
+ 1);
2860 static int write_entries(git_index
*index
, git_filebuf
*file
)
2864 git_vector case_sorted
= GIT_VECTOR_INIT
, *entries
= NULL
;
2865 git_index_entry
*entry
;
2866 const char *last
= NULL
;
2868 /* If index->entries is sorted case-insensitively, then we need
2869 * to re-sort it case-sensitively before writing */
2870 if (index
->ignore_case
) {
2871 if ((error
= git_vector_dup(&case_sorted
, &index
->entries
, git_index_entry_cmp
)) < 0)
2874 git_vector_sort(&case_sorted
);
2875 entries
= &case_sorted
;
2877 entries
= &index
->entries
;
2880 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2883 git_vector_foreach(entries
, i
, entry
) {
2884 if ((error
= write_disk_entry(file
, entry
, last
)) < 0)
2886 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2891 git_vector_free(&case_sorted
);
2895 static int write_extension(git_filebuf
*file
, struct index_extension
*header
, git_buf
*data
)
2897 struct index_extension ondisk
;
2899 memset(&ondisk
, 0x0, sizeof(struct index_extension
));
2900 memcpy(&ondisk
, header
, 4);
2901 ondisk
.extension_size
= htonl(header
->extension_size
);
2903 git_filebuf_write(file
, &ondisk
, sizeof(struct index_extension
));
2904 return git_filebuf_write(file
, data
->ptr
, data
->size
);
2907 static int create_name_extension_data(git_buf
*name_buf
, git_index_name_entry
*conflict_name
)
2911 if (conflict_name
->ancestor
== NULL
)
2912 error
= git_buf_put(name_buf
, "\0", 1);
2914 error
= git_buf_put(name_buf
, conflict_name
->ancestor
, strlen(conflict_name
->ancestor
) + 1);
2919 if (conflict_name
->ours
== NULL
)
2920 error
= git_buf_put(name_buf
, "\0", 1);
2922 error
= git_buf_put(name_buf
, conflict_name
->ours
, strlen(conflict_name
->ours
) + 1);
2927 if (conflict_name
->theirs
== NULL
)
2928 error
= git_buf_put(name_buf
, "\0", 1);
2930 error
= git_buf_put(name_buf
, conflict_name
->theirs
, strlen(conflict_name
->theirs
) + 1);
2936 static int write_name_extension(git_index
*index
, git_filebuf
*file
)
2938 git_buf name_buf
= GIT_BUF_INIT
;
2939 git_vector
*out
= &index
->names
;
2940 git_index_name_entry
*conflict_name
;
2941 struct index_extension extension
;
2945 git_vector_foreach(out
, i
, conflict_name
) {
2946 if ((error
= create_name_extension_data(&name_buf
, conflict_name
)) < 0)
2950 memset(&extension
, 0x0, sizeof(struct index_extension
));
2951 memcpy(&extension
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4);
2952 extension
.extension_size
= (uint32_t)name_buf
.size
;
2954 error
= write_extension(file
, &extension
, &name_buf
);
2956 git_buf_dispose(&name_buf
);
2962 static int create_reuc_extension_data(git_buf
*reuc_buf
, git_index_reuc_entry
*reuc
)
2967 if ((error
= git_buf_put(reuc_buf
, reuc
->path
, strlen(reuc
->path
) + 1)) < 0)
2970 for (i
= 0; i
< 3; i
++) {
2971 if ((error
= git_buf_printf(reuc_buf
, "%o", reuc
->mode
[i
])) < 0 ||
2972 (error
= git_buf_put(reuc_buf
, "\0", 1)) < 0)
2976 for (i
= 0; i
< 3; i
++) {
2977 if (reuc
->mode
[i
] && (error
= git_buf_put(reuc_buf
, (char *)&reuc
->oid
[i
].id
, GIT_OID_RAWSZ
)) < 0)
2984 static int write_reuc_extension(git_index
*index
, git_filebuf
*file
)
2986 git_buf reuc_buf
= GIT_BUF_INIT
;
2987 git_vector
*out
= &index
->reuc
;
2988 git_index_reuc_entry
*reuc
;
2989 struct index_extension extension
;
2993 git_vector_foreach(out
, i
, reuc
) {
2994 if ((error
= create_reuc_extension_data(&reuc_buf
, reuc
)) < 0)
2998 memset(&extension
, 0x0, sizeof(struct index_extension
));
2999 memcpy(&extension
.signature
, INDEX_EXT_UNMERGED_SIG
, 4);
3000 extension
.extension_size
= (uint32_t)reuc_buf
.size
;
3002 error
= write_extension(file
, &extension
, &reuc_buf
);
3004 git_buf_dispose(&reuc_buf
);
3010 static int write_tree_extension(git_index
*index
, git_filebuf
*file
)
3012 struct index_extension extension
;
3013 git_buf buf
= GIT_BUF_INIT
;
3016 if (index
->tree
== NULL
)
3019 if ((error
= git_tree_cache_write(&buf
, index
->tree
)) < 0)
3022 memset(&extension
, 0x0, sizeof(struct index_extension
));
3023 memcpy(&extension
.signature
, INDEX_EXT_TREECACHE_SIG
, 4);
3024 extension
.extension_size
= (uint32_t)buf
.size
;
3026 error
= write_extension(file
, &extension
, &buf
);
3028 git_buf_dispose(&buf
);
3033 static void clear_uptodate(git_index
*index
)
3035 git_index_entry
*entry
;
3038 git_vector_foreach(&index
->entries
, i
, entry
)
3039 entry
->flags_extended
&= ~GIT_INDEX_ENTRY_UPTODATE
;
3042 static int write_index(git_oid
*checksum
, git_index
*index
, git_filebuf
*file
)
3045 struct index_header header
;
3047 uint32_t index_version_number
;
3049 GIT_ASSERT_ARG(index
);
3050 GIT_ASSERT_ARG(file
);
3052 if (index
->version
<= INDEX_VERSION_NUMBER_EXT
) {
3053 is_extended
= is_index_extended(index
);
3054 index_version_number
= is_extended
? INDEX_VERSION_NUMBER_EXT
: INDEX_VERSION_NUMBER_LB
;
3056 index_version_number
= index
->version
;
3059 header
.signature
= htonl(INDEX_HEADER_SIG
);
3060 header
.version
= htonl(index_version_number
);
3061 header
.entry_count
= htonl((uint32_t)index
->entries
.length
);
3063 if (git_filebuf_write(file
, &header
, sizeof(struct index_header
)) < 0)
3066 if (write_entries(index
, file
) < 0)
3069 /* write the tree cache extension */
3070 if (index
->tree
!= NULL
&& write_tree_extension(index
, file
) < 0)
3073 /* write the rename conflict extension */
3074 if (index
->names
.length
> 0 && write_name_extension(index
, file
) < 0)
3077 /* write the reuc extension */
3078 if (index
->reuc
.length
> 0 && write_reuc_extension(index
, file
) < 0)
3081 /* get out the hash for all the contents we've appended to the file */
3082 git_filebuf_hash(&hash_final
, file
);
3083 git_oid_cpy(checksum
, &hash_final
);
3085 /* write it at the end of the file */
3086 if (git_filebuf_write(file
, hash_final
.id
, GIT_OID_RAWSZ
) < 0)
3089 /* file entries are no longer up to date */
3090 clear_uptodate(index
);
3095 int git_index_entry_stage(const git_index_entry
*entry
)
3097 return GIT_INDEX_ENTRY_STAGE(entry
);
3100 int git_index_entry_is_conflict(const git_index_entry
*entry
)
3102 return (GIT_INDEX_ENTRY_STAGE(entry
) > 0);
3105 typedef struct read_tree_data
{
3107 git_vector
*old_entries
;
3108 git_vector
*new_entries
;
3109 git_vector_cmp entry_cmp
;
3110 git_tree_cache
*tree
;
3113 static int read_tree_cb(
3114 const char *root
, const git_tree_entry
*tentry
, void *payload
)
3116 read_tree_data
*data
= payload
;
3117 git_index_entry
*entry
= NULL
, *old_entry
;
3118 git_buf path
= GIT_BUF_INIT
;
3121 if (git_tree_entry__is_tree(tentry
))
3124 if (git_buf_joinpath(&path
, root
, tentry
->filename
) < 0)
3127 if (index_entry_create(&entry
, INDEX_OWNER(data
->index
), path
.ptr
, NULL
, false) < 0)
3130 entry
->mode
= tentry
->attr
;
3131 git_oid_cpy(&entry
->id
, git_tree_entry_id(tentry
));
3133 /* look for corresponding old entry and copy data to new entry */
3134 if (data
->old_entries
!= NULL
&&
3135 !index_find_in_entries(
3136 &pos
, data
->old_entries
, data
->entry_cmp
, path
.ptr
, 0, 0) &&
3137 (old_entry
= git_vector_get(data
->old_entries
, pos
)) != NULL
&&
3138 entry
->mode
== old_entry
->mode
&&
3139 git_oid_equal(&entry
->id
, &old_entry
->id
))
3141 index_entry_cpy(entry
, old_entry
);
3142 entry
->flags_extended
= 0;
3145 index_entry_adjust_namemask(entry
, path
.size
);
3146 git_buf_dispose(&path
);
3148 if (git_vector_insert(data
->new_entries
, entry
) < 0) {
3149 index_entry_free(entry
);
3156 int git_index_read_tree(git_index
*index
, const git_tree
*tree
)
3159 git_vector entries
= GIT_VECTOR_INIT
;
3160 git_idxmap
*entries_map
;
3161 read_tree_data data
;
3165 if (git_idxmap_new(&entries_map
) < 0)
3168 git_vector_set_cmp(&entries
, index
->entries
._cmp
); /* match sort */
3171 data
.old_entries
= &index
->entries
;
3172 data
.new_entries
= &entries
;
3173 data
.entry_cmp
= index
->entries_search
;
3176 git_pool_clear(&index
->tree_pool
);
3178 git_vector_sort(&index
->entries
);
3180 if ((error
= git_tree_walk(tree
, GIT_TREEWALK_POST
, read_tree_cb
, &data
)) < 0)
3183 if ((error
= index_map_resize(entries_map
, entries
.length
, index
->ignore_case
)) < 0)
3186 git_vector_foreach(&entries
, i
, e
) {
3187 if ((error
= index_map_set(entries_map
, e
, index
->ignore_case
)) < 0) {
3188 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry into map");
3195 git_vector_sort(&entries
);
3197 if ((error
= git_index_clear(index
)) < 0) {
3198 /* well, this isn't good */;
3200 git_vector_swap(&entries
, &index
->entries
);
3201 entries_map
= git_atomic_swap(index
->entries_map
, entries_map
);
3207 git_vector_free(&entries
);
3208 git_idxmap_free(entries_map
);
3212 error
= git_tree_cache_read_tree(&index
->tree
, tree
, &index
->tree_pool
);
3217 static int git_index_read_iterator(
3219 git_iterator
*new_iterator
,
3220 size_t new_length_hint
)
3222 git_vector new_entries
= GIT_VECTOR_INIT
,
3223 remove_entries
= GIT_VECTOR_INIT
;
3224 git_idxmap
*new_entries_map
= NULL
;
3225 git_iterator
*index_iterator
= NULL
;
3226 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3227 const git_index_entry
*old_entry
, *new_entry
;
3228 git_index_entry
*entry
;
3232 GIT_ASSERT((new_iterator
->flags
& GIT_ITERATOR_DONT_IGNORE_CASE
));
3234 if ((error
= git_vector_init(&new_entries
, new_length_hint
, index
->entries
._cmp
)) < 0 ||
3235 (error
= git_vector_init(&remove_entries
, index
->entries
.length
, NULL
)) < 0 ||
3236 (error
= git_idxmap_new(&new_entries_map
)) < 0)
3239 if (new_length_hint
&& (error
= index_map_resize(new_entries_map
, new_length_hint
,
3240 index
->ignore_case
)) < 0)
3243 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3244 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3246 if ((error
= git_iterator_for_index(&index_iterator
,
3247 git_index_owner(index
), index
, &opts
)) < 0 ||
3248 ((error
= git_iterator_current(&old_entry
, index_iterator
)) < 0 &&
3249 error
!= GIT_ITEROVER
) ||
3250 ((error
= git_iterator_current(&new_entry
, new_iterator
)) < 0 &&
3251 error
!= GIT_ITEROVER
))
3258 *remove_entry
= NULL
;
3263 if (old_entry
&& new_entry
)
3264 diff
= git_index_entry_cmp(old_entry
, new_entry
);
3265 else if (!old_entry
&& new_entry
)
3267 else if (old_entry
&& !new_entry
)
3273 remove_entry
= (git_index_entry
*)old_entry
;
3274 } else if (diff
> 0) {
3275 dup_entry
= (git_index_entry
*)new_entry
;
3277 /* Path and stage are equal, if the OID is equal, keep it to
3278 * keep the stat cache data.
3280 if (git_oid_equal(&old_entry
->id
, &new_entry
->id
) &&
3281 old_entry
->mode
== new_entry
->mode
) {
3282 add_entry
= (git_index_entry
*)old_entry
;
3284 dup_entry
= (git_index_entry
*)new_entry
;
3285 remove_entry
= (git_index_entry
*)old_entry
;
3290 if ((error
= index_entry_dup_nocache(&add_entry
, index
, dup_entry
)) < 0)
3293 index_entry_adjust_namemask(add_entry
,
3294 ((struct entry_internal
*)add_entry
)->pathlen
);
3297 /* invalidate this path in the tree cache if this is new (to
3298 * invalidate the parent trees)
3300 if (dup_entry
&& !remove_entry
&& index
->tree
)
3301 git_tree_cache_invalidate_path(index
->tree
, dup_entry
->path
);
3304 if ((error
= git_vector_insert(&new_entries
, add_entry
)) == 0)
3305 error
= index_map_set(new_entries_map
, add_entry
,
3306 index
->ignore_case
);
3309 if (remove_entry
&& error
>= 0)
3310 error
= git_vector_insert(&remove_entries
, remove_entry
);
3313 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry");
3318 if ((error
= git_iterator_advance(&old_entry
, index_iterator
)) < 0 &&
3319 error
!= GIT_ITEROVER
)
3324 if ((error
= git_iterator_advance(&new_entry
, new_iterator
)) < 0 &&
3325 error
!= GIT_ITEROVER
)
3330 if ((error
= git_index_name_clear(index
)) < 0 ||
3331 (error
= git_index_reuc_clear(index
)) < 0)
3334 git_vector_swap(&new_entries
, &index
->entries
);
3335 new_entries_map
= git_atomic_swap(index
->entries_map
, new_entries_map
);
3337 git_vector_foreach(&remove_entries
, i
, entry
) {
3339 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
3341 index_entry_free(entry
);
3344 clear_uptodate(index
);
3350 git_idxmap_free(new_entries_map
);
3351 git_vector_free(&new_entries
);
3352 git_vector_free(&remove_entries
);
3353 git_iterator_free(index_iterator
);
3357 int git_index_read_index(
3359 const git_index
*new_index
)
3361 git_iterator
*new_iterator
= NULL
;
3362 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3365 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3366 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3368 if ((error
= git_iterator_for_index(&new_iterator
,
3369 git_index_owner(new_index
), (git_index
*)new_index
, &opts
)) < 0 ||
3370 (error
= git_index_read_iterator(index
, new_iterator
,
3371 new_index
->entries
.length
)) < 0)
3375 git_iterator_free(new_iterator
);
3379 git_repository
*git_index_owner(const git_index
*index
)
3381 return INDEX_OWNER(index
);
3385 INDEX_ACTION_NONE
= 0,
3386 INDEX_ACTION_UPDATE
= 1,
3387 INDEX_ACTION_REMOVE
= 2,
3388 INDEX_ACTION_ADDALL
= 3,
3391 int git_index_add_all(
3393 const git_strarray
*paths
,
3395 git_index_matched_path_cb cb
,
3399 git_repository
*repo
;
3400 git_iterator
*wditer
= NULL
;
3402 bool no_fnmatch
= (flags
& GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
) != 0;
3404 GIT_ASSERT_ARG(index
);
3406 repo
= INDEX_OWNER(index
);
3407 if ((error
= git_repository__ensure_not_bare(repo
, "index add all")) < 0)
3410 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3413 /* optionally check that pathspec doesn't mention any ignored files */
3414 if ((flags
& GIT_INDEX_ADD_CHECK_PATHSPEC
) != 0 &&
3415 (flags
& GIT_INDEX_ADD_FORCE
) == 0 &&
3416 (error
= git_ignore__check_pathspec_for_exact_ignores(
3417 repo
, &ps
.pathspec
, no_fnmatch
)) < 0)
3420 error
= index_apply_to_wd_diff(index
, INDEX_ACTION_ADDALL
, paths
, flags
, cb
, payload
);
3423 git_error_set_after_callback(error
);
3426 git_iterator_free(wditer
);
3427 git_pathspec__clear(&ps
);
3432 struct foreach_diff_data
{
3434 const git_pathspec
*pathspec
;
3436 git_index_matched_path_cb cb
;
3440 static int apply_each_file(const git_diff_delta
*delta
, float progress
, void *payload
)
3442 struct foreach_diff_data
*data
= payload
;
3443 const char *match
, *path
;
3446 GIT_UNUSED(progress
);
3448 path
= delta
->old_file
.path
;
3450 /* We only want those which match the pathspecs */
3451 if (!git_pathspec__match(
3452 &data
->pathspec
->pathspec
, path
, false, (bool)data
->index
->ignore_case
,
3457 error
= data
->cb(path
, match
, data
->payload
);
3459 if (error
> 0) /* skip this entry */
3461 if (error
< 0) /* actual error */
3464 /* If the workdir item does not exist, remove it from the index. */
3465 if ((delta
->new_file
.flags
& GIT_DIFF_FLAG_EXISTS
) == 0)
3466 error
= git_index_remove_bypath(data
->index
, path
);
3468 error
= git_index_add_bypath(data
->index
, delta
->new_file
.path
);
3473 static int index_apply_to_wd_diff(git_index
*index
, int action
, const git_strarray
*paths
,
3475 git_index_matched_path_cb cb
, void *payload
)
3480 git_repository
*repo
;
3481 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
3482 struct foreach_diff_data data
= {
3490 GIT_ASSERT_ARG(index
);
3491 GIT_ASSERT_ARG(action
== INDEX_ACTION_UPDATE
|| action
== INDEX_ACTION_ADDALL
);
3493 repo
= INDEX_OWNER(index
);
3496 return create_index_error(-1,
3497 "cannot run update; the index is not backed up by a repository.");
3501 * We do the matching ourselves intead of passing the list to
3502 * diff because we want to tell the callback which one
3503 * matched, which we do not know if we ask diff to filter for us.
3505 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3508 opts
.flags
= GIT_DIFF_INCLUDE_TYPECHANGE
;
3509 if (action
== INDEX_ACTION_ADDALL
) {
3510 opts
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
|
3511 GIT_DIFF_RECURSE_UNTRACKED_DIRS
;
3513 if (flags
== GIT_INDEX_ADD_FORCE
)
3514 opts
.flags
|= GIT_DIFF_INCLUDE_IGNORED
;
3517 if ((error
= git_diff_index_to_workdir(&diff
, repo
, index
, &opts
)) < 0)
3520 data
.pathspec
= &ps
;
3521 error
= git_diff_foreach(diff
, apply_each_file
, NULL
, NULL
, NULL
, &data
);
3522 git_diff_free(diff
);
3524 if (error
) /* make sure error is set if callback stopped iteration */
3525 git_error_set_after_callback(error
);
3528 git_pathspec__clear(&ps
);
3532 static int index_apply_to_all(
3535 const git_strarray
*paths
,
3536 git_index_matched_path_cb cb
,
3543 git_buf path
= GIT_BUF_INIT
;
3545 GIT_ASSERT_ARG(index
);
3547 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3550 git_vector_sort(&index
->entries
);
3552 for (i
= 0; !error
&& i
< index
->entries
.length
; ++i
) {
3553 git_index_entry
*entry
= git_vector_get(&index
->entries
, i
);
3555 /* check if path actually matches */
3556 if (!git_pathspec__match(
3557 &ps
.pathspec
, entry
->path
, false, (bool)index
->ignore_case
,
3561 /* issue notification callback if requested */
3562 if (cb
&& (error
= cb(entry
->path
, match
, payload
)) != 0) {
3563 if (error
> 0) { /* return > 0 means skip this one */
3567 if (error
< 0) /* return < 0 means abort */
3571 /* index manipulation may alter entry, so don't depend on it */
3572 if ((error
= git_buf_sets(&path
, entry
->path
)) < 0)
3576 case INDEX_ACTION_NONE
:
3578 case INDEX_ACTION_UPDATE
:
3579 error
= git_index_add_bypath(index
, path
.ptr
);
3581 if (error
== GIT_ENOTFOUND
) {
3584 error
= git_index_remove_bypath(index
, path
.ptr
);
3586 if (!error
) /* back up foreach if we removed this */
3590 case INDEX_ACTION_REMOVE
:
3591 if (!(error
= git_index_remove_bypath(index
, path
.ptr
)))
3592 i
--; /* back up foreach if we removed this */
3595 git_error_set(GIT_ERROR_INVALID
, "unknown index action %d", action
);
3601 git_buf_dispose(&path
);
3602 git_pathspec__clear(&ps
);
3607 int git_index_remove_all(
3609 const git_strarray
*pathspec
,
3610 git_index_matched_path_cb cb
,
3613 int error
= index_apply_to_all(
3614 index
, INDEX_ACTION_REMOVE
, pathspec
, cb
, payload
);
3616 if (error
) /* make sure error is set if callback stopped iteration */
3617 git_error_set_after_callback(error
);
3622 int git_index_update_all(
3624 const git_strarray
*pathspec
,
3625 git_index_matched_path_cb cb
,
3628 int error
= index_apply_to_wd_diff(index
, INDEX_ACTION_UPDATE
, pathspec
, 0, cb
, payload
);
3629 if (error
) /* make sure error is set if callback stopped iteration */
3630 git_error_set_after_callback(error
);
3635 int git_index_snapshot_new(git_vector
*snap
, git_index
*index
)
3639 GIT_REFCOUNT_INC(index
);
3641 git_atomic32_inc(&index
->readers
);
3642 git_vector_sort(&index
->entries
);
3644 error
= git_vector_dup(snap
, &index
->entries
, index
->entries
._cmp
);
3647 git_index_snapshot_release(snap
, index
);
3652 void git_index_snapshot_release(git_vector
*snap
, git_index
*index
)
3654 git_vector_free(snap
);
3656 git_atomic32_dec(&index
->readers
);
3658 git_index_free(index
);
3661 int git_index_snapshot_find(
3662 size_t *out
, git_vector
*entries
, git_vector_cmp entry_srch
,
3663 const char *path
, size_t path_len
, int stage
)
3665 return index_find_in_entries(out
, entries
, entry_srch
, path
, path_len
, stage
);
3668 int git_indexwriter_init(
3669 git_indexwriter
*writer
,
3674 GIT_REFCOUNT_INC(index
);
3676 writer
->index
= index
;
3678 if (!index
->index_file_path
)
3679 return create_index_error(-1,
3680 "failed to write index: The index is in-memory only");
3682 if ((error
= git_filebuf_open(
3683 &writer
->file
, index
->index_file_path
, GIT_FILEBUF_HASH_CONTENTS
, GIT_INDEX_FILE_MODE
)) < 0) {
3685 if (error
== GIT_ELOCKED
)
3686 git_error_set(GIT_ERROR_INDEX
, "the index is locked; this might be due to a concurrent or crashed process");
3691 writer
->should_write
= 1;
3696 int git_indexwriter_init_for_operation(
3697 git_indexwriter
*writer
,
3698 git_repository
*repo
,
3699 unsigned int *checkout_strategy
)
3704 if ((error
= git_repository_index__weakptr(&index
, repo
)) < 0 ||
3705 (error
= git_indexwriter_init(writer
, index
)) < 0)
3708 writer
->should_write
= (*checkout_strategy
& GIT_CHECKOUT_DONT_WRITE_INDEX
) == 0;
3709 *checkout_strategy
|= GIT_CHECKOUT_DONT_WRITE_INDEX
;
3714 int git_indexwriter_commit(git_indexwriter
*writer
)
3717 git_oid checksum
= {{ 0 }};
3719 if (!writer
->should_write
)
3722 git_vector_sort(&writer
->index
->entries
);
3723 git_vector_sort(&writer
->index
->reuc
);
3725 if ((error
= write_index(&checksum
, writer
->index
, &writer
->file
)) < 0) {
3726 git_indexwriter_cleanup(writer
);
3730 if ((error
= git_filebuf_commit(&writer
->file
)) < 0)
3733 if ((error
= git_futils_filestamp_check(
3734 &writer
->index
->stamp
, writer
->index
->index_file_path
)) < 0) {
3735 git_error_set(GIT_ERROR_OS
, "could not read index timestamp");
3739 writer
->index
->dirty
= 0;
3740 writer
->index
->on_disk
= 1;
3741 git_oid_cpy(&writer
->index
->checksum
, &checksum
);
3743 git_index_free(writer
->index
);
3744 writer
->index
= NULL
;
3749 void git_indexwriter_cleanup(git_indexwriter
*writer
)
3751 git_filebuf_cleanup(&writer
->file
);
3753 git_index_free(writer
->index
);
3754 writer
->index
= NULL
;
3757 /* Deprecated functions */
3759 #ifndef GIT_DEPRECATE_HARD
3760 int git_index_add_frombuffer(
3761 git_index
*index
, const git_index_entry
*source_entry
,
3762 const void *buffer
, size_t len
)
3764 return git_index_add_from_buffer(index
, source_entry
, buffer
, len
);