mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-22 08:00:07 +00:00
Merge pull request #3236 from libgit2/cmn/index-checksum
Use the checksum to check whether an index has been modified
This commit is contained in:
commit
883cb642cb
@ -273,6 +273,18 @@ GIT_EXTERN(int) git_index_write(git_index *index);
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(const char *) git_index_path(const git_index *index);
|
GIT_EXTERN(const char *) git_index_path(const git_index *index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the checksum of the index
|
||||||
|
*
|
||||||
|
* This checksum is the SHA-1 hash over the index file (except the
|
||||||
|
* last 20 bytes which are the checksum itself). In cases where the
|
||||||
|
* index does not exist on-disk, it will be zeroed out.
|
||||||
|
*
|
||||||
|
* @param index an existing index object
|
||||||
|
* @return a pointer to the checksum of the index
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(const git_oid *) git_index_checksum(git_index *index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a tree into the index file with stats
|
* Read a tree into the index file with stats
|
||||||
*
|
*
|
||||||
|
53
src/index.c
53
src/index.c
@ -116,7 +116,7 @@ static int read_header(struct index_header *dest, const void *buffer);
|
|||||||
|
|
||||||
static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
|
static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
|
||||||
static bool is_index_extended(git_index *index);
|
static bool is_index_extended(git_index *index);
|
||||||
static int write_index(git_index *index, git_filebuf *file);
|
static int write_index(git_oid *checksum, git_index *index, git_filebuf *file);
|
||||||
|
|
||||||
static void index_entry_free(git_index_entry *entry);
|
static void index_entry_free(git_index_entry *entry);
|
||||||
static void index_entry_reuc_free(git_index_reuc_entry *reuc);
|
static void index_entry_reuc_free(git_index_reuc_entry *reuc);
|
||||||
@ -598,6 +598,38 @@ int git_index_caps(const git_index *index)
|
|||||||
(index->no_symlinks ? GIT_INDEXCAP_NO_SYMLINKS : 0));
|
(index->no_symlinks ? GIT_INDEXCAP_NO_SYMLINKS : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const git_oid *git_index_checksum(git_index *index)
|
||||||
|
{
|
||||||
|
return &index->checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 1 for changed, 0 for not changed and <0 for errors
|
||||||
|
*/
|
||||||
|
static int compare_checksum(git_index *index)
|
||||||
|
{
|
||||||
|
int fd, error;
|
||||||
|
ssize_t bytes_read;
|
||||||
|
git_oid checksum = {{ 0 }};
|
||||||
|
|
||||||
|
if ((fd = p_open(index->index_file_path, O_RDONLY)) < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
if ((error = p_lseek(fd, -20, SEEK_END)) < 0) {
|
||||||
|
p_close(fd);
|
||||||
|
giterr_set(GITERR_OS, "failed to seek to end of file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read = p_read(fd, &checksum, GIT_OID_RAWSZ);
|
||||||
|
p_close(fd);
|
||||||
|
|
||||||
|
if (bytes_read < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return !!git_oid_cmp(&checksum, &index->checksum);
|
||||||
|
}
|
||||||
|
|
||||||
int git_index_read(git_index *index, int force)
|
int git_index_read(git_index *index, int force)
|
||||||
{
|
{
|
||||||
int error = 0, updated;
|
int error = 0, updated;
|
||||||
@ -616,8 +648,8 @@ int git_index_read(git_index *index, int force)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated = git_futils_filestamp_check(&stamp, index->index_file_path);
|
if ((updated = git_futils_filestamp_check(&stamp, index->index_file_path) < 0) ||
|
||||||
if (updated < 0) {
|
((updated = compare_checksum(index)) < 0)) {
|
||||||
giterr_set(
|
giterr_set(
|
||||||
GITERR_INDEX,
|
GITERR_INDEX,
|
||||||
"Failed to read index: '%s' no longer exists",
|
"Failed to read index: '%s' no longer exists",
|
||||||
@ -647,15 +679,13 @@ int git_index_read(git_index *index, int force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int git_index__changed_relative_to(
|
int git_index__changed_relative_to(
|
||||||
git_index *index, const git_futils_filestamp *fs)
|
git_index *index, const git_oid *checksum)
|
||||||
{
|
{
|
||||||
/* attempt to update index (ignoring errors) */
|
/* attempt to update index (ignoring errors) */
|
||||||
if (git_index_read(index, false) < 0)
|
if (git_index_read(index, false) < 0)
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
|
|
||||||
return (index->stamp.mtime != fs->mtime ||
|
return !!git_oid_cmp(&index->checksum, checksum);
|
||||||
index->stamp.size != fs->size ||
|
|
||||||
index->stamp.ino != fs->ino);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2092,6 +2122,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_oid_cpy(&index->checksum, &checksum_calculated);
|
||||||
|
|
||||||
#undef seek_forward
|
#undef seek_forward
|
||||||
|
|
||||||
/* Entries are stored case-sensitively on disk, so re-sort now if
|
/* Entries are stored case-sensitively on disk, so re-sort now if
|
||||||
@ -2355,7 +2387,7 @@ static int write_tree_extension(git_index *index, git_filebuf *file)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_index(git_index *index, git_filebuf *file)
|
static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
|
||||||
{
|
{
|
||||||
git_oid hash_final;
|
git_oid hash_final;
|
||||||
struct index_header header;
|
struct index_header header;
|
||||||
@ -2391,6 +2423,7 @@ static int write_index(git_index *index, git_filebuf *file)
|
|||||||
|
|
||||||
/* get out the hash for all the contents we've appended to the file */
|
/* get out the hash for all the contents we've appended to the file */
|
||||||
git_filebuf_hash(&hash_final, file);
|
git_filebuf_hash(&hash_final, file);
|
||||||
|
git_oid_cpy(checksum, &hash_final);
|
||||||
|
|
||||||
/* write it at the end of the file */
|
/* write it at the end of the file */
|
||||||
return git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ);
|
return git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ);
|
||||||
@ -2953,6 +2986,7 @@ int git_indexwriter_init_for_operation(
|
|||||||
int git_indexwriter_commit(git_indexwriter *writer)
|
int git_indexwriter_commit(git_indexwriter *writer)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
git_oid checksum = {{ 0 }};
|
||||||
|
|
||||||
if (!writer->should_write)
|
if (!writer->should_write)
|
||||||
return 0;
|
return 0;
|
||||||
@ -2962,7 +2996,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
|
|||||||
|
|
||||||
git_vector_sort(&writer->index->reuc);
|
git_vector_sort(&writer->index->reuc);
|
||||||
|
|
||||||
if ((error = write_index(writer->index, &writer->file)) < 0) {
|
if ((error = write_index(&checksum, writer->index, &writer->file)) < 0) {
|
||||||
git_indexwriter_cleanup(writer);
|
git_indexwriter_cleanup(writer);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -2977,6 +3011,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
writer->index->on_disk = 1;
|
writer->index->on_disk = 1;
|
||||||
|
git_oid_cpy(&writer->index->checksum, &checksum);
|
||||||
|
|
||||||
git_index_free(writer->index);
|
git_index_free(writer->index);
|
||||||
writer->index = NULL;
|
writer->index = NULL;
|
||||||
|
@ -22,6 +22,7 @@ struct git_index {
|
|||||||
|
|
||||||
char *index_file_path;
|
char *index_file_path;
|
||||||
git_futils_filestamp stamp;
|
git_futils_filestamp stamp;
|
||||||
|
git_oid checksum; /* checksum at the end of the file */
|
||||||
|
|
||||||
git_vector entries;
|
git_vector entries;
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ GIT_INLINE(const git_futils_filestamp *) git_index__filestamp(git_index *index)
|
|||||||
return &index->stamp;
|
return &index->stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int git_index__changed_relative_to(git_index *index, const git_futils_filestamp *fs);
|
extern int git_index__changed_relative_to(git_index *index, const git_oid *checksum);
|
||||||
|
|
||||||
/* Copy the current entries vector *and* increment the index refcount.
|
/* Copy the current entries vector *and* increment the index refcount.
|
||||||
* Call `git_index__release_snapshot` when done.
|
* Call `git_index__release_snapshot` when done.
|
||||||
|
@ -1946,7 +1946,7 @@ static int submodule_cache_refresh(git_submodule_cache *cache, int refresh)
|
|||||||
update_index = update_head = update_gitmod = true;
|
update_index = update_head = update_gitmod = true;
|
||||||
else {
|
else {
|
||||||
update_index =
|
update_index =
|
||||||
!idx || git_index__changed_relative_to(idx, &cache->index_stamp);
|
!idx || git_index__changed_relative_to(idx, &cache->index_checksum);
|
||||||
update_head =
|
update_head =
|
||||||
!head || !git_oid_equal(&cache->head_id, git_tree_id(head));
|
!head || !git_oid_equal(&cache->head_id, git_tree_id(head));
|
||||||
|
|
||||||
@ -1984,8 +1984,7 @@ static int submodule_cache_refresh(git_submodule_cache *cache, int refresh)
|
|||||||
if ((error = submodule_cache_refresh_from_index(cache, idx)) < 0)
|
if ((error = submodule_cache_refresh_from_index(cache, idx)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
git_futils_filestamp_set(
|
git_oid_cpy(&cache->index_checksum, git_index_checksum(idx));
|
||||||
&cache->index_stamp, git_index__filestamp(idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add submodule information from HEAD */
|
/* add submodule information from HEAD */
|
||||||
|
@ -110,7 +110,7 @@ typedef struct {
|
|||||||
|
|
||||||
/* cache invalidation data */
|
/* cache invalidation data */
|
||||||
git_oid head_id;
|
git_oid head_id;
|
||||||
git_futils_filestamp index_stamp;
|
git_oid index_checksum;
|
||||||
git_buf gitmodules_path;
|
git_buf gitmodules_path;
|
||||||
git_futils_filestamp gitmodules_stamp;
|
git_futils_filestamp gitmodules_stamp;
|
||||||
git_futils_filestamp config_stamp;
|
git_futils_filestamp config_stamp;
|
||||||
|
@ -103,8 +103,8 @@ void test_index_tests__default_test_index(void)
|
|||||||
git_index_entry *e = entries[test_entries[i].index];
|
git_index_entry *e = entries[test_entries[i].index];
|
||||||
|
|
||||||
cl_assert_equal_s(e->path, test_entries[i].path);
|
cl_assert_equal_s(e->path, test_entries[i].path);
|
||||||
cl_assert(e->mtime.seconds == test_entries[i].mtime);
|
cl_assert_equal_i(e->mtime.seconds, test_entries[i].mtime);
|
||||||
cl_assert(e->file_size == test_entries[i].file_size);
|
cl_assert_equal_i(e->file_size, test_entries[i].file_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
git_index_free(index);
|
git_index_free(index);
|
||||||
|
Loading…
Reference in New Issue
Block a user