Skip to content

Commit 3aa122f

Browse files
benpeartdscho
authored andcommitted
Merge pull request #23 from benpeart/unpack-trees-with-cache-tree-gvfs
Unpack trees with cache tree gvfs
2 parents 2b232b7 + ba70846 commit 3aa122f

12 files changed

+343
-22
lines changed

cache-tree.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "tree-walk.h"
55
#include "cache-tree.h"
66
#include "object-store.h"
7+
#include "replace-object.h"
78
#include "gvfs.h"
89

910
#ifndef DEBUG_CACHE_TREE
@@ -457,7 +458,9 @@ int cache_tree_update(struct index_state *istate, int flags)
457458

458459
if (i)
459460
return i;
461+
trace_performance_enter();
460462
i = update_one(it, cache, entries, "", 0, &skip, flags);
463+
trace_performance_leave("cache_tree_update");
461464
if (i < 0)
462465
return i;
463466
istate->cache_changed |= CACHE_TREE_CHANGED;
@@ -742,3 +745,80 @@ int cache_tree_matches_traversal(struct cache_tree *root,
742745
return it->entry_count;
743746
return 0;
744747
}
748+
749+
static void verify_one(struct index_state *istate,
750+
struct cache_tree *it,
751+
struct strbuf *path)
752+
{
753+
int i, pos, len = path->len;
754+
struct strbuf tree_buf = STRBUF_INIT;
755+
struct object_id new_oid;
756+
757+
for (i = 0; i < it->subtree_nr; i++) {
758+
strbuf_addf(path, "%s/", it->down[i]->name);
759+
verify_one(istate, it->down[i]->cache_tree, path);
760+
strbuf_setlen(path, len);
761+
}
762+
763+
if (it->entry_count < 0 ||
764+
/* no verification on tests (t7003) that replace trees */
765+
lookup_replace_object(the_repository, &it->oid) != &it->oid)
766+
return;
767+
768+
if (path->len) {
769+
pos = index_name_pos(istate, path->buf, path->len);
770+
pos = -pos - 1;
771+
} else {
772+
pos = 0;
773+
}
774+
775+
i = 0;
776+
while (i < it->entry_count) {
777+
struct cache_entry *ce = istate->cache[pos + i];
778+
const char *slash;
779+
struct cache_tree_sub *sub = NULL;
780+
const struct object_id *oid;
781+
const char *name;
782+
unsigned mode;
783+
int entlen;
784+
785+
if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE))
786+
BUG("%s with flags 0x%x should not be in cache-tree",
787+
ce->name, ce->ce_flags);
788+
name = ce->name + path->len;
789+
slash = strchr(name, '/');
790+
if (slash) {
791+
entlen = slash - name;
792+
sub = find_subtree(it, ce->name + path->len, entlen, 0);
793+
if (!sub || sub->cache_tree->entry_count < 0)
794+
BUG("bad subtree '%.*s'", entlen, name);
795+
oid = &sub->cache_tree->oid;
796+
mode = S_IFDIR;
797+
i += sub->cache_tree->entry_count;
798+
} else {
799+
oid = &ce->oid;
800+
mode = ce->ce_mode;
801+
entlen = ce_namelen(ce) - path->len;
802+
i++;
803+
}
804+
strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0');
805+
strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz);
806+
}
807+
hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid);
808+
if (oidcmp(&new_oid, &it->oid))
809+
BUG("cache-tree for path %.*s does not match. "
810+
"Expected %s got %s", len, path->buf,
811+
oid_to_hex(&new_oid), oid_to_hex(&it->oid));
812+
strbuf_setlen(path, len);
813+
strbuf_release(&tree_buf);
814+
}
815+
816+
void cache_tree_verify(struct index_state *istate)
817+
{
818+
struct strbuf path = STRBUF_INIT;
819+
820+
if (!istate->cache_tree)
821+
return;
822+
verify_one(istate, istate->cache_tree, &path);
823+
strbuf_release(&path);
824+
}

cache-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
3232

