@@ -39,7 +39,7 @@ static struct dir_entry *find_dir_entry(struct index_state *istate,
39
39
}
40
40
41
41
static struct dir_entry * hash_dir_entry (struct index_state * istate ,
42
- struct cache_entry * ce , int namelen )
42
+ struct cache_entry * ce , int namelen , struct dir_entry * * p_previous_dir )
43
43
{
44
44
/*
45
45
* Throw each directory component in the hash for quick lookup
@@ -70,9 +70,21 @@ static struct dir_entry *hash_dir_entry(struct index_state *istate,
70
70
namelen -- ;
71
71
72
72
/* lookup existing entry for that directory */
73
- if (!use_precomputed_dir_hash )
74
- hash = memihash (ce -> name , namelen );
75
- dir = find_dir_entry__hash (istate , ce -> name , namelen , hash );
73
+ if (p_previous_dir && * p_previous_dir
74
+ && namelen == (* p_previous_dir )-> namelen
75
+ && memcmp (ce -> name , (* p_previous_dir )-> name , namelen ) == 0 ) {
76
+ /*
77
+ * When our caller is sequentially iterating thru the index,
78
+ * items in the same directory will be sequential, and therefore
79
+ * refer to the same dir_entry.
80
+ */
81
+ dir = * p_previous_dir ;
82
+ } else {
83
+ if (!use_precomputed_dir_hash )
84
+ hash = memihash (ce -> name , namelen );
85
+ dir = find_dir_entry__hash (istate , ce -> name , namelen , hash );
86
+ }
87
+
76
88
if (!dir ) {
77
89
/* not found, create it and add to hash table */
78
90
FLEX_ALLOC_MEM (dir , name , ce -> name , namelen );
@@ -81,15 +93,20 @@ static struct dir_entry *hash_dir_entry(struct index_state *istate,
81
93
hashmap_add (& istate -> dir_hash , dir );
82
94
83
95
/* recursively add missing parent directories */
84
- dir -> parent = hash_dir_entry (istate , ce , namelen );
96
+ dir -> parent = hash_dir_entry (istate , ce , namelen , NULL );
85
97
}
98
+
99
+ if (p_previous_dir )
100
+ * p_previous_dir = dir ;
101
+
86
102
return dir ;
87
103
}
88
104
89
- static void add_dir_entry (struct index_state * istate , struct cache_entry * ce )
105
+ static void add_dir_entry (struct index_state * istate , struct cache_entry * ce ,
106
+ struct dir_entry * * p_previous_dir )
90
107
{
91
108
/* Add reference to the directory entry (and parents if 0). */
92
- struct dir_entry * dir = hash_dir_entry (istate , ce , ce_namelen (ce ));
109
+ struct dir_entry * dir = hash_dir_entry (istate , ce , ce_namelen (ce ), p_previous_dir );
93
110
while (dir && !(dir -> nr ++ ))
94
111
dir = dir -> parent ;
95
112
}
@@ -100,7 +117,7 @@ static void remove_dir_entry(struct index_state *istate, struct cache_entry *ce)
100
117
* Release reference to the directory entry. If 0, remove and continue
101
118
* with parent directory.
102
119
*/
103
- struct dir_entry * dir = hash_dir_entry (istate , ce , ce_namelen (ce ));
120
+ struct dir_entry * dir = hash_dir_entry (istate , ce , ce_namelen (ce ), NULL );
104
121
while (dir && !(-- dir -> nr )) {
105
122
struct dir_entry * parent = dir -> parent ;
106
123
hashmap_remove (& istate -> dir_hash , dir , NULL );
@@ -109,7 +126,8 @@ static void remove_dir_entry(struct index_state *istate, struct cache_entry *ce)
109
126
}
110
127
}
111
128
112
- static void hash_index_entry (struct index_state * istate , struct cache_entry * ce )
129
+ static void hash_index_entry (struct index_state * istate , struct cache_entry * ce ,
130
+ struct dir_entry * * p_previous_dir )
113
131
{
114
132
unsigned int h ;
115
133
@@ -126,7 +144,7 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
126
144
hashmap_add (& istate -> name_hash , ce );
127
145
128
146
if (ignore_case )
129
- add_dir_entry (istate , ce );
147
+ add_dir_entry (istate , ce , p_previous_dir );
130
148
}
131
149
132
150
static int cache_entry_cmp (const struct cache_entry * ce1 ,
@@ -142,6 +160,7 @@ static int cache_entry_cmp(const struct cache_entry *ce1,
142
160
143
161
static void lazy_init_name_hash (struct index_state * istate )
144
162
{
163
+ struct dir_entry * previous_dir = NULL ;
145
164
int nr ;
146
165
147
166
if (istate -> name_hash_initialized )
@@ -151,14 +170,14 @@ static void lazy_init_name_hash(struct index_state *istate)
151
170
hashmap_init (& istate -> dir_hash , (hashmap_cmp_fn ) dir_entry_cmp ,
152
171
istate -> cache_nr );
153
172
for (nr = 0 ; nr < istate -> cache_nr ; nr ++ )
154
- hash_index_entry (istate , istate -> cache [nr ]);
173
+ hash_index_entry (istate , istate -> cache [nr ], & previous_dir );
155
174
istate -> name_hash_initialized = 1 ;
156
175
}
157
176
158
177
void add_name_hash (struct index_state * istate , struct cache_entry * ce )
159
178
{
160
179
if (istate -> name_hash_initialized )
161
- hash_index_entry (istate , ce );
180
+ hash_index_entry (istate , ce , NULL );
162
181
}
163
182
164
183
void remove_name_hash (struct index_state * istate , struct cache_entry * ce )
0 commit comments