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
)
411 index
= git__calloc(1, sizeof(git_index
));
412 GIT_ERROR_CHECK_ALLOC(index
);
414 git_pool_init(&index
->tree_pool
, 1);
416 if (index_path
!= NULL
) {
417 index
->index_file_path
= git__strdup(index_path
);
418 if (!index
->index_file_path
)
421 /* Check if index file is stored on disk already */
422 if (git_path_exists(index
->index_file_path
) == true)
426 if (git_vector_init(&index
->entries
, 32, git_index_entry_cmp
) < 0 ||
427 git_idxmap_new(&index
->entries_map
) < 0 ||
428 git_vector_init(&index
->names
, 8, conflict_name_cmp
) < 0 ||
429 git_vector_init(&index
->reuc
, 8, reuc_cmp
) < 0 ||
430 git_vector_init(&index
->deleted
, 8, git_index_entry_cmp
) < 0)
433 index
->entries_cmp_path
= git__strcmp_cb
;
434 index
->entries_search
= git_index_entry_srch
;
435 index
->entries_search_path
= index_entry_srch_path
;
436 index
->reuc_search
= reuc_srch
;
437 index
->version
= INDEX_VERSION_NUMBER_DEFAULT
;
439 if (index_path
!= NULL
&& (error
= git_index_read(index
, true)) < 0)
443 GIT_REFCOUNT_INC(index
);
448 git_pool_clear(&index
->tree_pool
);
449 git_index_free(index
);
453 int git_index_new(git_index
**out
)
455 return git_index_open(out
, NULL
);
458 static void index_free(git_index
*index
)
460 /* index iterators increment the refcount of the index, so if we
461 * get here then there should be no outstanding iterators.
463 assert(!git_atomic_get(&index
->readers
));
465 git_index_clear(index
);
466 git_idxmap_free(index
->entries_map
);
467 git_vector_free(&index
->entries
);
468 git_vector_free(&index
->names
);
469 git_vector_free(&index
->reuc
);
470 git_vector_free(&index
->deleted
);
472 git__free(index
->index_file_path
);
474 git__memzero(index
, sizeof(*index
));
478 void git_index_free(git_index
*index
)
483 GIT_REFCOUNT_DEC(index
, index_free
);
486 /* call with locked index */
487 static void index_free_deleted(git_index
*index
)
489 int readers
= (int)git_atomic_get(&index
->readers
);
492 if (readers
> 0 || !index
->deleted
.length
)
495 for (i
= 0; i
< index
->deleted
.length
; ++i
) {
496 git_index_entry
*ie
= git__swap(index
->deleted
.contents
[i
], NULL
);
497 index_entry_free(ie
);
500 git_vector_clear(&index
->deleted
);
503 /* call with locked index */
504 static int index_remove_entry(git_index
*index
, size_t pos
)
507 git_index_entry
*entry
= git_vector_get(&index
->entries
, pos
);
510 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
511 index_map_delete(index
->entries_map
, entry
, index
->ignore_case
);
514 error
= git_vector_remove(&index
->entries
, pos
);
517 if (git_atomic_get(&index
->readers
) > 0) {
518 error
= git_vector_insert(&index
->deleted
, entry
);
520 index_entry_free(entry
);
529 int git_index_clear(git_index
*index
)
537 git_pool_clear(&index
->tree_pool
);
539 git_idxmap_clear(index
->entries_map
);
540 while (!error
&& index
->entries
.length
> 0)
541 error
= index_remove_entry(index
, index
->entries
.length
- 1);
546 index_free_deleted(index
);
548 if ((error
= git_index_name_clear(index
)) < 0 ||
549 (error
= git_index_reuc_clear(index
)) < 0)
552 git_futils_filestamp_set(&index
->stamp
, NULL
);
558 static int create_index_error(int error
, const char *msg
)
560 git_error_set_str(GIT_ERROR_INDEX
, msg
);
564 int git_index_set_caps(git_index
*index
, int caps
)
566 unsigned int old_ignore_case
;
570 old_ignore_case
= index
->ignore_case
;
572 if (caps
== GIT_INDEX_CAPABILITY_FROM_OWNER
) {
573 git_repository
*repo
= INDEX_OWNER(index
);
577 return create_index_error(
578 -1, "cannot access repository to set index caps");
580 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_IGNORECASE
))
581 index
->ignore_case
= (val
!= 0);
582 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_FILEMODE
))
583 index
->distrust_filemode
= (val
== 0);
584 if (!git_repository__configmap_lookup(&val
, repo
, GIT_CONFIGMAP_SYMLINKS
))
585 index
->no_symlinks
= (val
== 0);
588 index
->ignore_case
= ((caps
& GIT_INDEX_CAPABILITY_IGNORE_CASE
) != 0);
589 index
->distrust_filemode
= ((caps
& GIT_INDEX_CAPABILITY_NO_FILEMODE
) != 0);
590 index
->no_symlinks
= ((caps
& GIT_INDEX_CAPABILITY_NO_SYMLINKS
) != 0);
593 if (old_ignore_case
!= index
->ignore_case
) {
594 git_index__set_ignore_case(index
, (bool)index
->ignore_case
);
600 int git_index_caps(const git_index
*index
)
602 return ((index
->ignore_case
? GIT_INDEX_CAPABILITY_IGNORE_CASE
: 0) |
603 (index
->distrust_filemode
? GIT_INDEX_CAPABILITY_NO_FILEMODE
: 0) |
604 (index
->no_symlinks
? GIT_INDEX_CAPABILITY_NO_SYMLINKS
: 0));
607 const git_oid
*git_index_checksum(git_index
*index
)
609 return &index
->checksum
;
613 * Returns 1 for changed, 0 for not changed and <0 for errors
615 static int compare_checksum(git_index
*index
)
619 git_oid checksum
= {{ 0 }};
621 if ((fd
= p_open(index
->index_file_path
, O_RDONLY
)) < 0)
624 if (p_lseek(fd
, -20, SEEK_END
) < 0) {
626 git_error_set(GIT_ERROR_OS
, "failed to seek to end of file");
630 bytes_read
= p_read(fd
, &checksum
, GIT_OID_RAWSZ
);
636 return !!git_oid_cmp(&checksum
, &index
->checksum
);
639 int git_index_read(git_index
*index
, int force
)
641 int error
= 0, updated
;
642 git_buf buffer
= GIT_BUF_INIT
;
643 git_futils_filestamp stamp
= index
->stamp
;
645 if (!index
->index_file_path
)
646 return create_index_error(-1,
647 "failed to read index: The index is in-memory only");
649 index
->on_disk
= git_path_exists(index
->index_file_path
);
651 if (!index
->on_disk
) {
652 if (force
&& (error
= git_index_clear(index
)) < 0)
659 if ((updated
= git_futils_filestamp_check(&stamp
, index
->index_file_path
) < 0) ||
660 ((updated
= compare_checksum(index
)) < 0)) {
663 "failed to read index: '%s' no longer exists",
664 index
->index_file_path
);
668 if (!updated
&& !force
)
671 error
= git_futils_readbuffer(&buffer
, index
->index_file_path
);
676 git_pool_clear(&index
->tree_pool
);
678 error
= git_index_clear(index
);
681 error
= parse_index(index
, buffer
.ptr
, buffer
.size
);
684 git_futils_filestamp_set(&index
->stamp
, &stamp
);
688 git_buf_dispose(&buffer
);
692 int git_index_read_safely(git_index
*index
)
694 if (git_index__enforce_unsaved_safety
&& index
->dirty
) {
695 git_error_set(GIT_ERROR_INDEX
,
696 "the index has unsaved changes that would be overwritten by this operation");
697 return GIT_EINDEXDIRTY
;
700 return git_index_read(index
, false);
703 int git_index__changed_relative_to(
704 git_index
*index
, const git_oid
*checksum
)
706 /* attempt to update index (ignoring errors) */
707 if (git_index_read(index
, false) < 0)
710 return !!git_oid_cmp(&index
->checksum
, checksum
);
713 static bool is_racy_entry(git_index
*index
, const git_index_entry
*entry
)
715 /* Git special-cases submodules in the check */
716 if (S_ISGITLINK(entry
->mode
))
719 return git_index_entry_newer_than_index(entry
, index
);
723 * Force the next diff to take a look at those entries which have the
724 * same timestamp as the current index.
726 static int truncate_racily_clean(git_index
*index
)
730 git_index_entry
*entry
;
731 git_diff_options diff_opts
= GIT_DIFF_OPTIONS_INIT
;
732 git_diff
*diff
= NULL
;
733 git_vector paths
= GIT_VECTOR_INIT
;
734 git_diff_delta
*delta
;
736 /* Nothing to do if there's no repo to talk about */
737 if (!INDEX_OWNER(index
))
740 /* If there's no workdir, we can't know where to even check */
741 if (!git_repository_workdir(INDEX_OWNER(index
)))
744 diff_opts
.flags
|= GIT_DIFF_INCLUDE_TYPECHANGE
| GIT_DIFF_IGNORE_SUBMODULES
| GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
745 git_vector_foreach(&index
->entries
, i
, entry
) {
746 if ((entry
->flags_extended
& GIT_INDEX_ENTRY_UPTODATE
) == 0 &&
747 is_racy_entry(index
, entry
))
748 git_vector_insert(&paths
, (char *)entry
->path
);
751 if (paths
.length
== 0)
754 diff_opts
.pathspec
.count
= paths
.length
;
755 diff_opts
.pathspec
.strings
= (char **)paths
.contents
;
757 if ((error
= git_diff_index_to_workdir(&diff
, INDEX_OWNER(index
), index
, &diff_opts
)) < 0)
760 git_vector_foreach(&diff
->deltas
, i
, delta
) {
761 entry
= (git_index_entry
*)git_index_get_bypath(index
, delta
->old_file
.path
, 0);
763 /* Ensure that we have a stage 0 for this file (ie, it's not a
764 * conflict), otherwise smudging it is quite pointless.
767 entry
->file_size
= 0;
774 git_vector_free(&paths
);
778 unsigned git_index_version(git_index
*index
)
782 return index
->version
;
785 int git_index_set_version(git_index
*index
, unsigned int version
)
789 if (version
< INDEX_VERSION_NUMBER_LB
||
790 version
> INDEX_VERSION_NUMBER_UB
) {
791 git_error_set(GIT_ERROR_INDEX
, "invalid version number");
795 index
->version
= version
;
800 int git_index_write(git_index
*index
)
802 git_indexwriter writer
= GIT_INDEXWRITER_INIT
;
805 truncate_racily_clean(index
);
807 if ((error
= git_indexwriter_init(&writer
, index
)) == 0 &&
808 (error
= git_indexwriter_commit(&writer
)) == 0)
811 git_indexwriter_cleanup(&writer
);
816 const char * git_index_path(const git_index
*index
)
819 return index
->index_file_path
;
822 int git_index_write_tree(git_oid
*oid
, git_index
*index
)
824 git_repository
*repo
;
826 assert(oid
&& index
);
828 repo
= INDEX_OWNER(index
);
831 return create_index_error(-1, "Failed to write tree. "
832 "the index file is not backed up by an existing repository");
834 return git_tree__write_index(oid
, index
, repo
);
837 int git_index_write_tree_to(
838 git_oid
*oid
, git_index
*index
, git_repository
*repo
)
840 assert(oid
&& index
&& repo
);
841 return git_tree__write_index(oid
, index
, repo
);
844 size_t git_index_entrycount(const git_index
*index
)
847 return index
->entries
.length
;
850 const git_index_entry
*git_index_get_byindex(
851 git_index
*index
, size_t n
)
854 git_vector_sort(&index
->entries
);
855 return git_vector_get(&index
->entries
, n
);
858 const git_index_entry
*git_index_get_bypath(
859 git_index
*index
, const char *path
, int stage
)
861 git_index_entry key
= {{ 0 }};
862 git_index_entry
*value
;
867 GIT_INDEX_ENTRY_STAGE_SET(&key
, stage
);
869 if (index
->ignore_case
)
870 value
= git_idxmap_icase_get((git_idxmap_icase
*) index
->entries_map
, &key
);
872 value
= git_idxmap_get(index
->entries_map
, &key
);
875 git_error_set(GIT_ERROR_INDEX
, "index does not contain '%s'", path
);
882 void git_index_entry__init_from_stat(
883 git_index_entry
*entry
, struct stat
*st
, bool trust_mode
)
885 entry
->ctime
.seconds
= (int32_t)st
->st_ctime
;
886 entry
->mtime
.seconds
= (int32_t)st
->st_mtime
;
887 #if defined(GIT_USE_NSEC)
888 entry
->mtime
.nanoseconds
= st
->st_mtime_nsec
;
889 entry
->ctime
.nanoseconds
= st
->st_ctime_nsec
;
891 entry
->dev
= st
->st_rdev
;
892 entry
->ino
= st
->st_ino
;
893 entry
->mode
= (!trust_mode
&& S_ISREG(st
->st_mode
)) ?
894 git_index__create_mode(0666) : git_index__create_mode(st
->st_mode
);
895 entry
->uid
= st
->st_uid
;
896 entry
->gid
= st
->st_gid
;
897 entry
->file_size
= (uint32_t)st
->st_size
;
900 static void index_entry_adjust_namemask(
901 git_index_entry
*entry
,
904 entry
->flags
&= ~GIT_INDEX_ENTRY_NAMEMASK
;
906 if (path_length
< GIT_INDEX_ENTRY_NAMEMASK
)
907 entry
->flags
|= path_length
& GIT_INDEX_ENTRY_NAMEMASK
;
909 entry
->flags
|= GIT_INDEX_ENTRY_NAMEMASK
;
912 /* When `from_workdir` is true, we will validate the paths to avoid placing
913 * paths that are invalid for the working directory on the current filesystem
914 * (eg, on Windows, we will disallow `GIT~1`, `AUX`, `COM1`, etc). This
915 * function will *always* prevent `.git` and directory traversal `../` from
916 * being added to the index.
918 static int index_entry_create(
919 git_index_entry
**out
,
920 git_repository
*repo
,
925 size_t pathlen
= strlen(path
), alloclen
;
926 struct entry_internal
*entry
;
927 unsigned int path_valid_flags
= GIT_PATH_REJECT_INDEX_DEFAULTS
;
930 /* always reject placing `.git` in the index and directory traversal.
931 * when requested, disallow platform-specific filenames and upgrade to
932 * the platform-specific `.git` tests (eg, `git~1`, etc).
935 path_valid_flags
|= GIT_PATH_REJECT_WORKDIR_DEFAULTS
;
939 if (!git_path_isvalid(repo
, path
, mode
, path_valid_flags
)) {
940 git_error_set(GIT_ERROR_INDEX
, "invalid path: '%s'", path
);
944 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, sizeof(struct entry_internal
), pathlen
);
945 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen
, alloclen
, 1);
946 entry
= git__calloc(1, alloclen
);
947 GIT_ERROR_CHECK_ALLOC(entry
);
949 entry
->pathlen
= pathlen
;
950 memcpy(entry
->path
, path
, pathlen
);
951 entry
->entry
.path
= entry
->path
;
953 *out
= (git_index_entry
*)entry
;
957 static int index_entry_init(
958 git_index_entry
**entry_out
,
960 const char *rel_path
)
963 git_index_entry
*entry
= NULL
;
964 git_buf path
= GIT_BUF_INIT
;
967 git_repository
*repo
;
969 if (INDEX_OWNER(index
) == NULL
)
970 return create_index_error(-1,
971 "could not initialize index entry. "
972 "Index is not backed up by an existing repository.");
975 * FIXME: this is duplicated with the work in
976 * git_blob__create_from_paths. It should accept an optional stat
977 * structure so we can pass in the one we have to do here.
979 repo
= INDEX_OWNER(index
);
980 if (git_repository__ensure_not_bare(repo
, "create blob from file") < 0)
981 return GIT_EBAREREPO
;
983 if (git_buf_joinpath(&path
, git_repository_workdir(repo
), rel_path
) < 0)
986 error
= git_path_lstat(path
.ptr
, &st
);
987 git_buf_dispose(&path
);
992 if (index_entry_create(&entry
, INDEX_OWNER(index
), rel_path
, &st
, true) < 0)
995 /* write the blob to disk and get the oid and stat info */
996 error
= git_blob__create_from_paths(
997 &oid
, &st
, INDEX_OWNER(index
), NULL
, rel_path
, 0, true);
1000 index_entry_free(entry
);
1005 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1007 *entry_out
= (git_index_entry
*)entry
;
1011 static git_index_reuc_entry
*reuc_entry_alloc(const char *path
)
1013 size_t pathlen
= strlen(path
),
1014 structlen
= sizeof(struct reuc_entry_internal
),
1016 struct reuc_entry_internal
*entry
;
1018 if (GIT_ADD_SIZET_OVERFLOW(&alloclen
, structlen
, pathlen
) ||
1019 GIT_ADD_SIZET_OVERFLOW(&alloclen
, alloclen
, 1))
1022 entry
= git__calloc(1, alloclen
);
1026 entry
->pathlen
= pathlen
;
1027 memcpy(entry
->path
, path
, pathlen
);
1028 entry
->entry
.path
= entry
->path
;
1030 return (git_index_reuc_entry
*)entry
;
1033 static int index_entry_reuc_init(git_index_reuc_entry
**reuc_out
,
1035 int ancestor_mode
, const git_oid
*ancestor_oid
,
1036 int our_mode
, const git_oid
*our_oid
,
1037 int their_mode
, const git_oid
*their_oid
)
1039 git_index_reuc_entry
*reuc
= NULL
;
1041 assert(reuc_out
&& path
);
1043 *reuc_out
= reuc
= reuc_entry_alloc(path
);
1044 GIT_ERROR_CHECK_ALLOC(reuc
);
1046 if ((reuc
->mode
[0] = ancestor_mode
) > 0) {
1047 assert(ancestor_oid
);
1048 git_oid_cpy(&reuc
->oid
[0], ancestor_oid
);
1051 if ((reuc
->mode
[1] = our_mode
) > 0) {
1053 git_oid_cpy(&reuc
->oid
[1], our_oid
);
1056 if ((reuc
->mode
[2] = their_mode
) > 0) {
1058 git_oid_cpy(&reuc
->oid
[2], their_oid
);
1064 static void index_entry_cpy(
1065 git_index_entry
*tgt
,
1066 const git_index_entry
*src
)
1068 const char *tgt_path
= tgt
->path
;
1069 memcpy(tgt
, src
, sizeof(*tgt
));
1070 tgt
->path
= tgt_path
;
1073 static int index_entry_dup(
1074 git_index_entry
**out
,
1076 const git_index_entry
*src
)
1078 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1081 index_entry_cpy(*out
, src
);
1085 static void index_entry_cpy_nocache(
1086 git_index_entry
*tgt
,
1087 const git_index_entry
*src
)
1089 git_oid_cpy(&tgt
->id
, &src
->id
);
1090 tgt
->mode
= src
->mode
;
1091 tgt
->flags
= src
->flags
;
1092 tgt
->flags_extended
= (src
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
1095 static int index_entry_dup_nocache(
1096 git_index_entry
**out
,
1098 const git_index_entry
*src
)
1100 if (index_entry_create(out
, INDEX_OWNER(index
), src
->path
, NULL
, false) < 0)
1103 index_entry_cpy_nocache(*out
, src
);
1107 static int has_file_name(git_index
*index
,
1108 const git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1110 size_t len
= strlen(entry
->path
);
1111 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1112 const char *name
= entry
->path
;
1114 while (pos
< index
->entries
.length
) {
1115 struct entry_internal
*p
= index
->entries
.contents
[pos
++];
1117 if (len
>= p
->pathlen
)
1119 if (memcmp(name
, p
->path
, len
))
1121 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) != stage
)
1123 if (p
->path
[len
] != '/')
1128 if (index_remove_entry(index
, --pos
) < 0)
1135 * Do we have another file with a pathname that is a proper
1136 * subset of the name we're trying to add?
1138 static int has_dir_name(git_index
*index
,
1139 const git_index_entry
*entry
, int ok_to_replace
)
1141 int stage
= GIT_INDEX_ENTRY_STAGE(entry
);
1142 const char *name
= entry
->path
;
1143 const char *slash
= name
+ strlen(name
);
1149 if (*--slash
== '/')
1151 if (slash
<= entry
->path
)
1156 if (!index_find(&pos
, index
, name
, len
, stage
)) {
1160 if (index_remove_entry(index
, pos
) < 0)
1166 * Trivial optimization: if we find an entry that
1167 * already matches the sub-directory, then we know
1168 * we're ok, and we can exit.
1170 for (; pos
< index
->entries
.length
; ++pos
) {
1171 struct entry_internal
*p
= index
->entries
.contents
[pos
];
1173 if (p
->pathlen
<= len
||
1174 p
->path
[len
] != '/' ||
1175 memcmp(p
->path
, name
, len
))
1176 break; /* not our subdirectory */
1178 if (GIT_INDEX_ENTRY_STAGE(&p
->entry
) == stage
)
1186 static int check_file_directory_collision(git_index
*index
,
1187 git_index_entry
*entry
, size_t pos
, int ok_to_replace
)
1189 if (has_file_name(index
, entry
, pos
, ok_to_replace
) < 0 ||
1190 has_dir_name(index
, entry
, ok_to_replace
) < 0) {
1191 git_error_set(GIT_ERROR_INDEX
,
1192 "'%s' appears as both a file and a directory", entry
->path
);
1199 static int canonicalize_directory_path(
1201 git_index_entry
*entry
,
1202 git_index_entry
*existing
)
1204 const git_index_entry
*match
, *best
= NULL
;
1206 size_t pos
, search_len
, best_len
;
1208 if (!index
->ignore_case
)
1211 /* item already exists in the index, simply re-use the existing case */
1213 memcpy((char *)entry
->path
, existing
->path
, strlen(existing
->path
));
1218 if (strchr(entry
->path
, '/') == NULL
)
1221 if ((search
= git__strdup(entry
->path
)) == NULL
)
1224 /* starting at the parent directory and descending to the root, find the
1225 * common parent directory.
1227 while (!best
&& (sep
= strrchr(search
, '/'))) {
1230 search_len
= strlen(search
);
1232 git_vector_bsearch2(
1233 &pos
, &index
->entries
, index
->entries_search_path
, search
);
1235 while ((match
= git_vector_get(&index
->entries
, pos
))) {
1236 if (GIT_INDEX_ENTRY_STAGE(match
) != 0) {
1237 /* conflicts do not contribute to canonical paths */
1238 } else if (strncmp(search
, match
->path
, search_len
) == 0) {
1239 /* prefer an exact match to the input filename */
1241 best_len
= search_len
;
1243 } else if (strncasecmp(search
, match
->path
, search_len
) == 0) {
1244 /* continue walking, there may be a path with an exact
1245 * (case sensitive) match later in the index, but use this
1246 * as the best match until that happens.
1250 best_len
= search_len
;
1263 memcpy((char *)entry
->path
, best
->path
, best_len
);
1269 static int index_no_dups(void **old
, void *new)
1271 const git_index_entry
*entry
= new;
1273 git_error_set(GIT_ERROR_INDEX
, "'%s' appears multiple times at stage %d",
1274 entry
->path
, GIT_INDEX_ENTRY_STAGE(entry
));
1278 static void index_existing_and_best(
1279 git_index_entry
**existing
,
1280 size_t *existing_position
,
1281 git_index_entry
**best
,
1283 const git_index_entry
*entry
)
1289 error
= index_find(&pos
,
1290 index
, entry
->path
, 0, GIT_INDEX_ENTRY_STAGE(entry
));
1293 *existing
= index
->entries
.contents
[pos
];
1294 *existing_position
= pos
;
1295 *best
= index
->entries
.contents
[pos
];
1300 *existing_position
= 0;
1303 if (GIT_INDEX_ENTRY_STAGE(entry
) == 0) {
1304 for (; pos
< index
->entries
.length
; pos
++) {
1305 int (*strcomp
)(const char *a
, const char *b
) =
1306 index
->ignore_case
? git__strcasecmp
: git__strcmp
;
1308 e
= index
->entries
.contents
[pos
];
1310 if (strcomp(entry
->path
, e
->path
) != 0)
1313 if (GIT_INDEX_ENTRY_STAGE(e
) == GIT_INDEX_STAGE_ANCESTOR
) {
1324 /* index_insert takes ownership of the new entry - if it can't insert
1325 * it, then it will return an error **and also free the entry**. When
1326 * it replaces an existing entry, it will update the entry_ptr with the
1327 * actual entry in the index (and free the passed in one).
1329 * trust_path is whether we use the given path, or whether (on case
1330 * insensitive systems only) we try to canonicalize the given path to
1331 * be within an existing directory.
1333 * trust_mode is whether we trust the mode in entry_ptr.
1335 * trust_id is whether we trust the id or it should be validated.
1337 static int index_insert(
1339 git_index_entry
**entry_ptr
,
1345 git_index_entry
*existing
, *best
, *entry
;
1346 size_t path_length
, position
;
1349 assert(index
&& entry_ptr
);
1353 /* Make sure that the path length flag is correct */
1354 path_length
= ((struct entry_internal
*)entry
)->pathlen
;
1355 index_entry_adjust_namemask(entry
, path_length
);
1357 /* This entry is now up-to-date and should not be checked for raciness */
1358 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1360 git_vector_sort(&index
->entries
);
1363 * Look if an entry with this path already exists, either staged, or (if
1364 * this entry is a regular staged item) as the "ours" side of a conflict.
1366 index_existing_and_best(&existing
, &position
, &best
, index
, entry
);
1368 /* Update the file mode */
1369 entry
->mode
= trust_mode
?
1370 git_index__create_mode(entry
->mode
) :
1371 index_merge_mode(index
, best
, entry
->mode
);
1373 /* Canonicalize the directory name */
1374 if (!trust_path
&& (error
= canonicalize_directory_path(index
, entry
, best
)) < 0)
1377 /* Ensure that the given id exists (unless it's a submodule) */
1378 if (!trust_id
&& INDEX_OWNER(index
) &&
1379 (entry
->mode
& GIT_FILEMODE_COMMIT
) != GIT_FILEMODE_COMMIT
) {
1381 if (!git_object__is_valid(INDEX_OWNER(index
), &entry
->id
,
1382 git_object__type_from_filemode(entry
->mode
))) {
1388 /* Look for tree / blob name collisions, removing conflicts if requested */
1389 if ((error
= check_file_directory_collision(index
, entry
, position
, replace
)) < 0)
1393 * If we are replacing an existing item, overwrite the existing entry
1394 * and return it in place of the passed in one.
1398 index_entry_cpy(existing
, entry
);
1401 memcpy((char *)existing
->path
, entry
->path
, strlen(entry
->path
));
1404 index_entry_free(entry
);
1405 *entry_ptr
= existing
;
1408 * If replace is not requested or no existing entry exists, insert
1409 * at the sorted position. (Since we re-sort after each insert to
1410 * check for dups, this is actually cheaper in the long run.)
1412 if ((error
= git_vector_insert_sorted(&index
->entries
, entry
, index_no_dups
)) < 0 ||
1413 (error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1421 index_entry_free(*entry_ptr
);
1428 static int index_conflict_to_reuc(git_index
*index
, const char *path
)
1430 const git_index_entry
*conflict_entries
[3];
1431 int ancestor_mode
, our_mode
, their_mode
;
1432 git_oid
const *ancestor_oid
, *our_oid
, *their_oid
;
1435 if ((ret
= git_index_conflict_get(&conflict_entries
[0],
1436 &conflict_entries
[1], &conflict_entries
[2], index
, path
)) < 0)
1439 ancestor_mode
= conflict_entries
[0] == NULL
? 0 : conflict_entries
[0]->mode
;
1440 our_mode
= conflict_entries
[1] == NULL
? 0 : conflict_entries
[1]->mode
;
1441 their_mode
= conflict_entries
[2] == NULL
? 0 : conflict_entries
[2]->mode
;
1443 ancestor_oid
= conflict_entries
[0] == NULL
? NULL
: &conflict_entries
[0]->id
;
1444 our_oid
= conflict_entries
[1] == NULL
? NULL
: &conflict_entries
[1]->id
;
1445 their_oid
= conflict_entries
[2] == NULL
? NULL
: &conflict_entries
[2]->id
;
1447 if ((ret
= git_index_reuc_add(index
, path
, ancestor_mode
, ancestor_oid
,
1448 our_mode
, our_oid
, their_mode
, their_oid
)) >= 0)
1449 ret
= git_index_conflict_remove(index
, path
);
1454 GIT_INLINE(bool) is_file_or_link(const int filemode
)
1456 return (filemode
== GIT_FILEMODE_BLOB
||
1457 filemode
== GIT_FILEMODE_BLOB_EXECUTABLE
||
1458 filemode
== GIT_FILEMODE_LINK
);
1461 GIT_INLINE(bool) valid_filemode(const int filemode
)
1463 return (is_file_or_link(filemode
) || filemode
== GIT_FILEMODE_COMMIT
);
1466 int git_index_add_from_buffer(
1467 git_index
*index
, const git_index_entry
*source_entry
,
1468 const void *buffer
, size_t len
)
1470 git_index_entry
*entry
= NULL
;
1474 assert(index
&& source_entry
->path
);
1476 if (INDEX_OWNER(index
) == NULL
)
1477 return create_index_error(-1,
1478 "could not initialize index entry. "
1479 "Index is not backed up by an existing repository.");
1481 if (!is_file_or_link(source_entry
->mode
)) {
1482 git_error_set(GIT_ERROR_INDEX
, "invalid filemode");
1486 if (len
> UINT32_MAX
) {
1487 git_error_set(GIT_ERROR_INDEX
, "buffer is too large");
1491 if (index_entry_dup(&entry
, index
, source_entry
) < 0)
1494 error
= git_blob_create_from_buffer(&id
, INDEX_OWNER(index
), buffer
, len
);
1496 index_entry_free(entry
);
1500 git_oid_cpy(&entry
->id
, &id
);
1501 entry
->file_size
= (uint32_t)len
;
1503 if ((error
= index_insert(index
, &entry
, 1, true, true, true)) < 0)
1506 /* Adding implies conflict was resolved, move conflict entries to REUC */
1507 if ((error
= index_conflict_to_reuc(index
, entry
->path
)) < 0 && error
!= GIT_ENOTFOUND
)
1510 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1514 static int add_repo_as_submodule(git_index_entry
**out
, git_index
*index
, const char *path
)
1516 git_repository
*sub
;
1517 git_buf abspath
= GIT_BUF_INIT
;
1518 git_repository
*repo
= INDEX_OWNER(index
);
1519 git_reference
*head
;
1520 git_index_entry
*entry
;
1524 if ((error
= git_buf_joinpath(&abspath
, git_repository_workdir(repo
), path
)) < 0)
1527 if ((error
= p_stat(abspath
.ptr
, &st
)) < 0) {
1528 git_error_set(GIT_ERROR_OS
, "failed to stat repository dir");
1532 if (index_entry_create(&entry
, INDEX_OWNER(index
), path
, &st
, true) < 0)
1535 git_index_entry__init_from_stat(entry
, &st
, !index
->distrust_filemode
);
1537 if ((error
= git_repository_open(&sub
, abspath
.ptr
)) < 0)
1540 if ((error
= git_repository_head(&head
, sub
)) < 0)
1543 git_oid_cpy(&entry
->id
, git_reference_target(head
));
1544 entry
->mode
= GIT_FILEMODE_COMMIT
;
1546 git_reference_free(head
);
1547 git_repository_free(sub
);
1548 git_buf_dispose(&abspath
);
1554 int git_index_add_bypath(git_index
*index
, const char *path
)
1556 git_index_entry
*entry
= NULL
;
1559 assert(index
&& path
);
1561 if ((ret
= index_entry_init(&entry
, index
, path
)) == 0)
1562 ret
= index_insert(index
, &entry
, 1, false, false, true);
1564 /* If we were given a directory, let's see if it's a submodule */
1565 if (ret
< 0 && ret
!= GIT_EDIRECTORY
)
1568 if (ret
== GIT_EDIRECTORY
) {
1570 git_error_state err
;
1572 git_error_state_capture(&err
, ret
);
1574 ret
= git_submodule_lookup(&sm
, INDEX_OWNER(index
), path
);
1575 if (ret
== GIT_ENOTFOUND
)
1576 return git_error_state_restore(&err
);
1578 git_error_state_free(&err
);
1581 * EEXISTS means that there is a repository at that path, but it's not known
1582 * as a submodule. We add its HEAD as an entry and don't register it.
1584 if (ret
== GIT_EEXISTS
) {
1585 if ((ret
= add_repo_as_submodule(&entry
, index
, path
)) < 0)
1588 if ((ret
= index_insert(index
, &entry
, 1, false, false, true)) < 0)
1590 } else if (ret
< 0) {
1593 ret
= git_submodule_add_to_index(sm
, false);
1594 git_submodule_free(sm
);
1599 /* Adding implies conflict was resolved, move conflict entries to REUC */
1600 if ((ret
= index_conflict_to_reuc(index
, path
)) < 0 && ret
!= GIT_ENOTFOUND
)
1603 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1607 int git_index_remove_bypath(git_index
*index
, const char *path
)
1611 assert(index
&& path
);
1613 if (((ret
= git_index_remove(index
, path
, 0)) < 0 &&
1614 ret
!= GIT_ENOTFOUND
) ||
1615 ((ret
= index_conflict_to_reuc(index
, path
)) < 0 &&
1616 ret
!= GIT_ENOTFOUND
))
1619 if (ret
== GIT_ENOTFOUND
)
1625 int git_index__fill(git_index
*index
, const git_vector
*source_entries
)
1627 const git_index_entry
*source_entry
= NULL
;
1633 if (!source_entries
->length
)
1636 if (git_vector_size_hint(&index
->entries
, source_entries
->length
) < 0 ||
1637 index_map_resize(index
->entries_map
, (size_t)(source_entries
->length
* 1.3),
1638 index
->ignore_case
) < 0)
1641 git_vector_foreach(source_entries
, i
, source_entry
) {
1642 git_index_entry
*entry
= NULL
;
1644 if ((error
= index_entry_dup(&entry
, index
, source_entry
)) < 0)
1647 index_entry_adjust_namemask(entry
, ((struct entry_internal
*)entry
)->pathlen
);
1648 entry
->flags_extended
|= GIT_INDEX_ENTRY_UPTODATE
;
1649 entry
->mode
= git_index__create_mode(entry
->mode
);
1651 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0)
1654 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0)
1661 git_vector_sort(&index
->entries
);
1667 int git_index_add(git_index
*index
, const git_index_entry
*source_entry
)
1669 git_index_entry
*entry
= NULL
;
1672 assert(index
&& source_entry
&& source_entry
->path
);
1674 if (!valid_filemode(source_entry
->mode
)) {
1675 git_error_set(GIT_ERROR_INDEX
, "invalid entry mode");
1679 if ((ret
= index_entry_dup(&entry
, index
, source_entry
)) < 0 ||
1680 (ret
= index_insert(index
, &entry
, 1, true, true, false)) < 0)
1683 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
1687 int git_index_remove(git_index
*index
, const char *path
, int stage
)
1691 git_index_entry remove_key
= {{ 0 }};
1693 remove_key
.path
= path
;
1694 GIT_INDEX_ENTRY_STAGE_SET(&remove_key
, stage
);
1696 index_map_delete(index
->entries_map
, &remove_key
, index
->ignore_case
);
1698 if (index_find(&position
, index
, path
, 0, stage
) < 0) {
1700 GIT_ERROR_INDEX
, "index does not contain %s at stage %d", path
, stage
);
1701 error
= GIT_ENOTFOUND
;
1703 error
= index_remove_entry(index
, position
);
1709 int git_index_remove_directory(git_index
*index
, const char *dir
, int stage
)
1711 git_buf pfx
= GIT_BUF_INIT
;
1714 git_index_entry
*entry
;
1716 if (!(error
= git_buf_sets(&pfx
, dir
)) &&
1717 !(error
= git_path_to_dir(&pfx
)))
1718 index_find(&pos
, index
, pfx
.ptr
, pfx
.size
, GIT_INDEX_STAGE_ANY
);
1721 entry
= git_vector_get(&index
->entries
, pos
);
1722 if (!entry
|| git__prefixcmp(entry
->path
, pfx
.ptr
) != 0)
1725 if (GIT_INDEX_ENTRY_STAGE(entry
) != stage
) {
1730 error
= index_remove_entry(index
, pos
);
1732 /* removed entry at 'pos' so we don't need to increment */
1735 git_buf_dispose(&pfx
);
1740 int git_index_find_prefix(size_t *at_pos
, git_index
*index
, const char *prefix
)
1744 const git_index_entry
*entry
;
1746 index_find(&pos
, index
, prefix
, strlen(prefix
), GIT_INDEX_STAGE_ANY
);
1747 entry
= git_vector_get(&index
->entries
, pos
);
1748 if (!entry
|| git__prefixcmp(entry
->path
, prefix
) != 0)
1749 error
= GIT_ENOTFOUND
;
1751 if (!error
&& at_pos
)
1757 int git_index__find_pos(
1758 size_t *out
, git_index
*index
, const char *path
, size_t path_len
, int stage
)
1760 assert(index
&& path
);
1761 return index_find(out
, index
, path
, path_len
, stage
);
1764 int git_index_find(size_t *at_pos
, git_index
*index
, const char *path
)
1768 assert(index
&& path
);
1770 if (git_vector_bsearch2(
1771 &pos
, &index
->entries
, index
->entries_search_path
, path
) < 0) {
1772 git_error_set(GIT_ERROR_INDEX
, "index does not contain %s", path
);
1773 return GIT_ENOTFOUND
;
1776 /* Since our binary search only looked at path, we may be in the
1777 * middle of a list of stages.
1779 for (; pos
> 0; --pos
) {
1780 const git_index_entry
*prev
= git_vector_get(&index
->entries
, pos
- 1);
1782 if (index
->entries_cmp_path(prev
->path
, path
) != 0)
1792 int git_index_conflict_add(git_index
*index
,
1793 const git_index_entry
*ancestor_entry
,
1794 const git_index_entry
*our_entry
,
1795 const git_index_entry
*their_entry
)
1797 git_index_entry
*entries
[3] = { 0 };
1803 if ((ancestor_entry
&&
1804 (ret
= index_entry_dup(&entries
[0], index
, ancestor_entry
)) < 0) ||
1806 (ret
= index_entry_dup(&entries
[1], index
, our_entry
)) < 0) ||
1808 (ret
= index_entry_dup(&entries
[2], index
, their_entry
)) < 0))
1811 /* Validate entries */
1812 for (i
= 0; i
< 3; i
++) {
1813 if (entries
[i
] && !valid_filemode(entries
[i
]->mode
)) {
1814 git_error_set(GIT_ERROR_INDEX
, "invalid filemode for stage %d entry",
1821 /* Remove existing index entries for each path */
1822 for (i
= 0; i
< 3; i
++) {
1823 if (entries
[i
] == NULL
)
1826 if ((ret
= git_index_remove(index
, entries
[i
]->path
, 0)) != 0) {
1827 if (ret
!= GIT_ENOTFOUND
)
1835 /* Add the conflict entries */
1836 for (i
= 0; i
< 3; i
++) {
1837 if (entries
[i
] == NULL
)
1840 /* Make sure stage is correct */
1841 GIT_INDEX_ENTRY_STAGE_SET(entries
[i
], i
+ 1);
1843 if ((ret
= index_insert(index
, &entries
[i
], 1, true, true, false)) < 0)
1846 entries
[i
] = NULL
; /* don't free if later entry fails */
1852 for (i
= 0; i
< 3; i
++) {
1853 if (entries
[i
] != NULL
)
1854 index_entry_free(entries
[i
]);
1860 static int index_conflict__get_byindex(
1861 const git_index_entry
**ancestor_out
,
1862 const git_index_entry
**our_out
,
1863 const git_index_entry
**their_out
,
1867 const git_index_entry
*conflict_entry
;
1868 const char *path
= NULL
;
1872 assert(ancestor_out
&& our_out
&& their_out
&& index
);
1874 *ancestor_out
= NULL
;
1878 for (count
= git_index_entrycount(index
); n
< count
; ++n
) {
1879 conflict_entry
= git_vector_get(&index
->entries
, n
);
1881 if (path
&& index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1884 stage
= GIT_INDEX_ENTRY_STAGE(conflict_entry
);
1885 path
= conflict_entry
->path
;
1889 *their_out
= conflict_entry
;
1893 *our_out
= conflict_entry
;
1897 *ancestor_out
= conflict_entry
;
1908 int git_index_conflict_get(
1909 const git_index_entry
**ancestor_out
,
1910 const git_index_entry
**our_out
,
1911 const git_index_entry
**their_out
,
1918 assert(ancestor_out
&& our_out
&& their_out
&& index
&& path
);
1920 *ancestor_out
= NULL
;
1924 if (git_index_find(&pos
, index
, path
) < 0)
1925 return GIT_ENOTFOUND
;
1927 if ((len
= index_conflict__get_byindex(
1928 ancestor_out
, our_out
, their_out
, index
, pos
)) < 0)
1931 return GIT_ENOTFOUND
;
1936 static int index_conflict_remove(git_index
*index
, const char *path
)
1939 git_index_entry
*conflict_entry
;
1942 if (path
!= NULL
&& git_index_find(&pos
, index
, path
) < 0)
1943 return GIT_ENOTFOUND
;
1945 while ((conflict_entry
= git_vector_get(&index
->entries
, pos
)) != NULL
) {
1948 index
->entries_cmp_path(conflict_entry
->path
, path
) != 0)
1951 if (GIT_INDEX_ENTRY_STAGE(conflict_entry
) == 0) {
1956 if ((error
= index_remove_entry(index
, pos
)) < 0)
1963 int git_index_conflict_remove(git_index
*index
, const char *path
)
1965 assert(index
&& path
);
1966 return index_conflict_remove(index
, path
);
1969 int git_index_conflict_cleanup(git_index
*index
)
1972 return index_conflict_remove(index
, NULL
);
1975 int git_index_has_conflicts(const git_index
*index
)
1978 git_index_entry
*entry
;
1982 git_vector_foreach(&index
->entries
, i
, entry
) {
1983 if (GIT_INDEX_ENTRY_STAGE(entry
) > 0)
1990 int git_index_iterator_new(
1991 git_index_iterator
**iterator_out
,
1994 git_index_iterator
*it
;
1997 assert(iterator_out
&& index
);
1999 it
= git__calloc(1, sizeof(git_index_iterator
));
2000 GIT_ERROR_CHECK_ALLOC(it
);
2002 if ((error
= git_index_snapshot_new(&it
->snap
, index
)) < 0) {
2013 int git_index_iterator_next(
2014 const git_index_entry
**out
,
2015 git_index_iterator
*it
)
2019 if (it
->cur
>= git_vector_length(&it
->snap
))
2020 return GIT_ITEROVER
;
2022 *out
= (git_index_entry
*)git_vector_get(&it
->snap
, it
->cur
++);
2026 void git_index_iterator_free(git_index_iterator
*it
)
2031 git_index_snapshot_release(&it
->snap
, it
->index
);
2035 int git_index_conflict_iterator_new(
2036 git_index_conflict_iterator
**iterator_out
,
2039 git_index_conflict_iterator
*it
= NULL
;
2041 assert(iterator_out
&& index
);
2043 it
= git__calloc(1, sizeof(git_index_conflict_iterator
));
2044 GIT_ERROR_CHECK_ALLOC(it
);
2052 int git_index_conflict_next(
2053 const git_index_entry
**ancestor_out
,
2054 const git_index_entry
**our_out
,
2055 const git_index_entry
**their_out
,
2056 git_index_conflict_iterator
*iterator
)
2058 const git_index_entry
*entry
;
2061 assert(ancestor_out
&& our_out
&& their_out
&& iterator
);
2063 *ancestor_out
= NULL
;
2067 while (iterator
->cur
< iterator
->index
->entries
.length
) {
2068 entry
= git_index_get_byindex(iterator
->index
, iterator
->cur
);
2070 if (git_index_entry_is_conflict(entry
)) {
2071 if ((len
= index_conflict__get_byindex(
2076 iterator
->cur
)) < 0)
2079 iterator
->cur
+= len
;
2086 return GIT_ITEROVER
;
2089 void git_index_conflict_iterator_free(git_index_conflict_iterator
*iterator
)
2091 if (iterator
== NULL
)
2094 git__free(iterator
);
2097 size_t git_index_name_entrycount(git_index
*index
)
2100 return index
->names
.length
;
2103 const git_index_name_entry
*git_index_name_get_byindex(
2104 git_index
*index
, size_t n
)
2108 git_vector_sort(&index
->names
);
2109 return git_vector_get(&index
->names
, n
);
2112 static void index_name_entry_free(git_index_name_entry
*ne
)
2116 git__free(ne
->ancestor
);
2117 git__free(ne
->ours
);
2118 git__free(ne
->theirs
);
2122 int git_index_name_add(git_index
*index
,
2123 const char *ancestor
, const char *ours
, const char *theirs
)
2125 git_index_name_entry
*conflict_name
;
2127 assert((ancestor
&& ours
) || (ancestor
&& theirs
) || (ours
&& theirs
));
2129 conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2130 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2132 if ((ancestor
&& !(conflict_name
->ancestor
= git__strdup(ancestor
))) ||
2133 (ours
&& !(conflict_name
->ours
= git__strdup(ours
))) ||
2134 (theirs
&& !(conflict_name
->theirs
= git__strdup(theirs
))) ||
2135 git_vector_insert(&index
->names
, conflict_name
) < 0)
2137 index_name_entry_free(conflict_name
);
2145 int git_index_name_clear(git_index
*index
)
2148 git_index_name_entry
*conflict_name
;
2152 git_vector_foreach(&index
->names
, i
, conflict_name
)
2153 index_name_entry_free(conflict_name
);
2155 git_vector_clear(&index
->names
);
2162 size_t git_index_reuc_entrycount(git_index
*index
)
2165 return index
->reuc
.length
;
2168 static int index_reuc_on_dup(void **old
, void *new)
2170 index_entry_reuc_free(*old
);
2175 static int index_reuc_insert(
2177 git_index_reuc_entry
*reuc
)
2181 assert(index
&& reuc
&& reuc
->path
!= NULL
);
2182 assert(git_vector_is_sorted(&index
->reuc
));
2184 res
= git_vector_insert_sorted(&index
->reuc
, reuc
, &index_reuc_on_dup
);
2187 return res
== GIT_EEXISTS
? 0 : res
;
2190 int git_index_reuc_add(git_index
*index
, const char *path
,
2191 int ancestor_mode
, const git_oid
*ancestor_oid
,
2192 int our_mode
, const git_oid
*our_oid
,
2193 int their_mode
, const git_oid
*their_oid
)
2195 git_index_reuc_entry
*reuc
= NULL
;
2198 assert(index
&& path
);
2200 if ((error
= index_entry_reuc_init(&reuc
, path
, ancestor_mode
,
2201 ancestor_oid
, our_mode
, our_oid
, their_mode
, their_oid
)) < 0 ||
2202 (error
= index_reuc_insert(index
, reuc
)) < 0)
2203 index_entry_reuc_free(reuc
);
2208 int git_index_reuc_find(size_t *at_pos
, git_index
*index
, const char *path
)
2210 return git_vector_bsearch2(at_pos
, &index
->reuc
, index
->reuc_search
, path
);
2213 const git_index_reuc_entry
*git_index_reuc_get_bypath(
2214 git_index
*index
, const char *path
)
2217 assert(index
&& path
);
2219 if (!index
->reuc
.length
)
2222 assert(git_vector_is_sorted(&index
->reuc
));
2224 if (git_index_reuc_find(&pos
, index
, path
) < 0)
2227 return git_vector_get(&index
->reuc
, pos
);
2230 const git_index_reuc_entry
*git_index_reuc_get_byindex(
2231 git_index
*index
, size_t n
)
2234 assert(git_vector_is_sorted(&index
->reuc
));
2236 return git_vector_get(&index
->reuc
, n
);
2239 int git_index_reuc_remove(git_index
*index
, size_t position
)
2242 git_index_reuc_entry
*reuc
;
2244 assert(git_vector_is_sorted(&index
->reuc
));
2246 reuc
= git_vector_get(&index
->reuc
, position
);
2247 error
= git_vector_remove(&index
->reuc
, position
);
2250 index_entry_reuc_free(reuc
);
2256 int git_index_reuc_clear(git_index
*index
)
2262 for (i
= 0; i
< index
->reuc
.length
; ++i
)
2263 index_entry_reuc_free(git__swap(index
->reuc
.contents
[i
], NULL
));
2265 git_vector_clear(&index
->reuc
);
2272 static int index_error_invalid(const char *message
)
2274 git_error_set(GIT_ERROR_INDEX
, "invalid data in index - %s", message
);
2278 static int read_reuc(git_index
*index
, const char *buffer
, size_t size
)
2284 /* If called multiple times, the vector might already be initialized */
2285 if (index
->reuc
._alloc_size
== 0 &&
2286 git_vector_init(&index
->reuc
, 16, reuc_cmp
) < 0)
2290 git_index_reuc_entry
*lost
;
2292 len
= p_strnlen(buffer
, size
) + 1;
2294 return index_error_invalid("reading reuc entries");
2296 lost
= reuc_entry_alloc(buffer
);
2297 GIT_ERROR_CHECK_ALLOC(lost
);
2302 /* read 3 ASCII octal numbers for stage entries */
2303 for (i
= 0; i
< 3; i
++) {
2306 if (git__strntol64(&tmp
, buffer
, size
, &endptr
, 8) < 0 ||
2307 !endptr
|| endptr
== buffer
|| *endptr
||
2308 tmp
< 0 || tmp
> UINT32_MAX
) {
2309 index_entry_reuc_free(lost
);
2310 return index_error_invalid("reading reuc entry stage");
2313 lost
->mode
[i
] = (uint32_t)tmp
;
2315 len
= (endptr
+ 1) - buffer
;
2317 index_entry_reuc_free(lost
);
2318 return index_error_invalid("reading reuc entry stage");
2325 /* read up to 3 OIDs for stage entries */
2326 for (i
= 0; i
< 3; i
++) {
2330 index_entry_reuc_free(lost
);
2331 return index_error_invalid("reading reuc entry oid");
2334 git_oid_fromraw(&lost
->oid
[i
], (const unsigned char *) buffer
);
2339 /* entry was read successfully - insert into reuc vector */
2340 if (git_vector_insert(&index
->reuc
, lost
) < 0)
2344 /* entries are guaranteed to be sorted on-disk */
2345 git_vector_set_sorted(&index
->reuc
, true);
2351 static int read_conflict_names(git_index
*index
, const char *buffer
, size_t size
)
2355 /* This gets called multiple times, the vector might already be initialized */
2356 if (index
->names
._alloc_size
== 0 &&
2357 git_vector_init(&index
->names
, 16, conflict_name_cmp
) < 0)
2360 #define read_conflict_name(ptr) \
2361 len = p_strnlen(buffer, size) + 1; \
2363 index_error_invalid("reading conflict name entries"); \
2369 ptr = git__malloc(len); \
2370 GIT_ERROR_CHECK_ALLOC(ptr); \
2371 memcpy(ptr, buffer, len); \
2378 git_index_name_entry
*conflict_name
= git__calloc(1, sizeof(git_index_name_entry
));
2379 GIT_ERROR_CHECK_ALLOC(conflict_name
);
2381 read_conflict_name(conflict_name
->ancestor
);
2382 read_conflict_name(conflict_name
->ours
);
2383 read_conflict_name(conflict_name
->theirs
);
2385 if (git_vector_insert(&index
->names
, conflict_name
) < 0)
2391 git__free(conflict_name
->ancestor
);
2392 git__free(conflict_name
->ours
);
2393 git__free(conflict_name
->theirs
);
2394 git__free(conflict_name
);
2398 #undef read_conflict_name
2400 /* entries are guaranteed to be sorted on-disk */
2401 git_vector_set_sorted(&index
->names
, true);
2406 static size_t index_entry_size(size_t path_len
, size_t varint_len
, uint32_t flags
)
2409 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2410 return offsetof(struct entry_long
, path
) + path_len
+ 1 + varint_len
;
2412 return offsetof(struct entry_short
, path
) + path_len
+ 1 + varint_len
;
2414 #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
2415 if (flags
& GIT_INDEX_ENTRY_EXTENDED
)
2416 return entry_size(struct entry_long
, path_len
);
2418 return entry_size(struct entry_short
, path_len
);
2423 static int read_entry(
2424 git_index_entry
**out
,
2431 size_t path_length
, entry_size
;
2432 const char *path_ptr
;
2433 struct entry_short source
;
2434 git_index_entry entry
= {{0}};
2435 bool compressed
= index
->version
>= INDEX_VERSION_NUMBER_COMP
;
2436 char *tmp_path
= NULL
;
2438 if (INDEX_FOOTER_SIZE
+ minimal_entry_size
> buffer_size
)
2441 /* buffer is not guaranteed to be aligned */
2442 memcpy(&source
, buffer
, sizeof(struct entry_short
));
2444 entry
.ctime
.seconds
= (git_time_t
)ntohl(source
.ctime
.seconds
);
2445 entry
.ctime
.nanoseconds
= ntohl(source
.ctime
.nanoseconds
);
2446 entry
.mtime
.seconds
= (git_time_t
)ntohl(source
.mtime
.seconds
);
2447 entry
.mtime
.nanoseconds
= ntohl(source
.mtime
.nanoseconds
);
2448 entry
.dev
= ntohl(source
.dev
);
2449 entry
.ino
= ntohl(source
.ino
);
2450 entry
.mode
= ntohl(source
.mode
);
2451 entry
.uid
= ntohl(source
.uid
);
2452 entry
.gid
= ntohl(source
.gid
);
2453 entry
.file_size
= ntohl(source
.file_size
);
2454 git_oid_cpy(&entry
.id
, &source
.oid
);
2455 entry
.flags
= ntohs(source
.flags
);
2457 if (entry
.flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2459 size_t flags_offset
;
2461 flags_offset
= offsetof(struct entry_long
, flags_extended
);
2462 memcpy(&flags_raw
, (const char *) buffer
+ flags_offset
,
2464 flags_raw
= ntohs(flags_raw
);
2466 memcpy(&entry
.flags_extended
, &flags_raw
, sizeof(flags_raw
));
2467 path_ptr
= (const char *) buffer
+ offsetof(struct entry_long
, path
);
2469 path_ptr
= (const char *) buffer
+ offsetof(struct entry_short
, path
);
2472 path_length
= entry
.flags
& GIT_INDEX_ENTRY_NAMEMASK
;
2474 /* if this is a very long string, we must find its
2475 * real length without overflowing */
2476 if (path_length
== 0xFFF) {
2477 const char *path_end
;
2479 path_end
= memchr(path_ptr
, '\0', buffer_size
);
2480 if (path_end
== NULL
)
2483 path_length
= path_end
- path_ptr
;
2486 entry_size
= index_entry_size(path_length
, 0, entry
.flags
);
2487 entry
.path
= (char *)path_ptr
;
2489 size_t varint_len
, last_len
, prefix_len
, suffix_len
, path_len
;
2490 uintmax_t strip_len
;
2492 strip_len
= git_decode_varint((const unsigned char *)path_ptr
, &varint_len
);
2493 last_len
= strlen(last
);
2495 if (varint_len
== 0 || last_len
< strip_len
)
2496 return index_error_invalid("incorrect prefix length");
2498 prefix_len
= last_len
- (size_t)strip_len
;
2499 suffix_len
= strlen(path_ptr
+ varint_len
);
2501 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, prefix_len
, suffix_len
);
2502 GIT_ERROR_CHECK_ALLOC_ADD(&path_len
, path_len
, 1);
2504 if (path_len
> GIT_PATH_MAX
)
2505 return index_error_invalid("unreasonable path length");
2507 tmp_path
= git__malloc(path_len
);
2508 GIT_ERROR_CHECK_ALLOC(tmp_path
);
2510 memcpy(tmp_path
, last
, prefix_len
);
2511 memcpy(tmp_path
+ prefix_len
, path_ptr
+ varint_len
, suffix_len
+ 1);
2512 entry_size
= index_entry_size(suffix_len
, varint_len
, entry
.flags
);
2513 entry
.path
= tmp_path
;
2516 if (entry_size
== 0)
2519 if (INDEX_FOOTER_SIZE
+ entry_size
> buffer_size
)
2522 if (index_entry_dup(out
, index
, &entry
) < 0) {
2523 git__free(tmp_path
);
2527 git__free(tmp_path
);
2528 *out_size
= entry_size
;
2532 static int read_header(struct index_header
*dest
, const void *buffer
)
2534 const struct index_header
*source
= buffer
;
2536 dest
->signature
= ntohl(source
->signature
);
2537 if (dest
->signature
!= INDEX_HEADER_SIG
)
2538 return index_error_invalid("incorrect header signature");
2540 dest
->version
= ntohl(source
->version
);
2541 if (dest
->version
< INDEX_VERSION_NUMBER_LB
||
2542 dest
->version
> INDEX_VERSION_NUMBER_UB
)
2543 return index_error_invalid("incorrect header version");
2545 dest
->entry_count
= ntohl(source
->entry_count
);
2549 static int read_extension(size_t *read_len
, git_index
*index
, const char *buffer
, size_t buffer_size
)
2551 struct index_extension dest
;
2554 /* buffer is not guaranteed to be aligned */
2555 memcpy(&dest
, buffer
, sizeof(struct index_extension
));
2556 dest
.extension_size
= ntohl(dest
.extension_size
);
2558 total_size
= dest
.extension_size
+ sizeof(struct index_extension
);
2560 if (dest
.extension_size
> total_size
||
2561 buffer_size
< total_size
||
2562 buffer_size
- total_size
< INDEX_FOOTER_SIZE
) {
2563 index_error_invalid("extension is truncated");
2567 /* optional extension */
2568 if (dest
.signature
[0] >= 'A' && dest
.signature
[0] <= 'Z') {
2570 if (memcmp(dest
.signature
, INDEX_EXT_TREECACHE_SIG
, 4) == 0) {
2571 if (git_tree_cache_read(&index
->tree
, buffer
+ 8, dest
.extension_size
, &index
->tree_pool
) < 0)
2573 } else if (memcmp(dest
.signature
, INDEX_EXT_UNMERGED_SIG
, 4) == 0) {
2574 if (read_reuc(index
, buffer
+ 8, dest
.extension_size
) < 0)
2576 } else if (memcmp(dest
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4) == 0) {
2577 if (read_conflict_names(index
, buffer
+ 8, dest
.extension_size
) < 0)
2580 /* else, unsupported extension. We cannot parse this, but we can skip
2581 * it by returning `total_size */
2583 /* we cannot handle non-ignorable extensions;
2584 * in fact they aren't even defined in the standard */
2585 git_error_set(GIT_ERROR_INDEX
, "unsupported mandatory extension: '%.4s'", dest
.signature
);
2589 *read_len
= total_size
;
2594 static int parse_index(git_index
*index
, const char *buffer
, size_t buffer_size
)
2598 struct index_header header
= { 0 };
2599 git_oid checksum_calculated
, checksum_expected
;
2600 const char *last
= NULL
;
2601 const char *empty
= "";
2603 #define seek_forward(_increase) { \
2604 if (_increase >= buffer_size) { \
2605 error = index_error_invalid("ran out of data while parsing"); \
2607 buffer += _increase; \
2608 buffer_size -= _increase;\
2611 if (buffer_size
< INDEX_HEADER_SIZE
+ INDEX_FOOTER_SIZE
)
2612 return index_error_invalid("insufficient buffer space");
2614 /* Precalculate the SHA1 of the files's contents -- we'll match it to
2615 * the provided SHA1 in the footer */
2616 git_hash_buf(&checksum_calculated
, buffer
, buffer_size
- INDEX_FOOTER_SIZE
);
2619 if ((error
= read_header(&header
, buffer
)) < 0)
2622 index
->version
= header
.version
;
2623 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2626 seek_forward(INDEX_HEADER_SIZE
);
2628 assert(!index
->entries
.length
);
2630 if ((error
= index_map_resize(index
->entries_map
, header
.entry_count
, index
->ignore_case
)) < 0)
2633 /* Parse all the entries */
2634 for (i
= 0; i
< header
.entry_count
&& buffer_size
> INDEX_FOOTER_SIZE
; ++i
) {
2635 git_index_entry
*entry
= NULL
;
2638 if ((error
= read_entry(&entry
, &entry_size
, index
, buffer
, buffer_size
, last
)) < 0) {
2639 error
= index_error_invalid("invalid entry");
2643 if ((error
= git_vector_insert(&index
->entries
, entry
)) < 0) {
2644 index_entry_free(entry
);
2648 if ((error
= index_map_set(index
->entries_map
, entry
, index
->ignore_case
)) < 0) {
2649 index_entry_free(entry
);
2654 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2657 seek_forward(entry_size
);
2660 if (i
!= header
.entry_count
) {
2661 error
= index_error_invalid("header entries changed while parsing");
2665 /* There's still space for some extensions! */
2666 while (buffer_size
> INDEX_FOOTER_SIZE
) {
2667 size_t extension_size
;
2669 if ((error
= read_extension(&extension_size
, index
, buffer
, buffer_size
)) < 0) {
2673 seek_forward(extension_size
);
2676 if (buffer_size
!= INDEX_FOOTER_SIZE
) {
2677 error
= index_error_invalid(
2678 "buffer size does not match index footer size");
2682 /* 160-bit SHA-1 over the content of the index file before this checksum. */
2683 git_oid_fromraw(&checksum_expected
, (const unsigned char *)buffer
);
2685 if (git_oid__cmp(&checksum_calculated
, &checksum_expected
) != 0) {
2686 error
= index_error_invalid(
2687 "calculated checksum does not match expected");
2691 git_oid_cpy(&index
->checksum
, &checksum_calculated
);
2695 /* Entries are stored case-sensitively on disk, so re-sort now if
2696 * in-memory index is supposed to be case-insensitive
2698 git_vector_set_sorted(&index
->entries
, !index
->ignore_case
);
2699 git_vector_sort(&index
->entries
);
2706 static bool is_index_extended(git_index
*index
)
2709 git_index_entry
*entry
;
2713 git_vector_foreach(&index
->entries
, i
, entry
) {
2714 entry
->flags
&= ~GIT_INDEX_ENTRY_EXTENDED
;
2715 if (entry
->flags_extended
& GIT_INDEX_ENTRY_EXTENDED_FLAGS
) {
2717 entry
->flags
|= GIT_INDEX_ENTRY_EXTENDED
;
2721 return (extended
> 0);
2724 static int write_disk_entry(git_filebuf
*file
, git_index_entry
*entry
, const char *last
)
2727 struct entry_short ondisk
;
2728 size_t path_len
, disk_size
;
2731 const char *path_start
= entry
->path
;
2732 size_t same_len
= 0;
2734 path_len
= ((struct entry_internal
*)entry
)->pathlen
;
2737 const char *last_c
= last
;
2739 while (*path_start
== *last_c
) {
2740 if (!*path_start
|| !*last_c
)
2746 path_len
-= same_len
;
2747 varint_len
= git_encode_varint(NULL
, 0, strlen(last
) - same_len
);
2750 disk_size
= index_entry_size(path_len
, varint_len
, entry
->flags
);
2752 if (git_filebuf_reserve(file
, &mem
, disk_size
) < 0)
2755 memset(mem
, 0x0, disk_size
);
2758 * Yes, we have to truncate.
2760 * The on-disk format for Index entries clearly defines
2761 * the time and size fields to be 4 bytes each -- so even if
2762 * we store these values with 8 bytes on-memory, they must
2763 * be truncated to 4 bytes before writing to disk.
2765 * In 2038 I will be either too dead or too rich to care about this
2767 ondisk
.ctime
.seconds
= htonl((uint32_t)entry
->ctime
.seconds
);
2768 ondisk
.mtime
.seconds
= htonl((uint32_t)entry
->mtime
.seconds
);
2769 ondisk
.ctime
.nanoseconds
= htonl(entry
->ctime
.nanoseconds
);
2770 ondisk
.mtime
.nanoseconds
= htonl(entry
->mtime
.nanoseconds
);
2771 ondisk
.dev
= htonl(entry
->dev
);
2772 ondisk
.ino
= htonl(entry
->ino
);
2773 ondisk
.mode
= htonl(entry
->mode
);
2774 ondisk
.uid
= htonl(entry
->uid
);
2775 ondisk
.gid
= htonl(entry
->gid
);
2776 ondisk
.file_size
= htonl((uint32_t)entry
->file_size
);
2778 git_oid_cpy(&ondisk
.oid
, &entry
->id
);
2780 ondisk
.flags
= htons(entry
->flags
);
2782 if (entry
->flags
& GIT_INDEX_ENTRY_EXTENDED
) {
2783 struct entry_long ondisk_ext
;
2784 memcpy(&ondisk_ext
, &ondisk
, sizeof(struct entry_short
));
2785 ondisk_ext
.flags_extended
= htons(entry
->flags_extended
&
2786 GIT_INDEX_ENTRY_EXTENDED_FLAGS
);
2787 memcpy(mem
, &ondisk_ext
, offsetof(struct entry_long
, path
));
2788 path
= ((struct entry_long
*)mem
)->path
;
2789 disk_size
-= offsetof(struct entry_long
, path
);
2791 memcpy(mem
, &ondisk
, offsetof(struct entry_short
, path
));
2792 path
= ((struct entry_short
*)mem
)->path
;
2793 disk_size
-= offsetof(struct entry_short
, path
);
2797 varint_len
= git_encode_varint((unsigned char *) path
,
2798 disk_size
, strlen(last
) - same_len
);
2799 assert(varint_len
> 0);
2801 disk_size
-= varint_len
;
2804 * If using path compression, we are not allowed
2805 * to have additional trailing NULs.
2807 assert(disk_size
== path_len
+ 1);
2810 * If no path compression is used, we do have
2811 * NULs as padding. As such, simply assert that
2812 * we have enough space left to write the path.
2814 assert(disk_size
> path_len
);
2817 memcpy(path
, path_start
, path_len
+ 1);
2822 static int write_entries(git_index
*index
, git_filebuf
*file
)
2826 git_vector case_sorted
, *entries
;
2827 git_index_entry
*entry
;
2828 const char *last
= NULL
;
2830 /* If index->entries is sorted case-insensitively, then we need
2831 * to re-sort it case-sensitively before writing */
2832 if (index
->ignore_case
) {
2833 git_vector_dup(&case_sorted
, &index
->entries
, git_index_entry_cmp
);
2834 git_vector_sort(&case_sorted
);
2835 entries
= &case_sorted
;
2837 entries
= &index
->entries
;
2840 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2843 git_vector_foreach(entries
, i
, entry
) {
2844 if ((error
= write_disk_entry(file
, entry
, last
)) < 0)
2846 if (index
->version
>= INDEX_VERSION_NUMBER_COMP
)
2850 if (index
->ignore_case
)
2851 git_vector_free(&case_sorted
);
2856 static int write_extension(git_filebuf
*file
, struct index_extension
*header
, git_buf
*data
)
2858 struct index_extension ondisk
;
2860 memset(&ondisk
, 0x0, sizeof(struct index_extension
));
2861 memcpy(&ondisk
, header
, 4);
2862 ondisk
.extension_size
= htonl(header
->extension_size
);
2864 git_filebuf_write(file
, &ondisk
, sizeof(struct index_extension
));
2865 return git_filebuf_write(file
, data
->ptr
, data
->size
);
2868 static int create_name_extension_data(git_buf
*name_buf
, git_index_name_entry
*conflict_name
)
2872 if (conflict_name
->ancestor
== NULL
)
2873 error
= git_buf_put(name_buf
, "\0", 1);
2875 error
= git_buf_put(name_buf
, conflict_name
->ancestor
, strlen(conflict_name
->ancestor
) + 1);
2880 if (conflict_name
->ours
== NULL
)
2881 error
= git_buf_put(name_buf
, "\0", 1);
2883 error
= git_buf_put(name_buf
, conflict_name
->ours
, strlen(conflict_name
->ours
) + 1);
2888 if (conflict_name
->theirs
== NULL
)
2889 error
= git_buf_put(name_buf
, "\0", 1);
2891 error
= git_buf_put(name_buf
, conflict_name
->theirs
, strlen(conflict_name
->theirs
) + 1);
2897 static int write_name_extension(git_index
*index
, git_filebuf
*file
)
2899 git_buf name_buf
= GIT_BUF_INIT
;
2900 git_vector
*out
= &index
->names
;
2901 git_index_name_entry
*conflict_name
;
2902 struct index_extension extension
;
2906 git_vector_foreach(out
, i
, conflict_name
) {
2907 if ((error
= create_name_extension_data(&name_buf
, conflict_name
)) < 0)
2911 memset(&extension
, 0x0, sizeof(struct index_extension
));
2912 memcpy(&extension
.signature
, INDEX_EXT_CONFLICT_NAME_SIG
, 4);
2913 extension
.extension_size
= (uint32_t)name_buf
.size
;
2915 error
= write_extension(file
, &extension
, &name_buf
);
2917 git_buf_dispose(&name_buf
);
2923 static int create_reuc_extension_data(git_buf
*reuc_buf
, git_index_reuc_entry
*reuc
)
2928 if ((error
= git_buf_put(reuc_buf
, reuc
->path
, strlen(reuc
->path
) + 1)) < 0)
2931 for (i
= 0; i
< 3; i
++) {
2932 if ((error
= git_buf_printf(reuc_buf
, "%o", reuc
->mode
[i
])) < 0 ||
2933 (error
= git_buf_put(reuc_buf
, "\0", 1)) < 0)
2937 for (i
= 0; i
< 3; i
++) {
2938 if (reuc
->mode
[i
] && (error
= git_buf_put(reuc_buf
, (char *)&reuc
->oid
[i
].id
, GIT_OID_RAWSZ
)) < 0)
2945 static int write_reuc_extension(git_index
*index
, git_filebuf
*file
)
2947 git_buf reuc_buf
= GIT_BUF_INIT
;
2948 git_vector
*out
= &index
->reuc
;
2949 git_index_reuc_entry
*reuc
;
2950 struct index_extension extension
;
2954 git_vector_foreach(out
, i
, reuc
) {
2955 if ((error
= create_reuc_extension_data(&reuc_buf
, reuc
)) < 0)
2959 memset(&extension
, 0x0, sizeof(struct index_extension
));
2960 memcpy(&extension
.signature
, INDEX_EXT_UNMERGED_SIG
, 4);
2961 extension
.extension_size
= (uint32_t)reuc_buf
.size
;
2963 error
= write_extension(file
, &extension
, &reuc_buf
);
2965 git_buf_dispose(&reuc_buf
);
2971 static int write_tree_extension(git_index
*index
, git_filebuf
*file
)
2973 struct index_extension extension
;
2974 git_buf buf
= GIT_BUF_INIT
;
2977 if (index
->tree
== NULL
)
2980 if ((error
= git_tree_cache_write(&buf
, index
->tree
)) < 0)
2983 memset(&extension
, 0x0, sizeof(struct index_extension
));
2984 memcpy(&extension
.signature
, INDEX_EXT_TREECACHE_SIG
, 4);
2985 extension
.extension_size
= (uint32_t)buf
.size
;
2987 error
= write_extension(file
, &extension
, &buf
);
2989 git_buf_dispose(&buf
);
2994 static void clear_uptodate(git_index
*index
)
2996 git_index_entry
*entry
;
2999 git_vector_foreach(&index
->entries
, i
, entry
)
3000 entry
->flags_extended
&= ~GIT_INDEX_ENTRY_UPTODATE
;
3003 static int write_index(git_oid
*checksum
, git_index
*index
, git_filebuf
*file
)
3006 struct index_header header
;
3008 uint32_t index_version_number
;
3010 assert(index
&& file
);
3012 if (index
->version
<= INDEX_VERSION_NUMBER_EXT
) {
3013 is_extended
= is_index_extended(index
);
3014 index_version_number
= is_extended
? INDEX_VERSION_NUMBER_EXT
: INDEX_VERSION_NUMBER_LB
;
3016 index_version_number
= index
->version
;
3019 header
.signature
= htonl(INDEX_HEADER_SIG
);
3020 header
.version
= htonl(index_version_number
);
3021 header
.entry_count
= htonl((uint32_t)index
->entries
.length
);
3023 if (git_filebuf_write(file
, &header
, sizeof(struct index_header
)) < 0)
3026 if (write_entries(index
, file
) < 0)
3029 /* write the tree cache extension */
3030 if (index
->tree
!= NULL
&& write_tree_extension(index
, file
) < 0)
3033 /* write the rename conflict extension */
3034 if (index
->names
.length
> 0 && write_name_extension(index
, file
) < 0)
3037 /* write the reuc extension */
3038 if (index
->reuc
.length
> 0 && write_reuc_extension(index
, file
) < 0)
3041 /* get out the hash for all the contents we've appended to the file */
3042 git_filebuf_hash(&hash_final
, file
);
3043 git_oid_cpy(checksum
, &hash_final
);
3045 /* write it at the end of the file */
3046 if (git_filebuf_write(file
, hash_final
.id
, GIT_OID_RAWSZ
) < 0)
3049 /* file entries are no longer up to date */
3050 clear_uptodate(index
);
3055 int git_index_entry_stage(const git_index_entry
*entry
)
3057 return GIT_INDEX_ENTRY_STAGE(entry
);
3060 int git_index_entry_is_conflict(const git_index_entry
*entry
)
3062 return (GIT_INDEX_ENTRY_STAGE(entry
) > 0);
3065 typedef struct read_tree_data
{
3067 git_vector
*old_entries
;
3068 git_vector
*new_entries
;
3069 git_vector_cmp entry_cmp
;
3070 git_tree_cache
*tree
;
3073 static int read_tree_cb(
3074 const char *root
, const git_tree_entry
*tentry
, void *payload
)
3076 read_tree_data
*data
= payload
;
3077 git_index_entry
*entry
= NULL
, *old_entry
;
3078 git_buf path
= GIT_BUF_INIT
;
3081 if (git_tree_entry__is_tree(tentry
))
3084 if (git_buf_joinpath(&path
, root
, tentry
->filename
) < 0)
3087 if (index_entry_create(&entry
, INDEX_OWNER(data
->index
), path
.ptr
, NULL
, false) < 0)
3090 entry
->mode
= tentry
->attr
;
3091 git_oid_cpy(&entry
->id
, git_tree_entry_id(tentry
));
3093 /* look for corresponding old entry and copy data to new entry */
3094 if (data
->old_entries
!= NULL
&&
3095 !index_find_in_entries(
3096 &pos
, data
->old_entries
, data
->entry_cmp
, path
.ptr
, 0, 0) &&
3097 (old_entry
= git_vector_get(data
->old_entries
, pos
)) != NULL
&&
3098 entry
->mode
== old_entry
->mode
&&
3099 git_oid_equal(&entry
->id
, &old_entry
->id
))
3101 index_entry_cpy(entry
, old_entry
);
3102 entry
->flags_extended
= 0;
3105 index_entry_adjust_namemask(entry
, path
.size
);
3106 git_buf_dispose(&path
);
3108 if (git_vector_insert(data
->new_entries
, entry
) < 0) {
3109 index_entry_free(entry
);
3116 int git_index_read_tree(git_index
*index
, const git_tree
*tree
)
3119 git_vector entries
= GIT_VECTOR_INIT
;
3120 git_idxmap
*entries_map
;
3121 read_tree_data data
;
3125 if (git_idxmap_new(&entries_map
) < 0)
3128 git_vector_set_cmp(&entries
, index
->entries
._cmp
); /* match sort */
3131 data
.old_entries
= &index
->entries
;
3132 data
.new_entries
= &entries
;
3133 data
.entry_cmp
= index
->entries_search
;
3136 git_pool_clear(&index
->tree_pool
);
3138 git_vector_sort(&index
->entries
);
3140 if ((error
= git_tree_walk(tree
, GIT_TREEWALK_POST
, read_tree_cb
, &data
)) < 0)
3143 if ((error
= index_map_resize(entries_map
, entries
.length
, index
->ignore_case
)) < 0)
3146 git_vector_foreach(&entries
, i
, e
) {
3147 if ((error
= index_map_set(entries_map
, e
, index
->ignore_case
)) < 0) {
3148 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry into map");
3155 git_vector_sort(&entries
);
3157 if ((error
= git_index_clear(index
)) < 0) {
3158 /* well, this isn't good */;
3160 git_vector_swap(&entries
, &index
->entries
);
3161 entries_map
= git__swap(index
->entries_map
, entries_map
);
3167 git_vector_free(&entries
);
3168 git_idxmap_free(entries_map
);
3172 error
= git_tree_cache_read_tree(&index
->tree
, tree
, &index
->tree_pool
);
3177 static int git_index_read_iterator(
3179 git_iterator
*new_iterator
,
3180 size_t new_length_hint
)
3182 git_vector new_entries
= GIT_VECTOR_INIT
,
3183 remove_entries
= GIT_VECTOR_INIT
;
3184 git_idxmap
*new_entries_map
= NULL
;
3185 git_iterator
*index_iterator
= NULL
;
3186 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3187 const git_index_entry
*old_entry
, *new_entry
;
3188 git_index_entry
*entry
;
3192 assert((new_iterator
->flags
& GIT_ITERATOR_DONT_IGNORE_CASE
));
3194 if ((error
= git_vector_init(&new_entries
, new_length_hint
, index
->entries
._cmp
)) < 0 ||
3195 (error
= git_vector_init(&remove_entries
, index
->entries
.length
, NULL
)) < 0 ||
3196 (error
= git_idxmap_new(&new_entries_map
)) < 0)
3199 if (new_length_hint
&& (error
= index_map_resize(new_entries_map
, new_length_hint
,
3200 index
->ignore_case
)) < 0)
3203 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3204 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3206 if ((error
= git_iterator_for_index(&index_iterator
,
3207 git_index_owner(index
), index
, &opts
)) < 0 ||
3208 ((error
= git_iterator_current(&old_entry
, index_iterator
)) < 0 &&
3209 error
!= GIT_ITEROVER
) ||
3210 ((error
= git_iterator_current(&new_entry
, new_iterator
)) < 0 &&
3211 error
!= GIT_ITEROVER
))
3218 *remove_entry
= NULL
;
3223 if (old_entry
&& new_entry
)
3224 diff
= git_index_entry_cmp(old_entry
, new_entry
);
3225 else if (!old_entry
&& new_entry
)
3227 else if (old_entry
&& !new_entry
)
3233 remove_entry
= (git_index_entry
*)old_entry
;
3234 } else if (diff
> 0) {
3235 dup_entry
= (git_index_entry
*)new_entry
;
3237 /* Path and stage are equal, if the OID is equal, keep it to
3238 * keep the stat cache data.
3240 if (git_oid_equal(&old_entry
->id
, &new_entry
->id
) &&
3241 old_entry
->mode
== new_entry
->mode
) {
3242 add_entry
= (git_index_entry
*)old_entry
;
3244 dup_entry
= (git_index_entry
*)new_entry
;
3245 remove_entry
= (git_index_entry
*)old_entry
;
3250 if ((error
= index_entry_dup_nocache(&add_entry
, index
, dup_entry
)) < 0)
3253 index_entry_adjust_namemask(add_entry
,
3254 ((struct entry_internal
*)add_entry
)->pathlen
);
3257 /* invalidate this path in the tree cache if this is new (to
3258 * invalidate the parent trees)
3260 if (dup_entry
&& !remove_entry
&& index
->tree
)
3261 git_tree_cache_invalidate_path(index
->tree
, dup_entry
->path
);
3264 if ((error
= git_vector_insert(&new_entries
, add_entry
)) == 0)
3265 error
= index_map_set(new_entries_map
, add_entry
,
3266 index
->ignore_case
);
3269 if (remove_entry
&& error
>= 0)
3270 error
= git_vector_insert(&remove_entries
, remove_entry
);
3273 git_error_set(GIT_ERROR_INDEX
, "failed to insert entry");
3278 if ((error
= git_iterator_advance(&old_entry
, index_iterator
)) < 0 &&
3279 error
!= GIT_ITEROVER
)
3284 if ((error
= git_iterator_advance(&new_entry
, new_iterator
)) < 0 &&
3285 error
!= GIT_ITEROVER
)
3290 if ((error
= git_index_name_clear(index
)) < 0 ||
3291 (error
= git_index_reuc_clear(index
)) < 0)
3294 git_vector_swap(&new_entries
, &index
->entries
);
3295 new_entries_map
= git__swap(index
->entries_map
, new_entries_map
);
3297 git_vector_foreach(&remove_entries
, i
, entry
) {
3299 git_tree_cache_invalidate_path(index
->tree
, entry
->path
);
3301 index_entry_free(entry
);
3304 clear_uptodate(index
);
3310 git_idxmap_free(new_entries_map
);
3311 git_vector_free(&new_entries
);
3312 git_vector_free(&remove_entries
);
3313 git_iterator_free(index_iterator
);
3317 int git_index_read_index(
3319 const git_index
*new_index
)
3321 git_iterator
*new_iterator
= NULL
;
3322 git_iterator_options opts
= GIT_ITERATOR_OPTIONS_INIT
;
3325 opts
.flags
= GIT_ITERATOR_DONT_IGNORE_CASE
|
3326 GIT_ITERATOR_INCLUDE_CONFLICTS
;
3328 if ((error
= git_iterator_for_index(&new_iterator
,
3329 git_index_owner(new_index
), (git_index
*)new_index
, &opts
)) < 0 ||
3330 (error
= git_index_read_iterator(index
, new_iterator
,
3331 new_index
->entries
.length
)) < 0)
3335 git_iterator_free(new_iterator
);
3339 git_repository
*git_index_owner(const git_index
*index
)
3341 return INDEX_OWNER(index
);
3345 INDEX_ACTION_NONE
= 0,
3346 INDEX_ACTION_UPDATE
= 1,
3347 INDEX_ACTION_REMOVE
= 2,
3348 INDEX_ACTION_ADDALL
= 3,
3351 int git_index_add_all(
3353 const git_strarray
*paths
,
3355 git_index_matched_path_cb cb
,
3359 git_repository
*repo
;
3360 git_iterator
*wditer
= NULL
;
3362 bool no_fnmatch
= (flags
& GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
) != 0;
3366 repo
= INDEX_OWNER(index
);
3367 if ((error
= git_repository__ensure_not_bare(repo
, "index add all")) < 0)
3370 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3373 /* optionally check that pathspec doesn't mention any ignored files */
3374 if ((flags
& GIT_INDEX_ADD_CHECK_PATHSPEC
) != 0 &&
3375 (flags
& GIT_INDEX_ADD_FORCE
) == 0 &&
3376 (error
= git_ignore__check_pathspec_for_exact_ignores(
3377 repo
, &ps
.pathspec
, no_fnmatch
)) < 0)
3380 error
= index_apply_to_wd_diff(index
, INDEX_ACTION_ADDALL
, paths
, flags
, cb
, payload
);
3383 git_error_set_after_callback(error
);
3386 git_iterator_free(wditer
);
3387 git_pathspec__clear(&ps
);
3392 struct foreach_diff_data
{
3394 const git_pathspec
*pathspec
;
3396 git_index_matched_path_cb cb
;
3400 static int apply_each_file(const git_diff_delta
*delta
, float progress
, void *payload
)
3402 struct foreach_diff_data
*data
= payload
;
3403 const char *match
, *path
;
3406 GIT_UNUSED(progress
);
3408 path
= delta
->old_file
.path
;
3410 /* We only want those which match the pathspecs */
3411 if (!git_pathspec__match(
3412 &data
->pathspec
->pathspec
, path
, false, (bool)data
->index
->ignore_case
,
3417 error
= data
->cb(path
, match
, data
->payload
);
3419 if (error
> 0) /* skip this entry */
3421 if (error
< 0) /* actual error */
3424 /* If the workdir item does not exist, remove it from the index. */
3425 if ((delta
->new_file
.flags
& GIT_DIFF_FLAG_EXISTS
) == 0)
3426 error
= git_index_remove_bypath(data
->index
, path
);
3428 error
= git_index_add_bypath(data
->index
, delta
->new_file
.path
);
3433 static int index_apply_to_wd_diff(git_index
*index
, int action
, const git_strarray
*paths
,
3435 git_index_matched_path_cb cb
, void *payload
)
3440 git_repository
*repo
;
3441 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
3442 struct foreach_diff_data data
= {
3451 assert(action
== INDEX_ACTION_UPDATE
|| action
== INDEX_ACTION_ADDALL
);
3453 repo
= INDEX_OWNER(index
);
3456 return create_index_error(-1,
3457 "cannot run update; the index is not backed up by a repository.");
3461 * We do the matching ourselves intead of passing the list to
3462 * diff because we want to tell the callback which one
3463 * matched, which we do not know if we ask diff to filter for us.
3465 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3468 opts
.flags
= GIT_DIFF_INCLUDE_TYPECHANGE
;
3469 if (action
== INDEX_ACTION_ADDALL
) {
3470 opts
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
|
3471 GIT_DIFF_RECURSE_UNTRACKED_DIRS
;
3473 if (flags
== GIT_INDEX_ADD_FORCE
)
3474 opts
.flags
|= GIT_DIFF_INCLUDE_IGNORED
;
3477 if ((error
= git_diff_index_to_workdir(&diff
, repo
, index
, &opts
)) < 0)
3480 data
.pathspec
= &ps
;
3481 error
= git_diff_foreach(diff
, apply_each_file
, NULL
, NULL
, NULL
, &data
);
3482 git_diff_free(diff
);
3484 if (error
) /* make sure error is set if callback stopped iteration */
3485 git_error_set_after_callback(error
);
3488 git_pathspec__clear(&ps
);
3492 static int index_apply_to_all(
3495 const git_strarray
*paths
,
3496 git_index_matched_path_cb cb
,
3503 git_buf path
= GIT_BUF_INIT
;
3507 if ((error
= git_pathspec__init(&ps
, paths
)) < 0)
3510 git_vector_sort(&index
->entries
);
3512 for (i
= 0; !error
&& i
< index
->entries
.length
; ++i
) {
3513 git_index_entry
*entry
= git_vector_get(&index
->entries
, i
);
3515 /* check if path actually matches */
3516 if (!git_pathspec__match(
3517 &ps
.pathspec
, entry
->path
, false, (bool)index
->ignore_case
,
3521 /* issue notification callback if requested */
3522 if (cb
&& (error
= cb(entry
->path
, match
, payload
)) != 0) {
3523 if (error
> 0) { /* return > 0 means skip this one */
3527 if (error
< 0) /* return < 0 means abort */
3531 /* index manipulation may alter entry, so don't depend on it */
3532 if ((error
= git_buf_sets(&path
, entry
->path
)) < 0)
3536 case INDEX_ACTION_NONE
:
3538 case INDEX_ACTION_UPDATE
:
3539 error
= git_index_add_bypath(index
, path
.ptr
);
3541 if (error
== GIT_ENOTFOUND
) {
3544 error
= git_index_remove_bypath(index
, path
.ptr
);
3546 if (!error
) /* back up foreach if we removed this */
3550 case INDEX_ACTION_REMOVE
:
3551 if (!(error
= git_index_remove_bypath(index
, path
.ptr
)))
3552 i
--; /* back up foreach if we removed this */
3555 git_error_set(GIT_ERROR_INVALID
, "unknown index action %d", action
);
3561 git_buf_dispose(&path
);
3562 git_pathspec__clear(&ps
);
3567 int git_index_remove_all(
3569 const git_strarray
*pathspec
,
3570 git_index_matched_path_cb cb
,
3573 int error
= index_apply_to_all(
3574 index
, INDEX_ACTION_REMOVE
, pathspec
, cb
, payload
);
3576 if (error
) /* make sure error is set if callback stopped iteration */
3577 git_error_set_after_callback(error
);
3582 int git_index_update_all(
3584 const git_strarray
*pathspec
,
3585 git_index_matched_path_cb cb
,
3588 int error
= index_apply_to_wd_diff(index
, INDEX_ACTION_UPDATE
, pathspec
, 0, cb
, payload
);
3589 if (error
) /* make sure error is set if callback stopped iteration */
3590 git_error_set_after_callback(error
);
3595 int git_index_snapshot_new(git_vector
*snap
, git_index
*index
)
3599 GIT_REFCOUNT_INC(index
);
3601 git_atomic_inc(&index
->readers
);
3602 git_vector_sort(&index
->entries
);
3604 error
= git_vector_dup(snap
, &index
->entries
, index
->entries
._cmp
);
3607 git_index_snapshot_release(snap
, index
);
3612 void git_index_snapshot_release(git_vector
*snap
, git_index
*index
)
3614 git_vector_free(snap
);
3616 git_atomic_dec(&index
->readers
);
3618 git_index_free(index
);
3621 int git_index_snapshot_find(
3622 size_t *out
, git_vector
*entries
, git_vector_cmp entry_srch
,
3623 const char *path
, size_t path_len
, int stage
)
3625 return index_find_in_entries(out
, entries
, entry_srch
, path
, path_len
, stage
);
3628 int git_indexwriter_init(
3629 git_indexwriter
*writer
,
3634 GIT_REFCOUNT_INC(index
);
3636 writer
->index
= index
;
3638 if (!index
->index_file_path
)
3639 return create_index_error(-1,
3640 "failed to write index: The index is in-memory only");
3642 if ((error
= git_filebuf_open(
3643 &writer
->file
, index
->index_file_path
, GIT_FILEBUF_HASH_CONTENTS
, GIT_INDEX_FILE_MODE
)) < 0) {
3645 if (error
== GIT_ELOCKED
)
3646 git_error_set(GIT_ERROR_INDEX
, "the index is locked; this might be due to a concurrent or crashed process");
3651 writer
->should_write
= 1;
3656 int git_indexwriter_init_for_operation(
3657 git_indexwriter
*writer
,
3658 git_repository
*repo
,
3659 unsigned int *checkout_strategy
)
3664 if ((error
= git_repository_index__weakptr(&index
, repo
)) < 0 ||
3665 (error
= git_indexwriter_init(writer
, index
)) < 0)
3668 writer
->should_write
= (*checkout_strategy
& GIT_CHECKOUT_DONT_WRITE_INDEX
) == 0;
3669 *checkout_strategy
|= GIT_CHECKOUT_DONT_WRITE_INDEX
;
3674 int git_indexwriter_commit(git_indexwriter
*writer
)
3677 git_oid checksum
= {{ 0 }};
3679 if (!writer
->should_write
)
3682 git_vector_sort(&writer
->index
->entries
);
3683 git_vector_sort(&writer
->index
->reuc
);
3685 if ((error
= write_index(&checksum
, writer
->index
, &writer
->file
)) < 0) {
3686 git_indexwriter_cleanup(writer
);
3690 if ((error
= git_filebuf_commit(&writer
->file
)) < 0)
3693 if ((error
= git_futils_filestamp_check(
3694 &writer
->index
->stamp
, writer
->index
->index_file_path
)) < 0) {
3695 git_error_set(GIT_ERROR_OS
, "could not read index timestamp");
3699 writer
->index
->dirty
= 0;
3700 writer
->index
->on_disk
= 1;
3701 git_oid_cpy(&writer
->index
->checksum
, &checksum
);
3703 git_index_free(writer
->index
);
3704 writer
->index
= NULL
;
3709 void git_indexwriter_cleanup(git_indexwriter
*writer
)
3711 git_filebuf_cleanup(&writer
->file
);
3713 git_index_free(writer
->index
);
3714 writer
->index
= NULL
;
3717 /* Deprecated functions */
3719 int git_index_add_frombuffer(
3720 git_index
*index
, const git_index_entry
*source_entry
,
3721 const void *buffer
, size_t len
)
3723 return git_index_add_from_buffer(index
, source_entry
, buffer
, len
);