sha1_loose_object_info: make type lookup optional

Until recently, the only items to request from sha1_object_info_extended were type and size. This meant that we always had to open a loose object file to determine one or the other. But with the addition of the disk_size query, it's possible that we can fulfill the query without even opening the object file at all. However, since the function interface always returns the type, we have no way of knowing whether the caller cares about it or not. This patch only modified sha1_loose_object_info to make type lookup optional using an out-parameter, similar to the way the size is handled (and the return value is "0" or "-1" for success or error, respectively). There should be no functional change yet, though, as sha1_object_info_extended, the only caller, will always ask for a type. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 12, 2013 at 02:30 UTC 052fe5eaca92cac810cdb7f89bd8860fc2d5f0e1
1 file changed +43 -5
sha1_file.c
+43 -5
@@ -1303,6 +1303,26 @@ static int git_open_noatime(const char *name)
1303 }
1304 }
1305
1306 +static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
1307 +{
1308 + char *name = sha1_file_name(sha1);
1309 + struct alternate_object_database *alt;
1310 +
1311 + if (!lstat(name, st))
1312 + return 0;
1313 +
1314 + prepare_alt_odb();
1315 + errno = ENOENT;
1316 + for (alt = alt_odb_list; alt; alt = alt->next) {
1317 + name = alt->name;
1318 + fill_sha1_path(name, sha1);
1319 + if (!lstat(alt->base, st))
1320 + return 0;
1321 + }
1322 +
1323 + return -1;
1324 +}
1325 +
1326 static int open_sha1_file(const unsigned char *sha1)
1327 {
1328 int fd;
@@ -2344,7 +2364,9 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
2364
2365 }
2366
2347 -static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep,
2367 +static int sha1_loose_object_info(const unsigned char *sha1,
2368 + enum object_type *typep,
2369 + unsigned long *sizep,
2370 unsigned long *disk_sizep)
2371 {
2372 int status;
@@ -2353,6 +2375,20 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
2375 git_zstream stream;
2376 char hdr[32];
2377
2378 + /*
2379 + * If we don't care about type or size, then we don't
2380 + * need to look inside the object at all.
2381 + */
2382 + if (!typep && !sizep) {
2383 + if (disk_sizep) {
2384 + struct stat st;
2385 + if (stat_sha1_file(sha1, &st) < 0)
2386 + return -1;
2387 + *disk_sizep = st.st_size;
2388 + }
2389 + return 0;
2390 + }
2391 +
2392 map = map_sha1_file(sha1, &mapsize);
2393 if (!map)
2394 return error("unable to find %s", sha1_to_hex(sha1));
@@ -2367,7 +2403,9 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
2403 *sizep = size;
2404 git_inflate_end(&stream);
2405 munmap(map, mapsize);
2370 - return status;
2406 + if (typep)
2407 + *typep = status;
2408 + return 0;
2409 }
2410
2411 /* returns enum object_type or negative */
@@ -2389,8 +2427,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
2427
2428 if (!find_pack_entry(sha1, &e)) {
2429 /* Most likely it's a loose object. */
2392 - type = sha1_loose_object_info(sha1, oi->sizep, oi->disk_sizep);
2393 - if (type >= 0) {
2430 + if (!sha1_loose_object_info(sha1, &type,
2431 + oi->sizep, oi->disk_sizep)) {
2432 oi->whence = OI_LOOSE;
2433 return type;
2434 }
@@ -2398,7 +2436,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
2436 /* Not a loose object; someone else may have just packed it. */
2437 reprepare_packed_git();
2438 if (!find_pack_entry(sha1, &e))
2401 - return type;
2439 + return -1;
2440 }
2441
2442 type = packed_object_info(e.p, e.offset, oi->sizep, &rtype,