[PATCH v2 2/4] loose: lift loose object index parsing logic into helper

From
Justin Tobler <hidden>
Date
2026-10-29 00:24:21
Reply to
Justin Tobler, 2026-10-29
Mapping entries from the "loose-object-idx" file are parsed via
`loose_object_map_load()` and inserted into the in-memory loose object
map of the corresponding object source. In a subsequent commit, a
temporary loose object index file must also be parsed and have its
contents stored in a map that is not attached to any object source.

Extract the logic for parsing a loose object index file into a separate
`loose_object_map_read()` helper function that allows callers to
explicitly specify the map to insert the entries into. The
`insert_loose_map()` helper function is also updated accordingly to
explicitly operate on the provided map and optional cache instead of the
object source.

While at it, stop treating all errors related to opening the
"loose-object-idx" file as success and instead only ignore ENOENT. It is
expected that a mapping file may not always be present, but other errors
should be signaled back to callers. Note that this slightly changes the
behavior of `repo_read_loose_object_map()`, which now stops loading the
mapping files of subsequent object sources when one is unreadable, the
same way it already does when one is malformed.

Signed-off-by: Justin Tobler <redacted>
---
 loose.c | 87 +++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 54 insertions(+), 33 deletions(-)
diff --git a/loose.c b/loose.c
index c6f4ee0ec6..5f72c644f9 100644
--- a/loose.c
+++ b/loose.c
@@ -48,67 +48,88 @@ static int insert_oid_pair(kh_oid_map_t *map, const struct object_id *key, const
 	return 1;
 }
 
-static int insert_loose_map(struct odb_source_loose *loose,
+static int insert_loose_map(struct loose_object_map *map,
+			    struct oidtree *cache,
 			    const struct object_id *oid,
 			    const struct object_id *compat_oid)
 {
-	struct loose_object_map *map = loose->map;
 	int inserted = 0;
 
 	inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
 	inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
-	if (inserted)
-		oidtree_insert(loose->cache, compat_oid, NULL);
+	if (inserted && cache)
+		oidtree_insert(cache, compat_oid, NULL);
 
 	return inserted;
 }
 
-int loose_object_map_load(struct odb_source_loose *loose)
+static int loose_object_map_read(struct repository *repo, const char *path,
+				 struct loose_object_map *map,
+				 struct oidtree *cache)
 {
-	struct repository *repo = loose->base.odb->repo;
 	struct strbuf buf = STRBUF_INIT;
-	char *path;
 	FILE *fp;
-	int ret = -1;
-
-	if (!should_use_loose_object_map(repo))
-		return 0;
-
-	if (!loose->map)
-		loose_object_map_init(&loose->map);
-	if (!loose->cache) {
-		ALLOC_ARRAY(loose->cache, 1);
-		oidtree_init(loose->cache);
-	}
-
-	insert_loose_map(loose, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
-	insert_loose_map(loose, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob);
-	insert_loose_map(loose, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid);
+	int ret;
 
-	path = xstrfmt("%s/loose-object-idx", loose->base.path);
 	fp = fopen(path, "rb");
 	if (!fp) {
-		free(path);
-		return 0;
+		if (errno == ENOENT)
+			return 0;
+		return -1;
 	}
 
-	if (strbuf_getwholeline(&buf, fp, '\n') || strcmp(buf.buf, loose_object_header))
-		goto err;
+	if (strbuf_getwholeline(&buf, fp, '\n') || strcmp(buf.buf, loose_object_header)) {
+		ret = -1;
+		goto out;
+	}
 	while (!strbuf_getline_lf(&buf, fp)) {
 		const char *p;
 		struct object_id oid, compat_oid;
 		if (parse_oid_hex_algop(buf.buf, &oid, &p, repo->hash_algo) ||
 		    *p++ != ' ' ||
 		    parse_oid_hex_algop(p, &compat_oid, &p, repo->compat_hash_algo) ||
-		    p != buf.buf + buf.len)
-			goto err;
-		insert_loose_map(loose, &oid, &compat_oid);
+		    p != buf.buf + buf.len) {
+			ret = -1;
+			goto out;
+		}
+		insert_loose_map(map, cache, &oid, &compat_oid);
 	}
 
 	ret = ferror(fp) ? -1 : 0;
-err:
-	fclose(fp);
+
+out:
 	strbuf_release(&buf);
+	fclose(fp);
+
+	return ret;
+}
+
+int loose_object_map_load(struct odb_source_loose *loose)
+{
+	struct repository *repo = loose->base.odb->repo;
+	char *path;
+	int ret;
+
+	if (!should_use_loose_object_map(repo))
+		return 0;
+
+	if (!loose->map)
+		loose_object_map_init(&loose->map);
+	if (!loose->cache) {
+		ALLOC_ARRAY(loose->cache, 1);
+		oidtree_init(loose->cache);
+	}
+
+	insert_loose_map(loose->map, loose->cache, repo->hash_algo->empty_tree,
+			 repo->compat_hash_algo->empty_tree);
+	insert_loose_map(loose->map, loose->cache, repo->hash_algo->empty_blob,
+			 repo->compat_hash_algo->empty_blob);
+	insert_loose_map(loose->map, loose->cache, repo->hash_algo->null_oid,
+			 repo->compat_hash_algo->null_oid);
+
+	path = xstrfmt("%s/loose-object-idx", loose->base.path);
+	ret = loose_object_map_read(repo, path, loose->map, loose->cache);
+
 	free(path);
 	return ret;
 }
@@ -223,7 +244,7 @@ int repo_add_loose_object_map(struct odb_source_loose *loose,
 	if (!should_use_loose_object_map(loose->base.odb->repo))
 		return 0;
 
-	inserted = insert_loose_map(loose, oid, compat_oid);
+	inserted = insert_loose_map(loose->map, loose->cache, oid, compat_oid);
 	if (inserted)
 		return write_one_object(loose, oid, compat_oid);
 	return 0;
-- 
2.56.0.173.gf57c9a7388
Thread (34 messages) 34 messages, 4 authors, last reply 2d ago
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help