3333
int cache_tree_fully_valid(struct cache_tree *);
3434
int cache_tree_update(struct index_state *, int);
35+
void cache_tree_verify(struct index_state *);
3536

3637
/* bitmasks to write_cache_as_tree flags */
3738
#define WRITE_TREE_MISSING_OK 1

diff-lib.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ static int diff_cache(struct rev_info *revs,
518518
int run_diff_index(struct rev_info *revs, int cached)
519519
{
520520
struct object_array_entry *ent;
521-
uint64_t start = getnanotime();
522521

523522
if (revs->pending.nr != 1)
524523
BUG("run_diff_index must be passed exactly one tree");
@@ -531,7 +530,7 @@ int run_diff_index(struct rev_info *revs, int cached)
531530
diffcore_fix_diff_index(&revs->diffopt);
532531
diffcore_std(&revs->diffopt);
533532
diff_flush(&revs->diffopt);
534-
trace_performance_since(start, "diff-index");
533+
trace_performance_leave("diff-index");
535534
return 0;
536535
}
537536

dir.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,10 +2341,13 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
23412341
const char *path, int len, const struct pathspec *pathspec)
23422342
{
23432343
struct untracked_cache_dir *untracked;
2344-
uint64_t start = getnanotime();
23452344

2346-
if (has_symlink_leading_path(path, len))
2345+
trace_performance_enter();
2346+
2347+
if (has_symlink_leading_path(path, len)) {
2348+
trace_performance_leave("read directory %.*s", len, path);
23472349
return dir->nr;
2350+
}
23482351

23492352
untracked = validate_untracked_cache(dir, len, pathspec);
23502353
if (!untracked)
@@ -2380,7 +2383,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
23802383
dir->nr = i;
23812384
}
23822385

2383-
trace_performance_since(start, "read directory %.*s", len, path);
2386+
trace_performance_leave("read directory %.*s", len, path);
23842387
if (dir->untracked) {
23852388
static int force_untracked_cache = -1;
23862389
static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS);

name-hash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,10 +578,10 @@ static void threaded_lazy_init_name_hash(
578578

579579
static void lazy_init_name_hash(struct index_state *istate)
580580
{
581-
uint64_t start = getnanotime();
582581

583582
if (istate->name_hash_initialized)
584583
return;
584+
trace_performance_enter();
585585
hashmap_init(&istate->name_hash, cache_entry_cmp, NULL, istate->cache_nr);
586586
hashmap_init(&istate->dir_hash, dir_entry_cmp, NULL, istate->cache_nr);
587587

@@ -602,7 +602,7 @@ static void lazy_init_name_hash(struct index_state *istate)
602602
}
603603

604604
istate->name_hash_initialized = 1;
605-
trace_performance_since(start, "initialize name hash");
605+
trace_performance_leave("initialize name hash");
606606
}
607607

