Skip to content

Commit cfbd08a

Browse files
author
Vicent Martí
committed
Merge pull request #1630 from arrbee/index-read-tree-preserve-stat-cache
Make git_index_read_tree preserve stat cache where possible
2 parents 17ef7db + 03a8907 commit cfbd08a

File tree

1 file changed

+54
-14
lines changed

1 file changed

+54
-14
lines changed

src/index.c

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -359,22 +359,25 @@ void git_index_free(git_index *index)
359359
GIT_REFCOUNT_DEC(index, index_free);
360360
}
361361

362-
void git_index_clear(git_index *index)
362+
static void index_entries_free(git_vector *entries)
363363
{
364364
size_t i;
365365

366-
assert(index);
367-
368-
for (i = 0; i < index->entries.length; ++i) {
369-
git_index_entry *e;
370-
e = git_vector_get(&index->entries, i);
366+
for (i = 0; i < entries->length; ++i) {
367+
git_index_entry *e = git_vector_get(entries, i);
371368
git__free(e->path);
372369
git__free(e);
373370
}
374-
git_vector_clear(&index->entries);
375371

376-
git_index_reuc_clear(index);
372+
git_vector_clear(entries);
373+
}
377374

375+
void git_index_clear(git_index *index)
376+
{
377+
assert(index);
378+
379+
index_entries_free(&index->entries);
380+
git_index_reuc_clear(index);
378381
git_index_name_clear(index);
379382

380383
git_futils_filestamp_set(&index->stamp, NULL);
@@ -1951,13 +1954,14 @@ int git_index_entry_stage(const git_index_entry *entry)
19511954

19521955
typedef struct read_tree_data {
19531956
git_index *index;
1954-
git_transfer_progress *stats;
1957+
git_vector *old_entries;
19551958
} read_tree_data;
19561959

1957-
static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *data)
1960+
static int read_tree_cb(
1961+
const char *root, const git_tree_entry *tentry, void *payload)
19581962
{
1959-
git_index *index = (git_index *)data;
1960-
git_index_entry *entry = NULL;
1963+
read_tree_data *data = payload;
1964+
git_index_entry *entry = NULL, *old_entry;
19611965
git_buf path = GIT_BUF_INIT;
19621966

19631967
if (git_tree_entry__is_tree(tentry))
@@ -1972,6 +1976,25 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19721976
entry->mode = tentry->attr;
19731977
entry->oid = tentry->oid;
19741978

1979+
/* look for corresponding old entry and copy data to new entry */
1980+
if (data->old_entries) {
1981+
size_t pos;
1982+
struct entry_srch_key skey;
1983+
1984+
skey.path = path.ptr;
1985+
skey.stage = 0;
1986+
1987+
if (!git_vector_bsearch2(
1988+
&pos, data->old_entries, data->index->entries_search, &skey) &&
1989+
(old_entry = git_vector_get(data->old_entries, pos)) != NULL &&
1990+
entry->mode == old_entry->mode &&
1991+
git_oid_equal(&entry->oid, &old_entry->oid))
1992+
{
1993+
memcpy(entry, old_entry, sizeof(*entry));
1994+
entry->flags_extended = 0;
1995+
}
1996+
}
1997+
19751998
if (path.size < GIT_IDXENTRY_NAMEMASK)
19761999
entry->flags = path.size & GIT_IDXENTRY_NAMEMASK;
19772000
else
@@ -1980,7 +2003,7 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19802003
entry->path = git_buf_detach(&path);
19812004
git_buf_free(&path);
19822005

1983-
if (git_vector_insert(&index->entries, entry) < 0) {
2006+
if (git_vector_insert(&data->index->entries, entry) < 0) {
19842007
index_entry_free(entry);
19852008
return -1;
19862009
}
@@ -1990,9 +2013,26 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da
19902013

19912014
int git_index_read_tree(git_index *index, const git_tree *tree)
19922015
{
2016+
int error = 0;
2017+
git_vector entries = GIT_VECTOR_INIT;
2018+
read_tree_data data;
2019+
2020+
git_vector_sort(&index->entries);
2021+
2022+
entries._cmp = index->entries._cmp;
2023+
git_vector_swap(&entries, &index->entries);
2024+
19932025
git_index_clear(index);
19942026

1995-
return git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, index);
2027+
data.index = index;
2028+
data.old_entries = &entries;
2029+
2030+
error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data);
2031+
2032+
index_entries_free(&entries);
2033+
git_vector_sort(&index->entries);
2034+
2035+
return error;
19962036
}
19972037

19982038
git_repository *git_index_owner(const git_index *index)

0 commit comments

Comments
 (0)