summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--object-store.h18
-rw-r--r--packfile.c8
-rw-r--r--sha1-file.c26
-rw-r--r--sha1-name.c21
4 files changed, 48 insertions, 25 deletions
diff --git a/object-store.h b/object-store.h
index 30faf7b391..bf1e0cb761 100644
--- a/object-store.h
+++ b/object-store.h
@@ -11,11 +11,12 @@ struct object_directory {
struct object_directory *next;
/*
- * Used to store the results of readdir(3) calls when searching
- * for unique abbreviated hashes. This cache is never
- * invalidated, thus it's racy and not necessarily accurate.
- * That's fine for its purpose; don't use it for tasks requiring
- * greater accuracy!
+ * Used to store the results of readdir(3) calls when we are OK
+ * sacrificing accuracy due to races for speed. That includes
+ * our search for unique abbreviated hashes. Don't use it for tasks
+ * requiring greater accuracy!
+ *
+ * Be sure to call odb_load_loose_cache() before using.
*/
char loose_objects_subdir_seen[256];
struct oid_array loose_objects_cache;
@@ -45,6 +46,13 @@ void add_to_alternates_file(const char *dir);
*/
void add_to_alternates_memory(const char *dir);
+/*
+ * Populate an odb's loose object cache for one particular subdirectory (i.e.,
+ * the one that corresponds to the first byte of objects you're interested in,
+ * from 0 to 255 inclusive).
+ */
+void odb_load_loose_cache(struct object_directory *odb, int subdir_nr);
+
struct packed_git {
struct packed_git *next;
struct list_head mru;
diff --git a/packfile.c b/packfile.c
index 1eda33247f..91fd40efb0 100644
--- a/packfile.c
+++ b/packfile.c
@@ -987,6 +987,14 @@ static void prepare_packed_git(struct repository *r)
void reprepare_packed_git(struct repository *r)
{
+ struct object_directory *odb;
+
+ for (odb = r->objects->odb; odb; odb = odb->next) {
+ oid_array_clear(&odb->loose_objects_cache);
+ memset(&odb->loose_objects_subdir_seen, 0,
+ sizeof(odb->loose_objects_subdir_seen));
+ }
+
r->objects->approximate_object_count_valid = 0;
r->objects->packed_git_initialized = 0;
prepare_packed_git(r);
diff --git a/sha1-file.c b/sha1-file.c
index 503262edd2..4aae716a37 100644
--- a/sha1-file.c
+++ b/sha1-file.c
@@ -2125,6 +2125,32 @@ int for_each_loose_object(each_loose_object_fn cb, void *data,
return 0;
}
+static int append_loose_object(const struct object_id *oid, const char *path,
+ void *data)
+{
+ oid_array_append(data, oid);
+ return 0;
+}
+
+void odb_load_loose_cache(struct object_directory *odb, int subdir_nr)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ if (subdir_nr < 0 ||
+ subdir_nr >= ARRAY_SIZE(odb->loose_objects_subdir_seen))
+ BUG("subdir_nr out of range");
+
+ if (odb->loose_objects_subdir_seen[subdir_nr])
+ return;
+
+ strbuf_addstr(&buf, odb->path);
+ for_each_file_in_obj_subdir(subdir_nr, &buf,
+ append_loose_object,
+ NULL, NULL,
+ &odb->loose_objects_cache);
+ odb->loose_objects_subdir_seen[subdir_nr] = 1;
+}
+
static int check_stream_sha1(git_zstream *stream,
const char *hdr,
unsigned long size,
diff --git a/sha1-name.c b/sha1-name.c
index 358ca5e288..b24502811b 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -83,36 +83,19 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
/* otherwise, current can be discarded and candidate is still good */
}
-static int append_loose_object(const struct object_id *oid, const char *path,
- void *data)
-{
- oid_array_append(data, oid);
- return 0;
-}
-
static int match_sha(unsigned, const unsigned char *, const unsigned char *);
static void find_short_object_filename(struct disambiguate_state *ds)
{
int subdir_nr = ds->bin_pfx.hash[0];
struct object_directory *odb;
- struct strbuf buf = STRBUF_INIT;
for (odb = the_repository->objects->odb;
odb && !ds->ambiguous;
odb = odb->next) {
int pos;
- if (!odb->loose_objects_subdir_seen[subdir_nr]) {
- strbuf_reset(&buf);
- strbuf_addstr(&buf, odb->path);
- for_each_file_in_obj_subdir(subdir_nr, &buf,
- append_loose_object,
- NULL, NULL,
- &odb->loose_objects_cache);
- odb->loose_objects_subdir_seen[subdir_nr] = 1;
- }
-
+ odb_load_loose_cache(odb, subdir_nr);
pos = oid_array_lookup(&odb->loose_objects_cache, &ds->bin_pfx);
if (pos < 0)
pos = -1 - pos;
@@ -125,8 +108,6 @@ static void find_short_object_filename(struct disambiguate_state *ds)
pos++;
}
}
-
- strbuf_release(&buf);
}
static int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)