1111#include "pathspec.h"
1212#include "object-store.h"
1313#include "hash-lookup.h"
14+ #include "strmap.h"
1415
1516#define RESOLVED 0
1617#define PUNTED 1
@@ -23,26 +24,27 @@ static int rerere_enabled = -1;
2324/* automatically update cleanly resolved paths to the index */
2425static int rerere_autoupdate ;
2526
26- static int rerere_dir_nr ;
27- static int rerere_dir_alloc ;
28-
2927#define RR_HAS_POSTIMAGE 1
3028#define RR_HAS_PREIMAGE 2
31- static struct rerere_dir {
32- unsigned char hash [GIT_MAX_HEXSZ ];
29+ struct rerere_dir {
3330 int status_alloc , status_nr ;
3431 unsigned char * status ;
35- } * * rerere_dir ;
32+ char name [FLEX_ARRAY ];
33+ };
34+
35+ static struct strmap rerere_dirs = STRMAP_INIT ;
3636
3737static void free_rerere_dirs (void )
3838{
39- int i ;
40- for (i = 0 ; i < rerere_dir_nr ; i ++ ) {
41- free (rerere_dir [i ]-> status );
42- free (rerere_dir [i ]);
39+ struct hashmap_iter iter ;
40+ struct strmap_entry * ent ;
41+
42+ strmap_for_each_entry (& rerere_dirs , & iter , ent ) {
43+ struct rerere_dir * rr_dir = ent -> value ;
44+ free (rr_dir -> status );
45+ free (rr_dir );
4346 }
44- FREE_AND_NULL (rerere_dir );
45- rerere_dir_nr = rerere_dir_alloc = 0 ;
47+ strmap_clear (& rerere_dirs , 0 );
4648}
4749
4850static void free_rerere_id (struct string_list_item * item )
@@ -52,7 +54,7 @@ static void free_rerere_id(struct string_list_item *item)
5254
5355static const char * rerere_id_hex (const struct rerere_id * id )
5456{
55- return hash_to_hex ( id -> collection -> hash ) ;
57+ return id -> collection -> name ;
5658}
5759
5860static void fit_variant (struct rerere_dir * rr_dir , int variant )
@@ -115,7 +117,7 @@ static int is_rr_file(const char *name, const char *filename, int *variant)
115117static void scan_rerere_dir (struct rerere_dir * rr_dir )
116118{
117119 struct dirent * de ;
118- DIR * dir = opendir (git_path ("rr-cache/%s" , hash_to_hex ( rr_dir -> hash ) ));
120+ DIR * dir = opendir (git_path ("rr-cache/%s" , rr_dir -> name ));
119121
120122 if (!dir )
121123 return ;
@@ -133,39 +135,21 @@ static void scan_rerere_dir(struct rerere_dir *rr_dir)
133135 closedir (dir );
134136}
135137
136- static const unsigned char * rerere_dir_hash (size_t i , void * table )
137- {
138- struct rerere_dir * * rr_dir = table ;
139- return rr_dir [i ]-> hash ;
140- }
141-
142138static struct rerere_dir * find_rerere_dir (const char * hex )
143139{
144- unsigned char hash [GIT_MAX_RAWSZ ];
145140 struct rerere_dir * rr_dir ;
146- int pos ;
147-
148- if (get_sha1_hex (hex , hash ))
149- return NULL ; /* BUG */
150- pos = hash_pos (hash , rerere_dir , rerere_dir_nr , rerere_dir_hash );
151- if (pos < 0 ) {
152- rr_dir = xmalloc (sizeof (* rr_dir ));
153- hashcpy (rr_dir -> hash , hash );
141+
142+ rr_dir = strmap_get (& rerere_dirs , hex );
143+ if (!rr_dir ) {
144+ FLEX_ALLOC_STR (rr_dir , name , hex );
154145 rr_dir -> status = NULL ;
155146 rr_dir -> status_nr = 0 ;
156147 rr_dir -> status_alloc = 0 ;
157- pos = -1 - pos ;
158-
159- /* Make sure the array is big enough ... */
160- ALLOC_GROW (rerere_dir , rerere_dir_nr + 1 , rerere_dir_alloc );
161- /* ... and add it in. */
162- rerere_dir_nr ++ ;
163- MOVE_ARRAY (rerere_dir + pos + 1 , rerere_dir + pos ,
164- rerere_dir_nr - pos - 1 );
165- rerere_dir [pos ] = rr_dir ;
148+ strmap_put (& rerere_dirs , hex , rr_dir );
149+
166150 scan_rerere_dir (rr_dir );
167151 }
168- return rerere_dir [ pos ] ;
152+ return rr_dir ;
169153}
170154
171155static int has_rerere_resolution (const struct rerere_id * id )
@@ -1178,6 +1162,14 @@ static void prune_one(struct rerere_id *id,
11781162 unlink_rr_item (id );
11791163}
11801164
1165+ /* Does the basename in "path" look plausibly like an rr-cache entry? */
1166+ static int is_rr_cache_dirname (const char * path )
1167+ {
1168+ struct object_id oid ;
1169+ const char * end ;
1170+ return !parse_oid_hex (path , & oid , & end ) && !* end ;
1171+ }
1172+
11811173void rerere_gc (struct repository * r , struct string_list * rr )
11821174{
11831175 struct string_list to_remove = STRING_LIST_INIT_DUP ;
@@ -1205,10 +1197,11 @@ void rerere_gc(struct repository *r, struct string_list *rr)
12051197
12061198 if (is_dot_or_dotdot (e -> d_name ))
12071199 continue ;
1208- rr_dir = find_rerere_dir (e -> d_name );
1209- if (!rr_dir )
1200+ if (!is_rr_cache_dirname (e -> d_name ))
12101201 continue ; /* or should we remove e->d_name? */
12111202
1203+ rr_dir = find_rerere_dir (e -> d_name );
1204+
12121205 now_empty = 1 ;
12131206 for (id .variant = 0 , id .collection = rr_dir ;
12141207 id .variant < id .collection -> status_nr ;
0 commit comments