@@ -68,17 +68,21 @@ struct snapshot {
68
68
int mmapped ;
69
69
70
70
/*
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.
77
84
*/
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 ;
82
86
83
87
/*
84
88
* What is the peeled state of the `packed-refs` file that
@@ -169,8 +173,7 @@ static void clear_snapshot_buffer(struct snapshot *snapshot)
169
173
} else {
170
174
free (snapshot -> buf );
171
175
}
172
- snapshot -> buf = snapshot -> eof = NULL ;
173
- snapshot -> header_len = 0 ;
176
+ snapshot -> buf = snapshot -> start = snapshot -> eof = NULL ;
174
177
}
175
178
176
179
/*
@@ -319,13 +322,14 @@ static void sort_snapshot(struct snapshot *snapshot)
319
322
size_t len , i ;
320
323
char * new_buffer , * dst ;
321
324
322
- pos = snapshot -> buf + snapshot -> header_len ;
325
+ pos = snapshot -> start ;
323
326
eof = snapshot -> eof ;
324
- len = eof - pos ;
325
327
326
- if (! len )
328
+ if (pos == eof )
327
329
return ;
328
330
331
+ len = eof - pos ;
332
+
329
333
/*
330
334
* Initialize records based on a crude estimate of the number
331
335
* of references in the file (we'll grow it below if needed):
@@ -391,9 +395,8 @@ static void sort_snapshot(struct snapshot *snapshot)
391
395
* place:
392
396
*/
393
397
clear_snapshot_buffer (snapshot );
394
- snapshot -> buf = new_buffer ;
398
+ snapshot -> buf = snapshot -> start = new_buffer ;
395
399
snapshot -> eof = new_buffer + len ;
396
- snapshot -> header_len = 0 ;
397
400
398
401
cleanup :
399
402
free (records );
@@ -442,23 +445,26 @@ static const char *find_end_of_record(const char *p, const char *end)
442
445
*/
443
446
static void verify_buffer_safe (struct snapshot * snapshot )
444
447
{
445
- const char * buf = snapshot -> buf + snapshot -> header_len ;
448
+ const char * start = snapshot -> start ;
446
449
const char * eof = snapshot -> eof ;
447
450
const char * last_line ;
448
451
449
- if (buf == eof )
452
+ if (start == eof )
450
453
return ;
451
454
452
- last_line = find_start_of_record (buf , eof - 1 );
455
+ last_line = find_start_of_record (start , eof - 1 );
453
456
if (* (eof - 1 ) != '\n' || eof - last_line < GIT_SHA1_HEXSZ + 2 )
454
457
die_invalid_line (snapshot -> refs -> path ,
455
458
last_line , eof - last_line );
456
459
}
457
460
461
+ #define SMALL_FILE_SIZE (32*1024)
462
+
458
463
/*
459
464
* Depending on `mmap_strategy`, either mmap or read the contents of
460
465
* 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.
462
468
*/
463
469
static int load_contents (struct snapshot * snapshot )
464
470
{
@@ -489,24 +495,23 @@ static int load_contents(struct snapshot *snapshot)
489
495
die_errno ("couldn't stat %s" , snapshot -> refs -> path );
490
496
size = xsize_t (st .st_size );
491
497
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 ) {
494
501
snapshot -> buf = xmalloc (size );
495
502
bytes_read = read_in_full (fd , snapshot -> buf , size );
496
503
if (bytes_read < 0 || bytes_read != size )
497
504
die_errno ("couldn't read %s" , snapshot -> refs -> path );
498
- snapshot -> eof = snapshot -> buf + size ;
499
505
snapshot -> mmapped = 0 ;
500
- break ;
501
- case MMAP_TEMPORARY :
502
- case MMAP_OK :
506
+ } else {
503
507
snapshot -> buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
504
- snapshot -> eof = snapshot -> buf + size ;
505
508
snapshot -> mmapped = 1 ;
506
- break ;
507
509
}
508
510
close (fd );
509
511
512
+ snapshot -> start = snapshot -> buf ;
513
+ snapshot -> eof = snapshot -> buf + size ;
514
+
510
515
return 1 ;
511
516
}
512
517
@@ -515,9 +520,11 @@ static int load_contents(struct snapshot *snapshot)
515
520
* `refname` starts. If `mustexist` is true and the reference doesn't
516
521
* exist, then return NULL. If `mustexist` is false and the reference
517
522
* 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.
521
528
*
522
529
* The record is sought using a binary search, so `snapshot->buf` must
523
530
* be sorted.
@@ -539,15 +546,15 @@ static const char *find_reference_location(struct snapshot *snapshot,
539
546
* preceding records all have reference names that come
540
547
* *before* `refname`.
541
548
*/
542
- const char * lo = snapshot -> buf + snapshot -> header_len ;
549
+ const char * lo = snapshot -> start ;
543
550
544
551
/*
545
552
* A pointer to a the first character of a record whose
546
553
* reference name comes *after* `refname`.
547
554
*/
548
555
const char * hi = snapshot -> eof ;
549
556
550
- while (lo < hi ) {
557
+ while (lo != hi ) {
551
558
const char * mid , * rec ;
552
559
int cmp ;
553
560
@@ -616,9 +623,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
616
623
617
624
/* If the file has a header line, process it: */
618
625
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 ;
622
627
struct string_list traits = STRING_LIST_INIT_NODUP ;
623
628
624
629
eol = memchr (snapshot -> buf , '\n' ,
@@ -628,9 +633,9 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
628
633
snapshot -> buf ,
629
634
snapshot -> eof - snapshot -> buf );
630
635
631
- strbuf_add ( & tmp , snapshot -> buf , eol - snapshot -> buf );
636
+ tmp = xmemdupz ( snapshot -> buf , eol - snapshot -> buf );
632
637
633
- if (!skip_prefix (tmp . buf , "# pack-refs with:" , (const char * * )& p ))
638
+ if (!skip_prefix (tmp , "# pack-refs with:" , (const char * * )& p ))
634
639
die_invalid_line (refs -> path ,
635
640
snapshot -> buf ,
636
641
snapshot -> eof - snapshot -> buf );
@@ -647,10 +652,10 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
647
652
/* perhaps other traits later as well */
648
653
649
654
/* The "+ 1" is for the LF character. */
650
- snapshot -> header_len = eol + 1 - snapshot -> buf ;
655
+ snapshot -> start = eol + 1 ;
651
656
652
657
string_list_clear (& traits , 0 );
653
- strbuf_release ( & tmp );
658
+ free ( tmp );
654
659
}
655
660
656
661
verify_buffer_safe (snapshot );
@@ -671,13 +676,12 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
671
676
* We don't want to leave the file mmapped, so we are
672
677
* forced to make a copy now:
673
678
*/
674
- size_t size = snapshot -> eof -
675
- (snapshot -> buf + snapshot -> header_len );
679
+ size_t size = snapshot -> eof - snapshot -> start ;
676
680
char * buf_copy = xmalloc (size );
677
681
678
- memcpy (buf_copy , snapshot -> buf + snapshot -> header_len , size );
682
+ memcpy (buf_copy , snapshot -> start , size );
679
683
clear_snapshot_buffer (snapshot );
680
- snapshot -> buf = buf_copy ;
684
+ snapshot -> buf = snapshot -> start = buf_copy ;
681
685
snapshot -> eof = buf_copy + size ;
682
686
}
683
687
@@ -924,7 +928,12 @@ static struct ref_iterator *packed_ref_iterator_begin(
924
928
*/
925
929
snapshot = get_snapshot (refs );
926
930
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 )
928
937
return empty_ref_iterator_begin ();
929
938
930
939
iter = xcalloc (1 , sizeof (* iter ));
@@ -934,11 +943,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
934
943
iter -> snapshot = snapshot ;
935
944
acquire_snapshot (snapshot );
936
945
937
- if (prefix && * prefix )
938
- start = find_reference_location (snapshot , prefix , 0 );
939
- else
940
- start = snapshot -> buf + snapshot -> header_len ;
941
-
942
946
iter -> pos = start ;
943
947
iter -> eof = snapshot -> eof ;
944
948
strbuf_init (& iter -> refname_buf , 0 );
0 commit comments