608608
/*

preload-index.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ void preload_index(struct index_state *index, const struct pathspec *pathspec)
7676
{
7777
int threads, i, work, offset;
7878
struct thread_data data[MAX_PARALLEL];
79-
uint64_t start = getnanotime();
8079

8180
if (!core_preload_index)
8281
return;
@@ -86,6 +85,7 @@ void preload_index(struct index_state *index, const struct pathspec *pathspec)
8685
threads = 2;
8786
if (threads < 2)
8887
return;
88+
trace_performance_enter();
8989
if (threads > MAX_PARALLEL)
9090
threads = MAX_PARALLEL;
9191
offset = 0;
@@ -108,7 +108,7 @@ void preload_index(struct index_state *index, const struct pathspec *pathspec)
108108
if (pthread_join(p->pthread, NULL))
109109
die("unable to join threaded lstat");
110110
}
111-
trace_performance_since(start, "preload index");
111+
trace_performance_leave("preload index");
112112
enable_fscache(0);
113113
}
114114
#endif

read-cache.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
14781478
const char *typechange_fmt;
14791479
const char *added_fmt;
14801480
const char *unmerged_fmt;
1481-
uint64_t start = getnanotime();
14821481

1482+
trace_performance_enter();
14831483
modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
14841484
deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
14851485
typechange_fmt = (in_porcelain ? "T\t%s\n" : "%s needs update\n");
@@ -1551,7 +1551,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
15511551
replace_index_entry(istate, i, new_entry);
15521552
}
15531553
enable_fscache(0);
1554-
trace_performance_since(start, "refresh index");
1554+
trace_performance_leave("refresh index");
15551555
return has_errors;
15561556
}
15571557

@@ -2007,7 +2007,6 @@ static void freshen_shared_index(const char *shared_index, int warn)
20072007
int read_index_from(struct index_state *istate, const char *path,
20082008
const char *gitdir)
20092009
{
2010-
uint64_t start = getnanotime();
20112010
struct split_index *split_index;
20122011
int ret;
20132012
char *base_oid_hex;
@@ -2017,15 +2016,17 @@ int read_index_from(struct index_state *istate, const char *path,
20172016
if (istate->initialized)
20182017
return istate->cache_nr;
20192018

2019+
trace_performance_enter();
20202020
ret = do_read_index(istate, path, 0);
2021-
trace_performance_since(start, "read cache %s", path);
2021+
trace_performance_leave("read cache %s", path);
20222022

20232023
split_index = istate->split_index;
20242024
if (!split_index || is_null_oid(&split_index->base_oid)) {
20252025
post_read_index_from(istate);
20262026
return ret;
20272027
}
20282028

2029+
trace_performance_enter();
20292030
if (split_index->base)
20302031
discard_index(split_index->base);
20312032
else
@@ -2042,8 +2043,8 @@ int read_index_from(struct index_state *istate, const char *path,
20422043
freshen_shared_index(base_path, 0);
20432044
merge_base_index(istate);
20442045
post_read_index_from(istate);
2045-
trace_performance_since(start, "read cache %s", base_path);
20462046
free(base_path);
2047+
trace_performance_leave("read cache %s", base_path);
20472048
return ret;
20482049
}
20492050

@@ -2752,6 +2753,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
27522753
int new_shared_index, ret;
27532754
struct split_index *si = istate->split_index;
27542755

2756+
if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0))
2757+
cache_tree_verify(istate);
2758+
27552759
if ((flags & SKIP_IF_UNCHANGED) && !istate->cache_changed) {
27562760
if (flags & COMMIT_LOCK)
27572761
rollback_lock_file(lock);
@@ -2948,6 +2952,8 @@ void move_index_extensions(struct index_state *dst, struct index_state *src)
29482952
{
29492953
dst->untracked = src->untracked;
29502954
src->untracked = NULL;
2955+
dst->cache_tree = src->cache_tree;
2956+
src->cache_tree = NULL;
29512957
}
29522958

29532959
struct cache_entry *dup_cache_entry(const struct cache_entry *ce,

t/README

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ GIT_TEST_OE_DELTA_SIZE=<n> exercises the uncomon pack-objects code
319319
path where deltas larger than this limit require extra memory
320320
allocation for bookkeeping.
321321

322+
GIT_TEST_VALIDATE_INDEX_CACHE_ENTRIES=<boolean> checks that cache-tree
323+
records are valid when the index is written out or after a merge. This
324+
is mostly to catch missing invalidation. Default is true.
325+
322326
Naming Tests
323327
------------
324328

t/test-lib.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,12 @@ else
12561256
test_set_prereq C_LOCALE_OUTPUT
12571257
fi
12581258

1259+
if test -z "$GIT_TEST_CHECK_CACHE_TREE"
1260+
then
1261+
GIT_TEST_CHECK_CACHE_TREE=true
1262+
export GIT_TEST_CHECK_CACHE_TREE
1263+
fi
1264+
12591265
test_lazy_prereq PIPE '
12601266
# test whether the filesystem supports FIFOs
12611267
test_have_prereq !MINGW,!CYGWIN &&

0 commit comments

Comments
 (0)