Skip to content

Commit 052fe5e

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f2f57e3 commit 052fe5e

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

sha1_file.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,26 @@ static int git_open_noatime(const char *name)
13031303
}
13041304
}
13051305

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+
13061326
static int open_sha1_file(const unsigned char *sha1)
13071327
{
13081328
int fd;
@@ -2344,7 +2364,9 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
23442364

23452365
}
23462366

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,
23482370
unsigned long *disk_sizep)
23492371
{
23502372
int status;
@@ -2353,6 +2375,20 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
23532375
git_zstream stream;
23542376
char hdr[32];
23552377

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+
23562392
map = map_sha1_file(sha1, &mapsize);
23572393
if (!map)
23582394
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
23672403
*sizep = size;
23682404
git_inflate_end(&stream);
23692405
munmap(map, mapsize);
2370-
return status;
2406+
if (typep)
2407+
*typep = status;
2408+
return 0;
23712409
}
23722410

23732411
/* returns enum object_type or negative */
@@ -2389,16 +2427,16 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
23892427

23902428
if (!find_pack_entry(sha1, &e)) {
23912429
/* 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)) {
23942432
oi->whence = OI_LOOSE;
23952433
return type;
23962434
}
23972435

23982436
/* Not a loose object; someone else may have just packed it. */
23992437
reprepare_packed_git();
24002438
if (!find_pack_entry(sha1, &e))
2401-
return type;
2439+
return -1;
24022440
}
24032441

24042442
type = packed_object_info(e.p, e.offset, oi->sizep, &rtype,

0 commit comments

Comments
 (0)