Skip to content

Commit 49a03ef

Browse files
mhaggergitster
authored andcommitted
read_packed_refs(): use mmap to read the packed-refs file
It's still done in a pretty stupid way, involving more data copying than necessary. That will improve in future commits. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 735267a commit 49a03ef

1 file changed

Lines changed: 32 additions & 10 deletions

File tree

refs/packed-backend.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,12 @@ static NORETURN void die_invalid_line(const char *path,
215215
*/
216216
static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
217217
{
218-
FILE *f;
219218
struct packed_ref_cache *packed_refs = xcalloc(1, sizeof(*packed_refs));
219+
int fd;
220+
struct stat st;
221+
size_t size;
222+
char *buf;
223+
const char *pos, *eol, *eof;
220224
struct ref_entry *last = NULL;
221225
struct strbuf line = STRBUF_INIT;
222226
enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled = PEELED_NONE;
@@ -227,8 +231,8 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
227231
packed_refs->cache = create_ref_cache(NULL, NULL);
228232
packed_refs->cache->root->flag &= ~REF_INCOMPLETE;
229233

230-
f = fopen(refs->path, "r");
231-
if (!f) {
234+
fd = open(refs->path, O_RDONLY);
235+
if (fd < 0) {
232236
if (errno == ENOENT) {
233237
/*
234238
* This is OK; it just means that no
@@ -241,24 +245,35 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
241245
}
242246
}
243247

244-
stat_validity_update(&packed_refs->validity, fileno(f));
248+
stat_validity_update(&packed_refs->validity, fd);
249+
250+
if (fstat(fd, &st) < 0)
251+
die_errno("couldn't stat %s", refs->path);
252+
253+
size = xsize_t(st.st_size);
254+
buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
255+
pos = buf;
256+
eof = buf + size;
245257

246258
dir = get_ref_dir(packed_refs->cache->root);
247-
while (strbuf_getwholeline(&line, f, '\n') != EOF) {
259+
while (pos < eof) {
248260
struct object_id oid;
249261
const char *refname;
250262
const char *traits;
251263

252-
if (!line.len || line.buf[line.len - 1] != '\n')
253-
die_unterminated_line(refs->path, line.buf, line.len);
264+
eol = memchr(pos, '\n', eof - pos);
265+
if (!eol)
266+
die_unterminated_line(refs->path, pos, eof - pos);
267+
268+
strbuf_add(&line, pos, eol + 1 - pos);
254269

255270
if (skip_prefix(line.buf, "# pack-refs with:", &traits)) {
256271
if (strstr(traits, " fully-peeled "))
257272
peeled = PEELED_FULLY;
258273
else if (strstr(traits, " peeled "))
259274
peeled = PEELED_TAGS;
260275
/* perhaps other traits later as well */
261-
continue;
276+
goto next_line;
262277
}
263278

264279
refname = parse_ref_line(&line, &oid);
@@ -291,11 +306,18 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
291306
} else {
292307
die_invalid_line(refs->path, line.buf, line.len);
293308
}
309+
310+
next_line:
311+
/* The "+ 1" is for the LF character. */
312+
pos = eol + 1;
313+
strbuf_reset(&line);
294314
}
295315

296-
fclose(f);
297-
strbuf_release(&line);
316+
if (munmap(buf, size))
317+
die_errno("error ummapping packed-refs file");
318+
close(fd);
298319

320+
strbuf_release(&line);
299321
return packed_refs;
300322
}
301323

0 commit comments

Comments
 (0)