Skip to content

Commit 1f9b02b

Browse files
committed
Merge branch 'jt/avoid-lazy-fetch-commits'
Even in a repository with promisor remote, it is useless to attempt to lazily attempt fetching an object that is expected to be commit, because no "filter" mode omits commit objects. Take advantage of this assumption to fail fast on errors. * jt/avoid-lazy-fetch-commits: commit: don't lazy-fetch commits object-file: emit corruption errors when detected object-file: refactor map_loose_object_1() object-file: remove OBJECT_INFO_IGNORE_LOOSE
2 parents 319c3ab + 7e2ad1c commit 1f9b02b

File tree

3 files changed

+69
-61
lines changed

3 files changed

+69
-61
lines changed

commit.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,17 @@ int repo_parse_commit_internal(struct repository *r,
508508
enum object_type type;
509509
void *buffer;
510510
unsigned long size;
511+
struct object_info oi = {
512+
.typep = &type,
513+
.sizep = &size,
514+
.contentp = &buffer,
515+
};
516+
/*
517+
* Git does not support partial clones that exclude commits, so set
518+
* OBJECT_INFO_SKIP_FETCH_OBJECT to fail fast when an object is missing.
519+
*/
520+
int flags = OBJECT_INFO_LOOKUP_REPLACE | OBJECT_INFO_SKIP_FETCH_OBJECT |
521+
OBJECT_INFO_DIE_IF_CORRUPT;
511522
int ret;
512523

513524
if (!item)
@@ -516,8 +527,8 @@ int repo_parse_commit_internal(struct repository *r,
516527
return 0;
517528
if (use_commit_graph && parse_commit_in_graph(r, item))
518529
return 0;
519-
buffer = repo_read_object_file(r, &item->object.oid, &type, &size);
520-
if (!buffer)
530+
531+
if (oid_object_info_extended(r, &item->object.oid, &oi, flags) < 0)
521532
return quiet_on_missing ? -1 :
522533
error("Could not read %s",
523534
oid_to_hex(&item->object.oid));

object-file.c

Lines changed: 52 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,43 +1211,38 @@ static int quick_has_loose(struct repository *r,
12111211
}
12121212

12131213
/*
1214-
* Map the loose object at "path" if it is not NULL, or the path found by
1215-
* searching for a loose object named "oid".
1214+
* Map and close the given loose object fd. The path argument is used for
1215+
* error reporting.
12161216
*/
1217-
static void *map_loose_object_1(struct repository *r, const char *path,
1218-
const struct object_id *oid, unsigned long *size)
1217+
static void *map_fd(int fd, const char *path, unsigned long *size)
12191218
{
1220-
void *map;
1221-
int fd;
1222-
1223-
if (path)
1224-
fd = git_open(path);
1225-
else
1226-
fd = open_loose_object(r, oid, &path);
1227-
map = NULL;
1228-
if (fd >= 0) {
1229-
struct stat st;
1219+
void *map = NULL;
1220+
struct stat st;
12301221

1231-
if (!fstat(fd, &st)) {
1232-
*size = xsize_t(st.st_size);
1233-
if (!*size) {
1234-
/* mmap() is forbidden on empty files */
1235-
error(_("object file %s is empty"), path);
1236-
close(fd);
1237-
return NULL;
1238-
}
1239-
map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
1222+
if (!fstat(fd, &st)) {
1223+
*size = xsize_t(st.st_size);
1224+
if (!*size) {
1225+
/* mmap() is forbidden on empty files */
1226+
error(_("object file %s is empty"), path);
1227+
close(fd);
1228+
return NULL;
12401229
}
1241-
close(fd);
1230+
map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
12421231
}
1232+
close(fd);
12431233
return map;
12441234
}
12451235

12461236
void *map_loose_object(struct repository *r,
12471237
const struct object_id *oid,
12481238
unsigned long *size)
12491239
{
1250-
return map_loose_object_1(r, NULL, oid, size);
1240+
const char *p;
1241+
int fd = open_loose_object(r, oid, &p);
1242+
1243+
if (fd < 0)
1244+
return NULL;
1245+
return map_fd(fd, p, size);
12511246
}
12521247

12531248
enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
@@ -1427,7 +1422,9 @@ static int loose_object_info(struct repository *r,
14271422
struct object_info *oi, int flags)
14281423
{
14291424
int status = 0;
1425+
int fd;
14301426
unsigned long mapsize;
1427+
const char *path;
14311428
void *map;
14321429
git_zstream stream;
14331430
char hdr[MAX_HEADER_LEN];
@@ -1448,7 +1445,6 @@ static int loose_object_info(struct repository *r,
14481445
* object even exists.
14491446
*/
14501447
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
1451-
const char *path;
14521448
struct stat st;
14531449
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
14541450
return quick_has_loose(r, oid) ? 0 : -1;
@@ -1459,7 +1455,13 @@ static int loose_object_info(struct repository *r,
14591455
return 0;
14601456
}
14611457

1462-
map = map_loose_object(r, oid, &mapsize);
1458+
fd = open_loose_object(r, oid, &path);
1459+
if (fd < 0) {
1460+
if (errno != ENOENT)
1461+
error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
1462+
return -1;
1463+
}
1464+
map = map_fd(fd, path, &mapsize);
14631465
if (!map)
14641466
return -1;
14651467

@@ -1497,6 +1499,10 @@ static int loose_object_info(struct repository *r,
14971499
break;
14981500
}
14991501

1502+
if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
1503+
die(_("loose object %s (stored in %s) is corrupt"),
1504+
oid_to_hex(oid), path);
1505+
15001506
git_inflate_end(&stream);
15011507
cleanup:
15021508
munmap(map, mapsize);
@@ -1575,9 +1581,6 @@ static int do_oid_object_info_extended(struct repository *r,
15751581
if (find_pack_entry(r, real, &e))
15761582
break;
15771583

1578-
if (flags & OBJECT_INFO_IGNORE_LOOSE)
1579-
return -1;
1580-
15811584
/* Most likely it's a loose object. */
15821585
if (!loose_object_info(r, real, oi, flags))
15831586
return 0;
@@ -1609,6 +1612,15 @@ static int do_oid_object_info_extended(struct repository *r,
16091612
continue;
16101613
}
16111614

1615+
if (flags & OBJECT_INFO_DIE_IF_CORRUPT) {
1616+
const struct packed_git *p;
1617+
if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid))
1618+
die(_("replacement %s not found for %s"),
1619+
oid_to_hex(real), oid_to_hex(oid));
1620+
if ((p = has_packed_and_bad(r, real)))
1621+
die(_("packed object %s (stored in %s) is corrupt"),
1622+
oid_to_hex(real), p->pack_name);
1623+
}
16121624
return -1;
16131625
}
16141626

@@ -1661,15 +1673,17 @@ int oid_object_info(struct repository *r,
16611673

16621674
static void *read_object(struct repository *r,
16631675
const struct object_id *oid, enum object_type *type,
1664-
unsigned long *size)
1676+
unsigned long *size,
1677+
int die_if_corrupt)
16651678
{
16661679
struct object_info oi = OBJECT_INFO_INIT;
16671680
void *content;
16681681
oi.typep = type;
16691682
oi.sizep = size;
16701683
oi.contentp = &content;
16711684

1672-
if (oid_object_info_extended(r, oid, &oi, 0) < 0)
1685+
if (oid_object_info_extended(r, oid, &oi, die_if_corrupt
1686+
? OBJECT_INFO_DIE_IF_CORRUPT : 0) < 0)
16731687
return NULL;
16741688
return content;
16751689
}
@@ -1705,35 +1719,14 @@ void *read_object_file_extended(struct repository *r,
17051719
int lookup_replace)
17061720
{
17071721
void *data;
1708-
const struct packed_git *p;
1709-
const char *path;
1710-
struct stat st;
17111722
const struct object_id *repl = lookup_replace ?
17121723
lookup_replace_object(r, oid) : oid;
17131724

17141725
errno = 0;
1715-
data = read_object(r, repl, type, size);
1726+
data = read_object(r, repl, type, size, 1);
17161727
if (data)
17171728
return data;
17181729

1719-
obj_read_lock();
1720-
if (errno && errno != ENOENT)
1721-
die_errno(_("failed to read object %s"), oid_to_hex(oid));
1722-
1723-
/* die if we replaced an object with one that does not exist */
1724-
if (repl != oid)
1725-
die(_("replacement %s not found for %s"),
1726-
oid_to_hex(repl), oid_to_hex(oid));
1727-
1728-
if (!stat_loose_object(r, repl, &st, &path))
1729-
die(_("loose object %s (stored in %s) is corrupt"),
1730-
oid_to_hex(repl), path);
1731-
1732-
if ((p = has_packed_and_bad(r, repl)))
1733-
die(_("packed object %s (stored in %s) is corrupt"),
1734-
oid_to_hex(repl), p->pack_name);
1735-
obj_read_unlock();
1736-
17371730
return NULL;
17381731
}
17391732

@@ -2269,7 +2262,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
22692262

22702263
if (has_loose_object(oid))
22712264
return 0;
2272-
buf = read_object(the_repository, oid, &type, &len);
2265+
buf = read_object(the_repository, oid, &type, &len, 0);
22732266
if (!buf)
22742267
return error(_("cannot read object for %s"), oid_to_hex(oid));
22752268
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
@@ -2785,13 +2778,16 @@ int read_loose_object(const char *path,
27852778
struct object_info *oi)
27862779
{
27872780
int ret = -1;
2781+
int fd;
27882782
void *map = NULL;
27892783
unsigned long mapsize;
27902784
git_zstream stream;
27912785
char hdr[MAX_HEADER_LEN];
27922786
unsigned long *size = oi->sizep;
27932787

2794-
map = map_loose_object_1(the_repository, path, NULL, &mapsize);
2788+
fd = git_open(path);
2789+
if (fd >= 0)
2790+
map = map_fd(fd, path, &mapsize);
27952791
if (!map) {
27962792
error_errno(_("unable to mmap %s"), path);
27972793
goto out;

object-store.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,19 +434,20 @@ struct object_info {
434434
#define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2
435435
/* Do not retry packed storage after checking packed and loose storage */
436436
#define OBJECT_INFO_QUICK 8
437-
/* Do not check loose object */
438-
#define OBJECT_INFO_IGNORE_LOOSE 16
439437
/*
440438
* Do not attempt to fetch the object if missing (even if fetch_is_missing is
441439
* nonzero).
442440
*/
443-
#define OBJECT_INFO_SKIP_FETCH_OBJECT 32
441+
#define OBJECT_INFO_SKIP_FETCH_OBJECT 16
444442
/*
445443
* This is meant for bulk prefetching of missing blobs in a partial
446444
* clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK
447445
*/
448446
#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK)
449447

448+
/* Die if object corruption (not just an object being missing) was detected. */
449+
#define OBJECT_INFO_DIE_IF_CORRUPT 32
450+
450451
int oid_object_info_extended(struct repository *r,
451452
const struct object_id *,
452453
struct object_info *, unsigned flags);

0 commit comments

Comments
 (0)