packed-backend.c: rename a bunch of things and update comments

We've made huge changes to this file, and some of the old names and comments are no longer very fitting. So rename a bunch of things: * `struct packed_ref_cache` → `struct snapshot` * `acquire_packed_ref_cache()` → `acquire_snapshot()` * `release_packed_ref_buffer()` → `clear_snapshot_buffer()` * `release_packed_ref_cache()` → `release_snapshot()` * `clear_packed_ref_cache()` → `clear_snapshot()` * `struct packed_ref_entry` → `struct snapshot_record` * `cmp_packed_ref_entries()` → `cmp_packed_ref_records()` * `cmp_entry_to_refname()` → `cmp_record_to_refname()` * `sort_packed_refs()` → `sort_snapshot()` * `read_packed_refs()` → `create_snapshot()` * `validate_packed_ref_cache()` → `validate_snapshot()` * `get_packed_ref_cache()` → `get_snapshot()` * Renamed local variables and struct members accordingly. Also update a bunch of comments to reflect the renaming and the accumulated changes that the code has undergone. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Sep 25, 2017 at 10:00 UTC cff28ca94cca0fd4712aa37f6ca93430bb3351d8
1 file changed +232 -190
refs/packed-backend.c
+232 -190
@@ -37,10 +37,30 @@ static enum mmap_strategy mmap_strategy = MMAP_OK;
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
@@ -61,26 +81,42 @@ struct packed_ref_cache {
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;
@@ -91,10 +127,10 @@ struct packed_ref_store {
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
@@ -111,43 +147,42 @@ struct packed_ref_store {
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;
@@ -192,13 +227,13 @@ static struct packed_ref_store *packed_downcast(struct ref_store *ref_store,
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
@@ -225,14 +260,14 @@ static NORETURN void die_invalid_line(const char *path,
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
@@ -251,10 +286,10 @@ static int cmp_packed_ref_entries(const void *v1, const void *v2)
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;
@@ -272,31 +307,30 @@ static int cmp_entry_to_refname(const char *rec, const char *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);
@@ -304,7 +338,7 @@ static void sort_packed_refs(struct packed_ref_cache *packed_refs)
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 == '^') {
@@ -321,15 +355,15 @@ static void sort_packed_refs(struct packed_ref_cache *packed_refs)
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;
@@ -338,31 +372,31 @@ static void sort_packed_refs(struct packed_ref_cache *packed_refs)
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 /*
@@ -406,10 +440,10 @@ static const char *find_end_of_record(const char *p, const char *end)
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)
@@ -417,24 +451,23 @@ static void verify_buffer_safe(struct packed_ref_cache *packed_refs)
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 /*
@@ -446,30 +479,30 @@ static int load_contents(struct packed_ref_cache *packed_refs)
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);
@@ -478,7 +511,7 @@ static int load_contents(struct packed_ref_cache *packed_refs)
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
@@ -486,10 +519,10 @@ static int load_contents(struct packed_ref_cache *packed_refs)
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 /*
@@ -506,13 +539,13 @@ static const char *find_reference_location(struct packed_ref_cache *cache,
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;
@@ -520,7 +553,7 @@ static const char *find_reference_location(struct packed_ref_cache *cache,
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) {
@@ -537,9 +570,9 @@ static const char *find_reference_location(struct packed_ref_cache *cache,
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:
@@ -569,116 +602,117 @@ static const char *find_reference_location(struct packed_ref_cache *cache,
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,
@@ -687,12 +721,12 @@ 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. */
@@ -701,7 +735,7 @@ static int packed_read_raw_ref(struct ref_store *ref_store,
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;
@@ -716,26 +750,33 @@ static int packed_read_raw_ref(struct ref_store *ref_store,
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;
@@ -750,12 +791,12 @@ static int next_record(struct packed_ref_iterator *iter)
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);
@@ -768,8 +809,8 @@ static int next_record(struct packed_ref_iterator *iter)
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
@@ -780,7 +821,7 @@ static int next_record(struct packed_ref_iterator *iter)
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
@@ -850,7 +891,7 @@ static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
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 }
@@ -866,7 +907,7 @@ static struct ref_iterator *packed_ref_iterator_begin(
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;
@@ -876,30 +917,30 @@ static struct ref_iterator *packed_ref_iterator_begin(
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;
@@ -963,19 +1004,19 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err)
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
@@ -1002,8 +1043,8 @@ int packed_refs_is_locked(struct ref_store *ref_store)
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
@@ -1019,9 +1060,9 @@ static int packed_init_db(struct ref_store *ref_store, struct strbuf *err)
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 *
@@ -1262,9 +1303,10 @@ static int packed_transaction_prepare(struct ref_store *ref_store,
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));
@@ -1330,7 +1372,7 @@ static int packed_transaction_finish(struct ref_store *ref_store,
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)) {