git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Justin Tobler <jltobler@gmail.com>
Date
Oct 29, 2026, 23:22 UTC
Message-ID
<20261029232220.1245827-3-jltobler@gmail.com>
In-Reply-To
<20261029232220.1245827-1-jltobler@gmail.com>

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. The cache is made optional for future callers that may only be interested in updating the map.

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 <jltobler@gmail.com>
---
 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
Previous: Karthik NayakNext: Karthik Nayak
Message 23 of 33 in “tmp-objdir: merge loose object index when migrating tmpdir”
  1. tmp-objdir: merge loose object index when migrating tmpdirJustin Tobler, Oct 22, 2026
  2. Patrick SteinhardtOct 23, 2026
  3. Justin ToblerOct 23, 2026
  4. Patrick SteinhardtOct 26, 2026
  5. Justin ToblerOct 26, 2026
  6. 0/4 loose: fix migrating "loose-object-idx" with batch fsyncJustin Tobler, Oct 29, 2026
  7. 1/4 loose: use finite timeout when locking "loose-object-idx" fileJustin Tobler, Oct 29, 2026
  8. Patrick SteinhardtOct 29, 2026
  9. 2/4 loose: lift loose object index parsing logic into helperJustin Tobler, Oct 29, 2026
  10. Patrick SteinhardtOct 29, 2026
  11. Justin ToblerOct 29, 2026
  12. 3/4 loose: lift loose object index writing logic into helperJustin Tobler, Oct 29, 2026
  13. Patrick SteinhardtOct 29, 2026
  14. Justin ToblerOct 29, 2026
  15. 4/4 tmp-objdir: merge loose object index when migrating tmpdirJustin Tobler, Oct 29, 2026
  16. Patrick SteinhardtOct 29, 2026
  17. Justin ToblerOct 29, 2026
  18. Junio C HamanoOct 29, 2026
  19. Justin ToblerOct 29, 2026
  20. 0/4 loose: fix migrating "loose-object-idx" with batch fsyncJustin Tobler, Oct 29, 2026
  21. 1/4 loose: use finite timeout when locking "loose-object-idx" fileJustin Tobler, Oct 29, 2026
  22. Karthik NayakOct 30, 2026
  23. 2/4 loose: lift loose object index parsing logic into helperJustin Tobler, Oct 29, 2026
  24. Karthik NayakOct 30, 2026
  25. Justin ToblerOct 30, 2026
  26. 3/4 loose: lift loose object index writing logic into helperJustin Tobler, Oct 29, 2026
  27. 4/4 tmp-objdir: merge loose object index when migrating tmpdirJustin Tobler, Oct 29, 2026
  28. Karthik NayakOct 30, 2026
  29. Justin ToblerOct 30, 2026
  30. Patrick SteinhardtOct 30, 2026
  31. Justin ToblerOct 30, 2026
  32. Karthik NayakOct 30, 2026
  33. Justin ToblerOct 30, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.