37
38
struct packed_ref_store;
39
40
-struct packed_ref_cache {
40
+/*
41
+ * A `snapshot` represents one snapshot of a `packed-refs` file.
42
+ *
43
+ * Normally, this will be a mmapped view of the contents of the
44
+ * `packed-refs` file at the time the snapshot was created. However,
45
+ * if the `packed-refs` file was not sorted, this might point at heap
46
+ * memory holding the contents of the `packed-refs` file with its
47
+ * records sorted by refname.
48
+ *
49
+ * `snapshot` instances are reference counted (via
50
+ * `acquire_snapshot()` and `release_snapshot()`). This is to prevent
51
+ * an instance from disappearing while an iterator is still iterating
52
+ * over it. Instances are garbage collected when their `referrers`
53
+ * count goes to zero.
54
+ *
55
+ * The most recent `snapshot`, if available, is referenced by the
56
+ * `packed_ref_store`. Its freshness is checked whenever
57
+ * `get_snapshot()` is called; if the existing snapshot is obsolete, a
58
+ * new snapshot is taken.
59
+ */
60
+struct snapshot {
61
/*
62
* A back-pointer to the packed_ref_store with which this
43
- * cache is associated:
63
+ * snapshot is associated:
64
*/
65
struct packed_ref_store *refs;
66
81
size_t header_len;
82
83
/*
64
- * What is the peeled state of this cache? (This is usually
65
- * determined from the header of the "packed-refs" file.)
84
+ * What is the peeled state of the `packed-refs` file that
85
+ * this snapshot represents? (This is usually determined from
86
+ * the file's header.)
87
*/
88
enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled;
89
90
/*
70
- * Count of references to the data structure in this instance,
71
- * including the pointer from files_ref_store::packed if any.
72
- * The data will not be freed as long as the reference count
73
- * is nonzero.
91
+ * Count of references to this instance, including the pointer
92
+ * from `packed_ref_store::snapshot`, if any. The instance
93
+ * will not be freed as long as the reference count is
94
+ * nonzero.
95
*/
96
unsigned int referrers;
97
77
- /* The metadata from when this packed-refs cache was read */
98
+ /*
99
+ * The metadata of the `packed-refs` file from which this
100
+ * snapshot was created, used to tell if the file has been
101
+ * replaced since we read it.
102
+ */
103
struct stat_validity validity;
104
};
105
106
/*
82
- * A container for `packed-refs`-related data. It is not (yet) a
83
- * `ref_store`.
107
+ * A `ref_store` representing references stored in a `packed-refs`
108
+ * file. It implements the `ref_store` interface, though it has some
109
+ * limitations:
110
+ *
111
+ * - It cannot store symbolic references.
112
+ *
113
+ * - It cannot store reflogs.
114
+ *
115
+ * - It does not support reference renaming (though it could).
116
+ *
117
+ * On the other hand, it can be locked outside of a reference
118
+ * transaction. In that case, it remains locked even after the
119
+ * transaction is done and the new `packed-refs` file is activated.
120
*/
121
struct packed_ref_store {
122
struct ref_store base;
127
char *path;
128
129
/*
94
- * A cache of the values read from the `packed-refs` file, if
95
- * it might still be current; otherwise, NULL.
130
+ * A snapshot of the values read from the `packed-refs` file,
131
+ * if it might still be current; otherwise, NULL.
132
*/
97
- struct packed_ref_cache *cache;
133
+ struct snapshot *snapshot;
134
135
/*
136
* Lock used for the "packed-refs" file. Note that this (and
147
};
148
149
/*
114
- * Increment the reference count of *packed_refs.
150
+ * Increment the reference count of `*snapshot`.
151
*/
116
-static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs)
152
+static void acquire_snapshot(struct snapshot *snapshot)
153
{
118
- packed_refs->referrers++;
154
+ snapshot->referrers++;
155
}
156
157
/*
122
- * If the buffer in `packed_refs` is active, then either munmap the
158
+ * If the buffer in `snapshot` is active, then either munmap the
159
* memory and close the file, or free the memory. Then set the buffer
160
* pointers to NULL.
161
*/
126
-static void release_packed_ref_buffer(struct packed_ref_cache *packed_refs)
162
+static void clear_snapshot_buffer(struct snapshot *snapshot)
163
{
128
- if (packed_refs->mmapped) {
129
- if (munmap(packed_refs->buf,
130
- packed_refs->eof - packed_refs->buf))
164
+ if (snapshot->mmapped) {
165
+ if (munmap(snapshot->buf, snapshot->eof - snapshot->buf))
166
die_errno("error ummapping packed-refs file %s",
132
- packed_refs->refs->path);
133
- packed_refs->mmapped = 0;
167
+ snapshot->refs->path);
168
+ snapshot->mmapped = 0;
169
} else {
135
- free(packed_refs->buf);
170
+ free(snapshot->buf);
171
}
137
- packed_refs->buf = packed_refs->eof = NULL;
138
- packed_refs->header_len = 0;
172
+ snapshot->buf = snapshot->eof = NULL;
173
+ snapshot->header_len = 0;
174
}
175
176
/*
142
- * Decrease the reference count of *packed_refs. If it goes to zero,
143
- * free *packed_refs and return true; otherwise return false.
177
+ * Decrease the reference count of `*snapshot`. If it goes to zero,
178
+ * free `*snapshot` and return true; otherwise return false.
179
*/
145
-static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
180
+static int release_snapshot(struct snapshot *snapshot)
181
{
147
- if (!--packed_refs->referrers) {
148
- stat_validity_clear(&packed_refs->validity);
149
- release_packed_ref_buffer(packed_refs);
150
- free(packed_refs);
182
+ if (!--snapshot->referrers) {
183
+ stat_validity_clear(&snapshot->validity);
184
+ clear_snapshot_buffer(snapshot);
185
+ free(snapshot);
186
return 1;
187
} else {
188
return 0;
227
return refs;
228
}
229
195
-static void clear_packed_ref_cache(struct packed_ref_store *refs)
230
+static void clear_snapshot(struct packed_ref_store *refs)
231
{
197
- if (refs->cache) {
198
- struct packed_ref_cache *cache = refs->cache;
232
+ if (refs->snapshot) {
233
+ struct snapshot *snapshot = refs->snapshot;
234
200
- refs->cache = NULL;
201
- release_packed_ref_cache(cache);
235
+ refs->snapshot = NULL;
236
+ release_snapshot(snapshot);
237
}
238
}
239
260
261
}
262
228
-struct packed_ref_entry {
263
+struct snapshot_record {
264
const char *start;
265
size_t len;
266
};
267
233
-static int cmp_packed_ref_entries(const void *v1, const void *v2)
268
+static int cmp_packed_ref_records(const void *v1, const void *v2)
269
{
235
- const struct packed_ref_entry *e1 = v1, *e2 = v2;
270
+ const struct snapshot_record *e1 = v1, *e2 = v2;
271
const char *r1 = e1->start + GIT_SHA1_HEXSZ + 1;
272
const char *r2 = e2->start + GIT_SHA1_HEXSZ + 1;
273
286
}
287
288
/*
254
- * Compare a packed-refs record pointed to by `rec` to the specified
255
- * NUL-terminated refname.
289
+ * Compare a snapshot record at `rec` to the specified NUL-terminated
290
+ * refname.
291
*/
257
-static int cmp_entry_to_refname(const char *rec, const char *refname)
292
+static int cmp_record_to_refname(const char *rec, const char *refname)
293
{
294
const char *r1 = rec + GIT_SHA1_HEXSZ + 1;
295
const char *r2 = refname;
307
}
308
309
/*
275
- * `packed_refs->buf` is not known to be sorted. Check whether it is,
276
- * and if not, sort it into new memory and munmap/free the old
277
- * storage.
310
+ * `snapshot->buf` is not known to be sorted. Check whether it is, and
311
+ * if not, sort it into new memory and munmap/free the old storage.
312
*/
279
-static void sort_packed_refs(struct packed_ref_cache *packed_refs)
313
+static void sort_snapshot(struct snapshot *snapshot)
314
{
281
- struct packed_ref_entry *entries = NULL;
315
+ struct snapshot_record *records = NULL;
316
size_t alloc = 0, nr = 0;
317
int sorted = 1;
318
const char *pos, *eof, *eol;
319
size_t len, i;
320
char *new_buffer, *dst;
321
288
- pos = packed_refs->buf + packed_refs->header_len;
289
- eof = packed_refs->eof;
322
+ pos = snapshot->buf + snapshot->header_len;
323
+ eof = snapshot->eof;
324
len = eof - pos;
325
326
if (!len)
327
return;
328
329
/*
296
- * Initialize entries based on a crude estimate of the number
330
+ * Initialize records based on a crude estimate of the number
331
* of references in the file (we'll grow it below if needed):
332
*/
299
- ALLOC_GROW(entries, len / 80 + 20, alloc);
333
+ ALLOC_GROW(records, len / 80 + 20, alloc);
334
335
while (pos < eof) {
336
eol = memchr(pos, '\n', eof - pos);
338
/* The safety check should prevent this. */
339
BUG("unterminated line found in packed-refs");
340
if (eol - pos < GIT_SHA1_HEXSZ + 2)
307
- die_invalid_line(packed_refs->refs->path,
341
+ die_invalid_line(snapshot->refs->path,
342
pos, eof - pos);
343
eol++;
344
if (eol < eof && *eol == '^') {
355
eol++;
356
}
357
324
- ALLOC_GROW(entries, nr + 1, alloc);
325
- entries[nr].start = pos;
326
- entries[nr].len = eol - pos;
358
+ ALLOC_GROW(records, nr + 1, alloc);
359
+ records[nr].start = pos;
360
+ records[nr].len = eol - pos;
361
nr++;
362
363
if (sorted &&
364
nr > 1 &&
331
- cmp_packed_ref_entries(&entries[nr - 2],
332
- &entries[nr - 1]) >= 0)
365
+ cmp_packed_ref_records(&records[nr - 2],
366
+ &records[nr - 1]) >= 0)
367
sorted = 0;
368
369
pos = eol;
372
if (sorted)
373
goto cleanup;
374
341
- /* We need to sort the memory. First we sort the entries array: */
342
- QSORT(entries, nr, cmp_packed_ref_entries);
375
+ /* We need to sort the memory. First we sort the records array: */
376
+ QSORT(records, nr, cmp_packed_ref_records);
377
378
/*
379
* Allocate a new chunk of memory, and copy the old memory to
346
- * the new in the order indicated by `entries` (not bothering
380
+ * the new in the order indicated by `records` (not bothering
381
* with the header line):
382
*/
383
new_buffer = xmalloc(len);
384
for (dst = new_buffer, i = 0; i < nr; i++) {
351
- memcpy(dst, entries[i].start, entries[i].len);
352
- dst += entries[i].len;
385
+ memcpy(dst, records[i].start, records[i].len);
386
+ dst += records[i].len;
387
}
388
389
/*
390
* Now munmap the old buffer and use the sorted buffer in its
391
* place:
392
*/
359
- release_packed_ref_buffer(packed_refs);
360
- packed_refs->buf = new_buffer;
361
- packed_refs->eof = new_buffer + len;
362
- packed_refs->header_len = 0;
393
+ clear_snapshot_buffer(snapshot);
394
+ snapshot->buf = new_buffer;
395
+ snapshot->eof = new_buffer + len;
396
+ snapshot->header_len = 0;
397
398
cleanup:
365
- free(entries);
399
+ free(records);
400
}
401
402
/*
440
* (GIT_SHA1_HEXSZ + 1) characters before the LF. Die if either of
441
* these checks fails.
442
*/
409
-static void verify_buffer_safe(struct packed_ref_cache *packed_refs)
443
+static void verify_buffer_safe(struct snapshot *snapshot)
444
{
411
- const char *buf = packed_refs->buf + packed_refs->header_len;
412
- const char *eof = packed_refs->eof;
445
+ const char *buf = snapshot->buf + snapshot->header_len;
446
+ const char *eof = snapshot->eof;
447
const char *last_line;
448
449
if (buf == eof)
451
452
last_line = find_start_of_record(buf, eof - 1);
453
if (*(eof - 1) != '\n' || eof - last_line < GIT_SHA1_HEXSZ + 2)
420
- die_invalid_line(packed_refs->refs->path,
454
+ die_invalid_line(snapshot->refs->path,
455
last_line, eof - last_line);
456
}
457
458
/*
459
* Depending on `mmap_strategy`, either mmap or read the contents of
426
- * the `packed-refs` file into the `packed_refs` instance. Return 1 if
427
- * the file existed and was read, or 0 if the file was absent. Die on
428
- * errors.
460
+ * 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.
462
*/
430
-static int load_contents(struct packed_ref_cache *packed_refs)
463
+static int load_contents(struct snapshot *snapshot)
464
{
465
int fd;
466
struct stat st;
467
size_t size;
468
ssize_t bytes_read;
469
437
- fd = open(packed_refs->refs->path, O_RDONLY);
470
+ fd = open(snapshot->refs->path, O_RDONLY);
471
if (fd < 0) {
472
if (errno == ENOENT) {
473
/*
479
*/
480
return 0;
481
} else {
449
- die_errno("couldn't read %s", packed_refs->refs->path);
482
+ die_errno("couldn't read %s", snapshot->refs->path);
483
}
484
}
485
453
- stat_validity_update(&packed_refs->validity, fd);
486
+ stat_validity_update(&snapshot->validity, fd);
487
488
if (fstat(fd, &st) < 0)
456
- die_errno("couldn't stat %s", packed_refs->refs->path);
489
+ die_errno("couldn't stat %s", snapshot->refs->path);
490
size = xsize_t(st.st_size);
491
492
switch (mmap_strategy) {
493
case MMAP_NONE:
461
- packed_refs->buf = xmalloc(size);
462
- bytes_read = read_in_full(fd, packed_refs->buf, size);
494
+ snapshot->buf = xmalloc(size);
495
+ bytes_read = read_in_full(fd, snapshot->buf, size);
496
if (bytes_read < 0 || bytes_read != size)
464
- die_errno("couldn't read %s", packed_refs->refs->path);
465
- packed_refs->eof = packed_refs->buf + size;
466
- packed_refs->mmapped = 0;
497
+ die_errno("couldn't read %s", snapshot->refs->path);
498
+ snapshot->eof = snapshot->buf + size;
499
+ snapshot->mmapped = 0;
500
break;
501
case MMAP_TEMPORARY:
502
case MMAP_OK:
470
- packed_refs->buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
471
- packed_refs->eof = packed_refs->buf + size;
472
- packed_refs->mmapped = 1;
503
+ snapshot->buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
504
+ snapshot->eof = snapshot->buf + size;
505
+ snapshot->mmapped = 1;
506
break;
507
}
508
close(fd);
511
}
512
513
/*
481
- * Find the place in `cache->buf` where the start of the record for
514
+ * Find the place in `snapshot->buf` where the start of the record for
515
* `refname` starts. If `mustexist` is true and the reference doesn't
516
* exist, then return NULL. If `mustexist` is false and the reference
517
* doesn't exist, then return the point where that reference would be
519
* reference name; for example, one could search for "refs/replace/"
520
* to find the start of any replace references.
521
*
489
- * The record is sought using a binary search, so `cache->buf` must be
490
- * sorted.
522
+ * The record is sought using a binary search, so `snapshot->buf` must
523
+ * be sorted.
524
*/
492
-static const char *find_reference_location(struct packed_ref_cache *cache,
525
+static const char *find_reference_location(struct snapshot *snapshot,
526
const char *refname, int mustexist)
527
{
528
/*
539
* preceding records all have reference names that come
540
* *before* `refname`.
541
*/
509
- const char *lo = cache->buf + cache->header_len;
542
+ const char *lo = snapshot->buf + snapshot->header_len;
543
544
/*
545
* A pointer to a the first character of a record whose
546
* reference name comes *after* `refname`.
547
*/
515
- const char *hi = cache->eof;
548
+ const char *hi = snapshot->eof;
549
550
while (lo < hi) {
551
const char *mid, *rec;
553
554
mid = lo + (hi - lo) / 2;
555
rec = find_start_of_record(lo, mid);
523
- cmp = cmp_entry_to_refname(rec, refname);
556
+ cmp = cmp_record_to_refname(rec, refname);
557
if (cmp < 0) {
558
lo = find_end_of_record(mid, hi);
559
} else if (cmp > 0) {
570
}
571
572
/*
540
- * Read from the `packed-refs` file into a newly-allocated
541
- * `packed_ref_cache` and return it. The return value will already
542
- * have its reference count incremented.
573
+ * Create a newly-allocated `snapshot` of the `packed-refs` file in
574
+ * its current state and return it. The return value will already have
575
+ * its reference count incremented.
576
*
577
* A comment line of the form "# pack-refs with: " may contain zero or
578
* more traits. We interpret the traits as follows:
602
*
603
* The references in this file are known to be sorted by refname.
604
*/
572
-static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
605
+static struct snapshot *create_snapshot(struct packed_ref_store *refs)
606
{
574
- struct packed_ref_cache *packed_refs = xcalloc(1, sizeof(*packed_refs));
607
+ struct snapshot *snapshot = xcalloc(1, sizeof(*snapshot));
608
int sorted = 0;
609
577
- packed_refs->refs = refs;
578
- acquire_packed_ref_cache(packed_refs);
579
- packed_refs->peeled = PEELED_NONE;
610
+ snapshot->refs = refs;
611
+ acquire_snapshot(snapshot);
612
+ snapshot->peeled = PEELED_NONE;
613
581
- if (!load_contents(packed_refs))
582
- return packed_refs;
614
+ if (!load_contents(snapshot))
615
+ return snapshot;
616
617
/* If the file has a header line, process it: */
585
- if (packed_refs->buf < packed_refs->eof && *packed_refs->buf == '#') {
618
+ if (snapshot->buf < snapshot->eof && *snapshot->buf == '#') {
619
struct strbuf tmp = STRBUF_INIT;
620
char *p;
621
const char *eol;
622
struct string_list traits = STRING_LIST_INIT_NODUP;
623
591
- eol = memchr(packed_refs->buf, '\n',
592
- packed_refs->eof - packed_refs->buf);
624
+ eol = memchr(snapshot->buf, '\n',
625
+ snapshot->eof - snapshot->buf);
626
if (!eol)
627
die_unterminated_line(refs->path,
595
- packed_refs->buf,
596
- packed_refs->eof - packed_refs->buf);
628
+ snapshot->buf,
629
+ snapshot->eof - snapshot->buf);
630
598
- strbuf_add(&tmp, packed_refs->buf, eol - packed_refs->buf);
631
+ strbuf_add(&tmp, snapshot->buf, eol - snapshot->buf);
632
633
if (!skip_prefix(tmp.buf, "# pack-refs with:", (const char **)&p))
634
die_invalid_line(refs->path,
602
- packed_refs->buf,
603
- packed_refs->eof - packed_refs->buf);
635
+ snapshot->buf,
636
+ snapshot->eof - snapshot->buf);
637
638
string_list_split_in_place(&traits, p, ' ', -1);
639
640
if (unsorted_string_list_has_string(&traits, "fully-peeled"))
608
- packed_refs->peeled = PEELED_FULLY;
641
+ snapshot->peeled = PEELED_FULLY;
642
else if (unsorted_string_list_has_string(&traits, "peeled"))
610
- packed_refs->peeled = PEELED_TAGS;
643
+ snapshot->peeled = PEELED_TAGS;
644
645
sorted = unsorted_string_list_has_string(&traits, "sorted");
646
647
/* perhaps other traits later as well */
648
649
/* The "+ 1" is for the LF character. */
617
- packed_refs->header_len = eol + 1 - packed_refs->buf;
650
+ snapshot->header_len = eol + 1 - snapshot->buf;
651
652
string_list_clear(&traits, 0);
653
strbuf_release(&tmp);
654
}
655
623
- verify_buffer_safe(packed_refs);
656
+ verify_buffer_safe(snapshot);
657
658
if (!sorted) {
626
- sort_packed_refs(packed_refs);
659
+ sort_snapshot(snapshot);
660
661
/*
662
* Reordering the records might have moved a short one
663
* to the end of the buffer, so verify the buffer's
664
* safety again:
665
*/
633
- verify_buffer_safe(packed_refs);
666
+ verify_buffer_safe(snapshot);
667
}
668
636
- if (mmap_strategy != MMAP_OK && packed_refs->mmapped) {
669
+ if (mmap_strategy != MMAP_OK && snapshot->mmapped) {
670
/*
671
* We don't want to leave the file mmapped, so we are
672
* forced to make a copy now:
673
*/
641
- size_t size = packed_refs->eof -
642
- (packed_refs->buf + packed_refs->header_len);
674
+ size_t size = snapshot->eof -
675
+ (snapshot->buf + snapshot->header_len);
676
char *buf_copy = xmalloc(size);
677
645
- memcpy(buf_copy, packed_refs->buf + packed_refs->header_len, size);
646
- release_packed_ref_buffer(packed_refs);
647
- packed_refs->buf = buf_copy;
648
- packed_refs->eof = buf_copy + size;
678
+ memcpy(buf_copy, snapshot->buf + snapshot->header_len, size);
679
+ clear_snapshot_buffer(snapshot);
680
+ snapshot->buf = buf_copy;
681
+ snapshot->eof = buf_copy + size;
682
}
683
651
- return packed_refs;
684
+ return snapshot;
685
}
686
687
/*
655
- * Check that the packed refs cache (if any) still reflects the
656
- * contents of the file. If not, clear the cache.
688
+ * Check that `refs->snapshot` (if present) still reflects the
689
+ * contents of the `packed-refs` file. If not, clear the snapshot.
690
*/
658
-static void validate_packed_ref_cache(struct packed_ref_store *refs)
691
+static void validate_snapshot(struct packed_ref_store *refs)
692
{
660
- if (refs->cache &&
661
- !stat_validity_check(&refs->cache->validity, refs->path))
662
- clear_packed_ref_cache(refs);
693
+ if (refs->snapshot &&
694
+ !stat_validity_check(&refs->snapshot->validity, refs->path))
695
+ clear_snapshot(refs);
696
}
697
698
/*
666
- * Get the packed_ref_cache for the specified packed_ref_store,
667
- * creating and populating it if it hasn't been read before or if the
668
- * file has been changed (according to its `validity` field) since it
669
- * was last read. On the other hand, if we hold the lock, then assume
670
- * that the file hasn't been changed out from under us, so skip the
671
- * extra `stat()` call in `stat_validity_check()`.
699
+ * Get the `snapshot` for the specified packed_ref_store, creating and
700
+ * populating it if it hasn't been read before or if the file has been
701
+ * changed (according to its `validity` field) since it was last read.
702
+ * On the other hand, if we hold the lock, then assume that the file
703
+ * hasn't been changed out from under us, so skip the extra `stat()`
704
+ * call in `stat_validity_check()`. This function does *not* increase
705
+ * the snapshot's reference count on behalf of the caller.
706
*/
673
-static struct packed_ref_cache *get_packed_ref_cache(struct packed_ref_store *refs)
707
+static struct snapshot *get_snapshot(struct packed_ref_store *refs)
708
{
709
if (!is_lock_file_locked(&refs->lock))
676
- validate_packed_ref_cache(refs);
710
+ validate_snapshot(refs);
711
678
- if (!refs->cache)
679
- refs->cache = read_packed_refs(refs);
712
+ if (!refs->snapshot)
713
+ refs->snapshot = create_snapshot(refs);
714
681
- return refs->cache;
715
+ return refs->snapshot;
716
}
717
718
static int packed_read_raw_ref(struct ref_store *ref_store,
721
{
722
struct packed_ref_store *refs =
723
packed_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
690
- struct packed_ref_cache *packed_refs = get_packed_ref_cache(refs);
724
+ struct snapshot *snapshot = get_snapshot(refs);
725
const char *rec;
726
727
*type = 0;
728
695
- rec = find_reference_location(packed_refs, refname, 1);
729
+ rec = find_reference_location(snapshot, refname, 1);
730
731
if (!rec) {
732
/* refname is not a packed reference. */
735
}
736
737
if (get_sha1_hex(rec, sha1))
704
- die_invalid_line(refs->path, rec, packed_refs->eof - rec);
738
+ die_invalid_line(refs->path, rec, snapshot->eof - rec);
739
740
*type = REF_ISPACKED;
741
return 0;
750
#define REF_KNOWS_PEELED 0x40
751
752
/*
719
- * An iterator over a packed-refs file that is currently mmapped.
753
+ * An iterator over a snapshot of a `packed-refs` file.
754
*/
755
struct packed_ref_iterator {
756
struct ref_iterator base;
757
724
- struct packed_ref_cache *packed_refs;
758
+ struct snapshot *snapshot;
759
726
- /* The current position in the mmapped file: */
760
+ /* The current position in the snapshot's buffer: */
761
const char *pos;
762
729
- /* The end of the mmapped file: */
763
+ /* The end of the part of the buffer that will be iterated over: */
764
const char *eof;
765
766
+ /* Scratch space for current values: */
767
struct object_id oid, peeled;
733
-
768
struct strbuf refname_buf;
769
770
unsigned int flags;
771
};
772
773
+/*
774
+ * Move the iterator to the next record in the snapshot, without
775
+ * respect for whether the record is actually required by the current
776
+ * iteration. Adjust the fields in `iter` and return `ITER_OK` or
777
+ * `ITER_DONE`. This function does not free the iterator in the case
778
+ * of `ITER_DONE`.
779
+ */
780
static int next_record(struct packed_ref_iterator *iter)
781
{
782
const char *p = iter->pos, *eol;
791
if (iter->eof - p < GIT_SHA1_HEXSZ + 2 ||
792
parse_oid_hex(p, &iter->oid, &p) ||
793
!isspace(*p++))
753
- die_invalid_line(iter->packed_refs->refs->path,
794
+ die_invalid_line(iter->snapshot->refs->path,
795
iter->pos, iter->eof - iter->pos);
796
797
eol = memchr(p, '\n', iter->eof - p);
798
if (!eol)
758
- die_unterminated_line(iter->packed_refs->refs->path,
799
+ die_unterminated_line(iter->snapshot->refs->path,
800
iter->pos, iter->eof - iter->pos);
801
802
strbuf_add(&iter->refname_buf, p, eol - p);
809
oidclr(&iter->oid);
810
iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
811
}
771
- if (iter->packed_refs->peeled == PEELED_FULLY ||
772
- (iter->packed_refs->peeled == PEELED_TAGS &&
812
+ if (iter->snapshot->peeled == PEELED_FULLY ||
813
+ (iter->snapshot->peeled == PEELED_TAGS &&
814
starts_with(iter->base.refname, "refs/tags/")))
815
iter->base.flags |= REF_KNOWS_PEELED;
816
821
if (iter->eof - p < GIT_SHA1_HEXSZ + 1 ||
822
parse_oid_hex(p, &iter->peeled, &p) ||
823
*p++ != '\n')
783
- die_invalid_line(iter->packed_refs->refs->path,
824
+ die_invalid_line(iter->snapshot->refs->path,
825
iter->pos, iter->eof - iter->pos);
826
iter->pos = p;
827
891
int ok = ITER_DONE;
892
893
strbuf_release(&iter->refname_buf);
853
- release_packed_ref_cache(iter->packed_refs);
894
+ release_snapshot(iter->snapshot);
895
base_ref_iterator_free(ref_iterator);
896
return ok;
897
}
907
const char *prefix, unsigned int flags)
908
{
909
struct packed_ref_store *refs;
869
- struct packed_ref_cache *packed_refs;
910
+ struct snapshot *snapshot;
911
const char *start;
912
struct packed_ref_iterator *iter;
913
struct ref_iterator *ref_iterator;
917
required_flags |= REF_STORE_ODB;
918
refs = packed_downcast(ref_store, required_flags, "ref_iterator_begin");
919
879
- packed_refs = get_packed_ref_cache(refs);
920
+ /*
921
+ * Note that `get_snapshot()` internally checks whether the
922
+ * snapshot is up to date with what is on disk, and re-reads
923
+ * it if not.
924
+ */
925
+ snapshot = get_snapshot(refs);
926
881
- if (!packed_refs->buf)
927
+ if (!snapshot->buf)
928
return empty_ref_iterator_begin();
929
930
iter = xcalloc(1, sizeof(*iter));
931
ref_iterator = &iter->base;
932
base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable, 1);
933
888
- /*
889
- * Note that get_packed_ref_cache() internally checks whether
890
- * the packed-ref cache is up to date with what is on disk,
891
- * and re-reads it if not.
892
- */
893
- iter->packed_refs = packed_refs;
894
- acquire_packed_ref_cache(packed_refs);
934
+ iter->snapshot = snapshot;
935
+ acquire_snapshot(snapshot);
936
937
if (prefix && *prefix)
897
- start = find_reference_location(packed_refs, prefix, 0);
938
+ start = find_reference_location(snapshot, prefix, 0);
939
else
899
- start = packed_refs->buf + packed_refs->header_len;
940
+ start = snapshot->buf + snapshot->header_len;
941
942
iter->pos = start;
902
- iter->eof = packed_refs->eof;
943
+ iter->eof = snapshot->eof;
944
strbuf_init(&iter->refname_buf, 0);
945
946
iter->base.oid = &iter->oid;
1004
1005
/*
1006
* Now that we hold the `packed-refs` lock, make sure that our
966
- * cache matches the current version of the file. Normally
967
- * `get_packed_ref_cache()` does that for us, but that
968
- * function assumes that when the file is locked, any existing
969
- * cache is still valid. We've just locked the file, but it
970
- * might have changed the moment *before* we locked it.
1007
+ * snapshot matches the current version of the file. Normally
1008
+ * `get_snapshot()` does that for us, but that function
1009
+ * assumes that when the file is locked, any existing snapshot
1010
+ * is still valid. We've just locked the file, but it might
1011
+ * have changed the moment *before* we locked it.
1012
*/
972
- validate_packed_ref_cache(refs);
1013
+ validate_snapshot(refs);
1014
1015
/*
1016
* Now make sure that the packed-refs file as it exists in the
976
- * locked state is loaded into the cache:
1017
+ * locked state is loaded into the snapshot:
1018
*/
978
- get_packed_ref_cache(refs);
1019
+ get_snapshot(refs);
1020
return 0;
1021
}
1022
1043
}
1044
1045
/*
1005
- * The packed-refs header line that we write out. Perhaps other
1006
- * traits will be added later.
1046
+ * The packed-refs header line that we write out. Perhaps other traits
1047
+ * will be added later.
1048
*
1049
* Note that earlier versions of Git used to parse these traits by
1050
* looking for " trait " in the line. For this reason, the space after
1060
}
1061
1062
/*
1022
- * Write the packed-refs from the cache to the packed-refs tempfile,
1023
- * incorporating any changes from `updates`. `updates` must be a
1024
- * sorted string list whose keys are the refnames and whose util
1063
+ * Write the packed refs from the current snapshot to the packed-refs
1064
+ * tempfile, incorporating any changes from `updates`. `updates` must
1065
+ * be a sorted string list whose keys are the refnames and whose util
1066
* values are `struct ref_update *`. On error, rollback the tempfile,
1067
* write an error message to `err`, and return a nonzero value.
1068
*
1303
/*
1304
* Note that we *don't* skip transactions with zero updates,
1305
* because such a transaction might be executed for the side
1265
- * effect of ensuring that all of the references are peeled.
1266
- * If the caller wants to optimize away empty transactions, it
1267
- * should do so itself.
1306
+ * effect of ensuring that all of the references are peeled or
1307
+ * ensuring that the `packed-refs` file is sorted. If the
1308
+ * caller wants to optimize away empty transactions, it should
1309
+ * do so itself.
1310
*/
1311
1312
data = xcalloc(1, sizeof(*data));
1372
int ret = TRANSACTION_GENERIC_ERROR;
1373
char *packed_refs_path;
1374
1333
- clear_packed_ref_cache(refs);
1375
+ clear_snapshot(refs);
1376
1377
packed_refs_path = get_locked_file_path(&refs->lock);
1378
if (rename_tempfile(&refs->tempfile, packed_refs_path)) {