@@ -68,17 +68,21 @@ struct snapshot {
6868 int mmapped ;
6969
7070 /*
71- * The contents of the `packed-refs` file. If the file was
72- * already sorted, this points at the mmapped contents of the
73- * file. If not, this points at heap-allocated memory
74- * containing the contents, sorted. If there were no contents
75- * (e.g., because the file didn't exist), `buf` and `eof` are
76- * both NULL.
71+ * The contents of the `packed-refs` file:
72+ *
73+ * - buf -- a pointer to the start of the memory
74+ * - start -- a pointer to the first byte of actual references
75+ * (i.e., after the header line, if one is present)
76+ * - eof -- a pointer just past the end of the reference
77+ * contents
78+ *
79+ * If the `packed-refs` file was already sorted, `buf` points
80+ * at the mmapped contents of the file. If not, it points at
81+ * heap-allocated memory containing the contents, sorted. If
82+ * there were no contents (e.g., because the file didn't
83+ * exist), `buf`, `start`, and `eof` are all NULL.
7784 */
78- char * buf , * eof ;
79-
80- /* The size of the header line, if any; otherwise, 0: */
81- size_t header_len ;
85+ char * buf , * start , * eof ;
8286
8387 /*
8488 * What is the peeled state of the `packed-refs` file that
@@ -169,8 +173,7 @@ static void clear_snapshot_buffer(struct snapshot *snapshot)
169173 } else {
170174 free (snapshot -> buf );
171175 }
172- snapshot -> buf = snapshot -> eof = NULL ;
173- snapshot -> header_len = 0 ;
176+ snapshot -> buf = snapshot -> start = snapshot -> eof = NULL ;
174177}
175178
176179/*
@@ -319,13 +322,14 @@ static void sort_snapshot(struct snapshot *snapshot)
319322 size_t len , i ;
320323 char * new_buffer , * dst ;
321324
322- pos = snapshot -> buf + snapshot -> header_len ;
325+ pos = snapshot -> start ;
323326 eof = snapshot -> eof ;
324- len = eof - pos ;
325327
326- if (! len )
328+ if (pos == eof )
327329 return ;
328330
331+ len = eof - pos ;
332+
329333 /*
330334 * Initialize records based on a crude estimate of the number
331335 * of references in the file (we'll grow it below if needed):
@@ -391,9 +395,8 @@ static void sort_snapshot(struct snapshot *snapshot)
391395 * place:
392396 */
393397 clear_snapshot_buffer (snapshot );
394- snapshot -> buf = new_buffer ;
398+ snapshot -> buf = snapshot -> start = new_buffer ;
395399 snapshot -> eof = new_buffer + len ;
396- snapshot -> header_len = 0 ;
397400
398401cleanup :
399402 free (records );
@@ -442,23 +445,26 @@ static const char *find_end_of_record(const char *p, const char *end)
442445 */
443446static void verify_buffer_safe (struct snapshot * snapshot )
444447{
445- const char * buf = snapshot -> buf + snapshot -> header_len ;
448+ const char * start = snapshot -> start ;
446449 const char * eof = snapshot -> eof ;
447450 const char * last_line ;
448451
449- if (buf == eof )
452+ if (start == eof )
450453 return ;
451454
452- last_line = find_start_of_record (buf , eof - 1 );
455+ last_line = find_start_of_record (start , eof - 1 );
453456 if (* (eof - 1 ) != '\n' || eof - last_line < GIT_SHA1_HEXSZ + 2 )
454457 die_invalid_line (snapshot -> refs -> path ,
455458 last_line , eof - last_line );
456459}
457460
461+ #define SMALL_FILE_SIZE (32*1024)
462+
458463/*
459464 * Depending on `mmap_strategy`, either mmap or read the contents of
460465 * the `packed-refs` file into the snapshot. Return 1 if the file
461- * existed and was read, or 0 if the file was absent. Die on errors.
466+ * existed and was read, or 0 if the file was absent or empty. Die on
467+ * errors.
462468 */
463469static int load_contents (struct snapshot * snapshot )
464470{
@@ -489,24 +495,23 @@ static int load_contents(struct snapshot *snapshot)
489495 die_errno ("couldn't stat %s" , snapshot -> refs -> path );
490496 size = xsize_t (st .st_size );
491497
492- switch (mmap_strategy ) {
493- case MMAP_NONE :
498+ if (!size ) {
499+ return 0 ;
500+ } else if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE ) {
494501 snapshot -> buf = xmalloc (size );
495502 bytes_read = read_in_full (fd , snapshot -> buf , size );
496503 if (bytes_read < 0 || bytes_read != size )
497504 die_errno ("couldn't read %s" , snapshot -> refs -> path );
498- snapshot -> eof = snapshot -> buf + size ;
499505 snapshot -> mmapped = 0 ;
500- break ;
501- case MMAP_TEMPORARY :
502- case MMAP_OK :
506+ } else {
503507 snapshot -> buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
504- snapshot -> eof = snapshot -> buf + size ;
505508 snapshot -> mmapped = 1 ;
506- break ;
507509 }
508510 close (fd );
509511
512+ snapshot -> start = snapshot -> buf ;
513+ snapshot -> eof = snapshot -> buf + size ;
514+
510515 return 1 ;
511516}
512517
@@ -515,9 +520,11 @@ static int load_contents(struct snapshot *snapshot)
515520 * `refname` starts. If `mustexist` is true and the reference doesn't
516521 * exist, then return NULL. If `mustexist` is false and the reference
517522 * doesn't exist, then return the point where that reference would be
518- * inserted. In the latter mode, `refname` doesn't have to be a proper
519- * reference name; for example, one could search for "refs/replace/"
520- * to find the start of any replace references.
523+ * inserted, or `snapshot->eof` (which might be NULL) if it would be
524+ * inserted at the end of the file. In the latter mode, `refname`
525+ * doesn't have to be a proper reference name; for example, one could
526+ * search for "refs/replace/" to find the start of any replace
527+ * references.
521528 *
522529 * The record is sought using a binary search, so `snapshot->buf` must
523530 * be sorted.
@@ -539,15 +546,15 @@ static const char *find_reference_location(struct snapshot *snapshot,
539546 * preceding records all have reference names that come
540547 * *before* `refname`.
541548 */
542- const char * lo = snapshot -> buf + snapshot -> header_len ;
549+ const char * lo = snapshot -> start ;
543550
544551 /*
545552 * A pointer to a the first character of a record whose
546553 * reference name comes *after* `refname`.
547554 */
548555 const char * hi = snapshot -> eof ;
549556
550- while (lo < hi ) {
557+ while (lo != hi ) {
551558 const char * mid , * rec ;
552559 int cmp ;
553560
@@ -616,9 +623,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
616623
617624 /* If the file has a header line, process it: */
618625 if (snapshot -> buf < snapshot -> eof && * snapshot -> buf == '#' ) {
619- struct strbuf tmp = STRBUF_INIT ;
620- char * p ;
621- const char * eol ;
626+ char * tmp , * p , * eol ;
622627 struct string_list traits = STRING_LIST_INIT_NODUP ;
623628
624629 eol = memchr (snapshot -> buf , '\n' ,
@@ -628,9 +633,9 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
628633 snapshot -> buf ,
629634 snapshot -> eof - snapshot -> buf );
630635
631- strbuf_add ( & tmp , snapshot -> buf , eol - snapshot -> buf );
636+ tmp = xmemdupz ( snapshot -> buf , eol - snapshot -> buf );
632637
633- if (!skip_prefix (tmp . buf , "# pack-refs with:" , (const char * * )& p ))
638+ if (!skip_prefix (tmp , "# pack-refs with:" , (const char * * )& p ))
634639 die_invalid_line (refs -> path ,
635640 snapshot -> buf ,
636641 snapshot -> eof - snapshot -> buf );
@@ -647,10 +652,10 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
647652 /* perhaps other traits later as well */
648653
649654 /* The "+ 1" is for the LF character. */
650- snapshot -> header_len = eol + 1 - snapshot -> buf ;
655+ snapshot -> start = eol + 1 ;
651656
652657 string_list_clear (& traits , 0 );
653- strbuf_release ( & tmp );
658+ free ( tmp );
654659 }
655660
656661 verify_buffer_safe (snapshot );
@@ -671,13 +676,12 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
671676 * We don't want to leave the file mmapped, so we are
672677 * forced to make a copy now:
673678 */
674- size_t size = snapshot -> eof -
675- (snapshot -> buf + snapshot -> header_len );
679+ size_t size = snapshot -> eof - snapshot -> start ;
676680 char * buf_copy = xmalloc (size );
677681
678- memcpy (buf_copy , snapshot -> buf + snapshot -> header_len , size );
682+ memcpy (buf_copy , snapshot -> start , size );
679683 clear_snapshot_buffer (snapshot );
680- snapshot -> buf = buf_copy ;
684+ snapshot -> buf = snapshot -> start = buf_copy ;
681685 snapshot -> eof = buf_copy + size ;
682686 }
683687
@@ -924,7 +928,12 @@ static struct ref_iterator *packed_ref_iterator_begin(
924928 */
925929 snapshot = get_snapshot (refs );
926930
927- if (!snapshot -> buf )
931+ if (prefix && * prefix )
932+ start = find_reference_location (snapshot , prefix , 0 );
933+ else
934+ start = snapshot -> start ;
935+
936+ if (start == snapshot -> eof )
928937 return empty_ref_iterator_begin ();
929938
930939 iter = xcalloc (1 , sizeof (* iter ));
@@ -934,11 +943,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
934943 iter -> snapshot = snapshot ;
935944 acquire_snapshot (snapshot );
936945
937- if (prefix && * prefix )
938- start = find_reference_location (snapshot , prefix , 0 );
939- else
940- start = snapshot -> buf + snapshot -> header_len ;
941-
942946 iter -> pos = start ;
943947 iter -> eof = snapshot -> eof ;
944948 strbuf_init (& iter -> refname_buf , 0 );
0 commit comments