]> git.ipfire.org Git - thirdparty/git.git/blobdiff - rerere.c
Merge branch 'ab/pager-exit-log'
[thirdparty/git.git] / rerere.c
index d6928c1b5c1a84980e403c805d2e5fcd072e40aa..dee60dc6df6324857904f07a3edb7355afacec45 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -11,6 +11,7 @@
 #include "pathspec.h"
 #include "object-store.h"
 #include "hash-lookup.h"
+#include "strmap.h"
 
 #define RESOLVED 0
 #define PUNTED 1
@@ -23,26 +24,27 @@ static int rerere_enabled = -1;
 /* automatically update cleanly resolved paths to the index */
 static int rerere_autoupdate;
 
-static int rerere_dir_nr;
-static int rerere_dir_alloc;
-
 #define RR_HAS_POSTIMAGE 1
 #define RR_HAS_PREIMAGE 2
-static struct rerere_dir {
-       unsigned char hash[GIT_MAX_HEXSZ];
+struct rerere_dir {
        int status_alloc, status_nr;
        unsigned char *status;
-} **rerere_dir;
+       char name[FLEX_ARRAY];
+};
+
+static struct strmap rerere_dirs = STRMAP_INIT;
 
 static void free_rerere_dirs(void)
 {
-       int i;
-       for (i = 0; i < rerere_dir_nr; i++) {
-               free(rerere_dir[i]->status);
-               free(rerere_dir[i]);
+       struct hashmap_iter iter;
+       struct strmap_entry *ent;
+
+       strmap_for_each_entry(&rerere_dirs, &iter, ent) {
+               struct rerere_dir *rr_dir = ent->value;
+               free(rr_dir->status);
+               free(rr_dir);
        }
-       FREE_AND_NULL(rerere_dir);
-       rerere_dir_nr = rerere_dir_alloc = 0;
+       strmap_clear(&rerere_dirs, 0);
 }
 
 static void free_rerere_id(struct string_list_item *item)
@@ -52,7 +54,7 @@ static void free_rerere_id(struct string_list_item *item)
 
 static const char *rerere_id_hex(const struct rerere_id *id)
 {
-       return hash_to_hex(id->collection->hash);
+       return id->collection->name;
 }
 
 static 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)
 static void scan_rerere_dir(struct rerere_dir *rr_dir)
 {
        struct dirent *de;
-       DIR *dir = opendir(git_path("rr-cache/%s", hash_to_hex(rr_dir->hash)));
+       DIR *dir = opendir(git_path("rr-cache/%s", rr_dir->name));
 
        if (!dir)
                return;
@@ -133,39 +135,21 @@ static void scan_rerere_dir(struct rerere_dir *rr_dir)
        closedir(dir);
 }
 
-static const unsigned char *rerere_dir_hash(size_t i, void *table)
-{
-       struct rerere_dir **rr_dir = table;
-       return rr_dir[i]->hash;
-}
-
 static struct rerere_dir *find_rerere_dir(const char *hex)
 {
-       unsigned char hash[GIT_MAX_RAWSZ];
        struct rerere_dir *rr_dir;
-       int pos;
-
-       if (get_sha1_hex(hex, hash))
-               return NULL; /* BUG */
-       pos = hash_pos(hash, rerere_dir, rerere_dir_nr, rerere_dir_hash);
-       if (pos < 0) {
-               rr_dir = xmalloc(sizeof(*rr_dir));
-               hashcpy(rr_dir->hash, hash);
+
+       rr_dir = strmap_get(&rerere_dirs, hex);
+       if (!rr_dir) {
+               FLEX_ALLOC_STR(rr_dir, name, hex);
                rr_dir->status = NULL;
                rr_dir->status_nr = 0;
                rr_dir->status_alloc = 0;
-               pos = -1 - pos;
-
-               /* Make sure the array is big enough ... */
-               ALLOC_GROW(rerere_dir, rerere_dir_nr + 1, rerere_dir_alloc);
-               /* ... and add it in. */
-               rerere_dir_nr++;
-               MOVE_ARRAY(rerere_dir + pos + 1, rerere_dir + pos,
-                          rerere_dir_nr - pos - 1);
-               rerere_dir[pos] = rr_dir;
+               strmap_put(&rerere_dirs, hex, rr_dir);
+
                scan_rerere_dir(rr_dir);
        }
-       return rerere_dir[pos];
+       return rr_dir;
 }
 
 static int has_rerere_resolution(const struct rerere_id *id)
@@ -1178,6 +1162,14 @@ static void prune_one(struct rerere_id *id,
                unlink_rr_item(id);
 }
 
+/* Does the basename in "path" look plausibly like an rr-cache entry? */
+static int is_rr_cache_dirname(const char *path)
+{
+       struct object_id oid;
+       const char *end;
+       return !parse_oid_hex(path, &oid, &end) && !*end;
+}
+
 void rerere_gc(struct repository *r, struct string_list *rr)
 {
        struct string_list to_remove = STRING_LIST_INIT_DUP;
@@ -1205,10 +1197,11 @@ void rerere_gc(struct repository *r, struct string_list *rr)
 
                if (is_dot_or_dotdot(e->d_name))
                        continue;
-               rr_dir = find_rerere_dir(e->d_name);
-               if (!rr_dir)
+               if (!is_rr_cache_dirname(e->d_name))
                        continue; /* or should we remove e->d_name? */
 
+               rr_dir = find_rerere_dir(e->d_name);
+
                now_empty = 1;
                for (id.variant = 0, id.collection = rr_dir;
                     id.variant < id.collection->status_nr;