packed_ref_store: make class into a subclass of `ref_store`

Add the infrastructure to make `packed_ref_store` implement `ref_store`, at least formally (few of the methods are actually implemented yet). Change the functions in its interface to take `ref_store *` arguments. Change `files_ref_store` to store a pointer to `ref_store *` and to call functions via the virtual `ref_store` interface where possible. This also means that a few `packed_ref_store` functions can become static. This is a work in progress. Some more `ref_store` methods will soon be implemented (e.g., those having to do with reference transactions). But some of them will never be implemented (e.g., those having to do with symrefs or reflogs). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jun 23, 2017 at 09:01 UTC e0cc8ac8202f7d6a721cc87fd5346a6c7f453302
4 files changed +227 -45
refs/files-backend.c
+8 -8
@@ -28,7 +28,7 @@ struct files_ref_store {
28
29 struct ref_cache *loose;
30
31 - struct packed_ref_store *packed_ref_store;
31 + struct ref_store *packed_ref_store;
32 };
33
34 static void clear_loose_ref_cache(struct files_ref_store *refs)
@@ -311,8 +311,8 @@ stat_ref:
311 if (lstat(path, &st) < 0) {
312 if (errno != ENOENT)
313 goto out;
314 - if (packed_read_raw_ref(refs->packed_ref_store, refname,
315 - sha1, referent, type)) {
314 + if (refs_read_raw_ref(refs->packed_ref_store, refname,
315 + sha1, referent, type)) {
316 errno = ENOENT;
317 goto out;
318 }
@@ -351,8 +351,8 @@ stat_ref:
351 * ref is supposed to be, there could still be a
352 * packed ref:
353 */
354 - if (packed_read_raw_ref(refs->packed_ref_store, refname,
355 - sha1, referent, type)) {
354 + if (refs_read_raw_ref(refs->packed_ref_store, refname,
355 + sha1, referent, type)) {
356 errno = EISDIR;
357 goto out;
358 }
@@ -683,7 +683,7 @@ static int files_peel_ref(struct ref_store *ref_store,
683 * have REF_KNOWS_PEELED.
684 */
685 if (flag & REF_ISPACKED &&
686 - !packed_peel_ref(refs->packed_ref_store, refname, sha1))
686 + !refs_peel_ref(refs->packed_ref_store, refname, sha1))
687 return 0;
688
689 return peel_object(base, sha1);
@@ -804,8 +804,8 @@ static struct ref_iterator *files_ref_iterator_begin(
804 * ones in files_ref_iterator_advance(), after we have merged
805 * the packed and loose references.
806 */
807 - packed_iter = packed_ref_iterator_begin(
808 - refs->packed_ref_store, prefix,
807 + packed_iter = refs_ref_iterator_begin(
808 + refs->packed_ref_store, prefix, 0,
809 DO_FOR_EACH_INCLUDE_BROKEN);
810
811 iter->iter0 = overlay_ref_iterator_begin(loose_iter, packed_iter);
refs/packed-backend.c
+212 -20
@@ -50,6 +50,8 @@ static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
50 * `ref_store`.
51 */
52 struct packed_ref_store {
53 + struct ref_store base;
54 +
55 unsigned int store_flags;
56
57 /* The path of the "packed-refs" file: */
@@ -68,14 +70,17 @@ struct packed_ref_store {
70 struct lock_file lock;
71 };
72
71 -struct packed_ref_store *packed_ref_store_create(
72 - const char *path, unsigned int store_flags)
73 +struct ref_store *packed_ref_store_create(const char *path,
74 + unsigned int store_flags)
75 {
76 struct packed_ref_store *refs = xcalloc(1, sizeof(*refs));
77 + struct ref_store *ref_store = (struct ref_store *)refs;
78
79 + base_ref_store_init(ref_store, &refs_be_packed);
80 refs->store_flags = store_flags;
81 +
82 refs->path = xstrdup(path);
78 - return refs;
83 + return ref_store;
84 }
85
86 /*
@@ -91,6 +96,31 @@ static void packed_assert_main_repository(struct packed_ref_store *refs,
96 die("BUG: operation %s only allowed for main ref store", caller);
97 }
98
99 +/*
100 + * Downcast `ref_store` to `packed_ref_store`. Die if `ref_store` is
101 + * not a `packed_ref_store`. Also die if `packed_ref_store` doesn't
102 + * support at least the flags specified in `required_flags`. `caller`
103 + * is used in any necessary error messages.
104 + */
105 +static struct packed_ref_store *packed_downcast(struct ref_store *ref_store,
106 + unsigned int required_flags,
107 + const char *caller)
108 +{
109 + struct packed_ref_store *refs;
110 +
111 + if (ref_store->be != &refs_be_packed)
112 + die("BUG: ref_store is type \"%s\" not \"packed\" in %s",
113 + ref_store->be->name, caller);
114 +
115 + refs = (struct packed_ref_store *)ref_store;
116 +
117 + if ((refs->store_flags & required_flags) != required_flags)
118 + die("BUG: unallowed operation (%s), requires %x, has %x\n",
119 + caller, required_flags, refs->store_flags);
120 +
121 + return refs;
122 +}
123 +
124 static void clear_packed_ref_cache(struct packed_ref_store *refs)
125 {
126 if (refs->cache) {
@@ -287,9 +317,12 @@ static struct ref_dir *get_packed_refs(struct packed_ref_store *refs)
317 * (see lock_packed_refs()). To actually write the packed-refs file,
318 * call commit_packed_refs().
319 */
290 -void add_packed_ref(struct packed_ref_store *refs,
320 +void add_packed_ref(struct ref_store *ref_store,
321 const char *refname, const struct object_id *oid)
322 {
323 + struct packed_ref_store *refs =
324 + packed_downcast(ref_store, REF_STORE_WRITE,
325 + "add_packed_ref");
326 struct ref_dir *packed_refs;
327 struct ref_entry *packed_entry;
328
@@ -322,10 +355,13 @@ static struct ref_entry *get_packed_ref(struct packed_ref_store *refs,
355 return find_ref_entry(get_packed_refs(refs), refname);
356 }
357
325 -int packed_read_raw_ref(struct packed_ref_store *refs,
326 - const char *refname, unsigned char *sha1,
327 - struct strbuf *referent, unsigned int *type)
358 +static int packed_read_raw_ref(struct ref_store *ref_store,
359 + const char *refname, unsigned char *sha1,
360 + struct strbuf *referent, unsigned int *type)
361 {
362 + struct packed_ref_store *refs =
363 + packed_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
364 +
365 struct ref_entry *entry;
366
367 *type = 0;
@@ -341,9 +377,12 @@ int packed_read_raw_ref(struct packed_ref_store *refs,
377 return 0;
378 }
379
344 -int packed_peel_ref(struct packed_ref_store *refs,
345 - const char *refname, unsigned char *sha1)
380 +static int packed_peel_ref(struct ref_store *ref_store,
381 + const char *refname, unsigned char *sha1)
382 {
383 + struct packed_ref_store *refs =
384 + packed_downcast(ref_store, REF_STORE_READ | REF_STORE_ODB,
385 + "peel_ref");
386 struct ref_entry *r = get_packed_ref(refs, refname);
387
388 if (!r || peel_entry(r, 0))
@@ -420,12 +459,18 @@ static struct ref_iterator_vtable packed_ref_iterator_vtable = {
459 packed_ref_iterator_abort
460 };
461
423 -struct ref_iterator *packed_ref_iterator_begin(
424 - struct packed_ref_store *refs,
462 +static struct ref_iterator *packed_ref_iterator_begin(
463 + struct ref_store *ref_store,
464 const char *prefix, unsigned int flags)
465 {
466 + struct packed_ref_store *refs;
467 struct packed_ref_iterator *iter;
468 struct ref_iterator *ref_iterator;
469 + unsigned int required_flags = REF_STORE_READ;
470 +
471 + if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
472 + required_flags |= REF_STORE_ODB;
473 + refs = packed_downcast(ref_store, required_flags, "ref_iterator_begin");
474
475 iter = xcalloc(1, sizeof(*iter));
476 ref_iterator = &iter->base;
@@ -459,14 +504,15 @@ static void write_packed_entry(FILE *fh, const char *refname,
504 fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled));
505 }
506
462 -int lock_packed_refs(struct packed_ref_store *refs, int flags)
507 +int lock_packed_refs(struct ref_store *ref_store, int flags)
508 {
509 + struct packed_ref_store *refs =
510 + packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN,
511 + "lock_packed_refs");
512 static int timeout_configured = 0;
513 static int timeout_value = 1000;
514 struct packed_ref_cache *packed_ref_cache;
515
468 - packed_assert_main_repository(refs, "lock_packed_refs");
469 -
516 if (!timeout_configured) {
517 git_config_get_int("core.packedrefstimeout", &timeout_value);
518 timeout_configured = 1;
@@ -507,8 +553,11 @@ static const char PACKED_REFS_HEADER[] =
553 * lock_packed_refs()). Return zero on success. On errors, set errno
554 * and return a nonzero value.
555 */
510 -int commit_packed_refs(struct packed_ref_store *refs)
556 +int commit_packed_refs(struct ref_store *ref_store)
557 {
558 + struct packed_ref_store *refs =
559 + packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN,
560 + "commit_packed_refs");
561 struct packed_ref_cache *packed_ref_cache =
562 get_packed_ref_cache(refs);
563 int ok, error = 0;
@@ -516,8 +565,6 @@ int commit_packed_refs(struct packed_ref_store *refs)
565 FILE *out;
566 struct ref_iterator *iter;
567
519 - packed_assert_main_repository(refs, "commit_packed_refs");
520 -
568 if (!is_lock_file_locked(&refs->lock))
569 die("BUG: packed-refs not locked");
570
@@ -573,9 +620,12 @@ static void rollback_packed_refs(struct packed_ref_store *refs)
620 *
621 * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
622 */
576 -int repack_without_refs(struct packed_ref_store *refs,
623 +int repack_without_refs(struct ref_store *ref_store,
624 struct string_list *refnames, struct strbuf *err)
625 {
626 + struct packed_ref_store *refs =
627 + packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN,
628 + "repack_without_refs");
629 struct ref_dir *packed;
630 struct string_list_item *refname;
631 int ret, needs_repacking = 0, removed = 0;
@@ -595,7 +645,7 @@ int repack_without_refs(struct packed_ref_store *refs,
645 if (!needs_repacking)
646 return 0; /* no refname exists in packed refs */
647
598 - if (lock_packed_refs(refs, 0)) {
648 + if (lock_packed_refs(&refs->base, 0)) {
649 unable_to_lock_message(refs->path, errno, err);
650 return -1;
651 }
@@ -615,9 +665,151 @@ int repack_without_refs(struct packed_ref_store *refs,
665 }
666
667 /* Write what remains */
618 - ret = commit_packed_refs(refs);
668 + ret = commit_packed_refs(&refs->base);
669 if (ret)
670 strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
671 strerror(errno));
672 return ret;
673 }
674 +
675 +static int packed_init_db(struct ref_store *ref_store, struct strbuf *err)
676 +{
677 + /* Nothing to do. */
678 + return 0;
679 +}
680 +
681 +static int packed_transaction_prepare(struct ref_store *ref_store,
682 + struct ref_transaction *transaction,
683 + struct strbuf *err)
684 +{
685 + die("BUG: not implemented yet");
686 +}
687 +
688 +static int packed_transaction_abort(struct ref_store *ref_store,
689 + struct ref_transaction *transaction,
690 + struct strbuf *err)
691 +{
692 + die("BUG: not implemented yet");
693 +}
694 +
695 +static int packed_transaction_finish(struct ref_store *ref_store,
696 + struct ref_transaction *transaction,
697 + struct strbuf *err)
698 +{
699 + die("BUG: not implemented yet");
700 +}
701 +
702 +static int packed_initial_transaction_commit(struct ref_store *ref_store,
703 + struct ref_transaction *transaction,
704 + struct strbuf *err)
705 +{
706 + return ref_transaction_commit(transaction, err);
707 +}
708 +
709 +static int packed_delete_refs(struct ref_store *ref_store, const char *msg,
710 + struct string_list *refnames, unsigned int flags)
711 +{
712 + die("BUG: not implemented yet");
713 +}
714 +
715 +static int packed_pack_refs(struct ref_store *ref_store, unsigned int flags)
716 +{
717 + /*
718 + * Packed refs are already packed. It might be that loose refs
719 + * are packed *into* a packed refs store, but that is done by
720 + * updating the packed references via a transaction.
721 + */
722 + return 0;
723 +}
724 +
725 +static int packed_create_symref(struct ref_store *ref_store,
726 + const char *refname, const char *target,
727 + const char *logmsg)
728 +{
729 + die("BUG: packed reference store does not support symrefs");
730 +}
731 +
732 +static int packed_rename_ref(struct ref_store *ref_store,
733 + const char *oldrefname, const char *newrefname,
734 + const char *logmsg)
735 +{
736 + die("BUG: packed reference store does not support renaming references");
737 +}
738 +
739 +static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)
740 +{
741 + return empty_ref_iterator_begin();
742 +}
743 +
744 +static int packed_for_each_reflog_ent(struct ref_store *ref_store,
745 + const char *refname,
746 + each_reflog_ent_fn fn, void *cb_data)
747 +{
748 + return 0;
749 +}
750 +
751 +static int packed_for_each_reflog_ent_reverse(struct ref_store *ref_store,
752 + const char *refname,
753 + each_reflog_ent_fn fn,
754 + void *cb_data)
755 +{
756 + return 0;
757 +}
758 +
759 +static int packed_reflog_exists(struct ref_store *ref_store,
760 + const char *refname)
761 +{
762 + return 0;
763 +}
764 +
765 +static int packed_create_reflog(struct ref_store *ref_store,
766 + const char *refname, int force_create,
767 + struct strbuf *err)
768 +{
769 + die("BUG: packed reference store does not support reflogs");
770 +}
771 +
772 +static int packed_delete_reflog(struct ref_store *ref_store,
773 + const char *refname)
774 +{
775 + return 0;
776 +}
777 +
778 +static int packed_reflog_expire(struct ref_store *ref_store,
779 + const char *refname, const unsigned char *sha1,
780 + unsigned int flags,
781 + reflog_expiry_prepare_fn prepare_fn,
782 + reflog_expiry_should_prune_fn should_prune_fn,
783 + reflog_expiry_cleanup_fn cleanup_fn,
784 + void *policy_cb_data)
785 +{
786 + return 0;
787 +}
788 +
789 +struct ref_storage_be refs_be_packed = {
790 + NULL,
791 + "packed",
792 + packed_ref_store_create,
793 + packed_init_db,
794 + packed_transaction_prepare,
795 + packed_transaction_finish,
796 + packed_transaction_abort,
797 + packed_initial_transaction_commit,
798 +
799 + packed_pack_refs,
800 + packed_peel_ref,
801 + packed_create_symref,
802 + packed_delete_refs,
803 + packed_rename_ref,
804 +
805 + packed_ref_iterator_begin,
806 + packed_read_raw_ref,
807 +
808 + packed_reflog_iterator_begin,
809 + packed_for_each_reflog_ent,
810 + packed_for_each_reflog_ent_reverse,
811 + packed_reflog_exists,
812 + packed_create_reflog,
813 + packed_delete_reflog,
814 + packed_reflog_expire
815 +};
refs/packed-backend.h
+6 -17
@@ -1,33 +1,22 @@
1 #ifndef REFS_PACKED_BACKEND_H
2 #define REFS_PACKED_BACKEND_H
3
4 -struct packed_ref_store *packed_ref_store_create(
5 - const char *path, unsigned int store_flags);
6 -
7 -int packed_read_raw_ref(struct packed_ref_store *refs,
8 - const char *refname, unsigned char *sha1,
9 - struct strbuf *referent, unsigned int *type);
10 -
11 -int packed_peel_ref(struct packed_ref_store *refs,
12 - const char *refname, unsigned char *sha1);
13 -
14 -struct ref_iterator *packed_ref_iterator_begin(
15 - struct packed_ref_store *refs,
16 - const char *prefix, unsigned int flags);
4 +struct ref_store *packed_ref_store_create(const char *path,
5 + unsigned int store_flags);
6
7 /*
8 * Lock the packed-refs file for writing. Flags is passed to
9 * hold_lock_file_for_update(). Return 0 on success. On errors, set
10 * errno appropriately and return a nonzero value.
11 */
23 -int lock_packed_refs(struct packed_ref_store *refs, int flags);
12 +int lock_packed_refs(struct ref_store *ref_store, int flags);
13
25 -void add_packed_ref(struct packed_ref_store *refs,
14 +void add_packed_ref(struct ref_store *ref_store,
15 const char *refname, const struct object_id *oid);
16
28 -int commit_packed_refs(struct packed_ref_store *refs);
17 +int commit_packed_refs(struct ref_store *ref_store);
18
30 -int repack_without_refs(struct packed_ref_store *refs,
19 +int repack_without_refs(struct ref_store *ref_store,
20 struct string_list *refnames, struct strbuf *err);
21
22 #endif /* REFS_PACKED_BACKEND_H */
refs/refs-internal.h
+1
@@ -664,6 +664,7 @@ struct ref_storage_be {
664 };
665
666 extern struct ref_storage_be refs_be_files;
667 +extern struct ref_storage_be refs_be_packed;
668
669 /*
670 * A representation of the reference store for the main repository or