packfile: generalize pack directory list

In anticipation of sharing the pack directory listing with the multi-pack-index, generalize prepare_packed_git_one() into for_each_file_in_pack_dir(). Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Jul 12, 2018 at 15:39 UTC 9208e318f548d28c677203a222f02a31a15c5d0e
2 files changed +69 -38
packfile.c
+63 -38
@@ -738,13 +738,14 @@ static void report_pack_garbage(struct string_list *list)
738 report_helper(list, seen_bits, first, list->nr);
739 }
740
741 -static void prepare_packed_git_one(struct repository *r, char *objdir, int local)
741 +void for_each_file_in_pack_dir(const char *objdir,
742 + each_file_in_pack_dir_fn fn,
743 + void *data)
744 {
745 struct strbuf path = STRBUF_INIT;
746 size_t dirnamelen;
747 DIR *dir;
748 struct dirent *de;
747 - struct string_list garbage = STRING_LIST_INIT_DUP;
749
750 strbuf_addstr(&path, objdir);
751 strbuf_addstr(&path, "/pack");
@@ -759,53 +760,77 @@ static void prepare_packed_git_one(struct repository *r, char *objdir, int local
760 strbuf_addch(&path, '/');
761 dirnamelen = path.len;
762 while ((de = readdir(dir)) != NULL) {
762 - struct packed_git *p;
763 - size_t base_len;
764 -
763 if (is_dot_or_dotdot(de->d_name))
764 continue;
765
766 strbuf_setlen(&path, dirnamelen);
767 strbuf_addstr(&path, de->d_name);
768
771 - base_len = path.len;
772 - if (strip_suffix_mem(path.buf, &base_len, ".idx")) {
773 - /* Don't reopen a pack we already have. */
774 - for (p = r->objects->packed_git; p;
775 - p = p->next) {
776 - size_t len;
777 - if (strip_suffix(p->pack_name, ".pack", &len) &&
778 - len == base_len &&
779 - !memcmp(p->pack_name, path.buf, len))
780 - break;
781 - }
782 - if (p == NULL &&
783 - /*
784 - * See if it really is a valid .idx file with
785 - * corresponding .pack file that we can map.
786 - */
787 - (p = add_packed_git(path.buf, path.len, local)) != NULL)
788 - install_packed_git(r, p);
789 - }
790 -
791 - if (!report_garbage)
792 - continue;
793 -
794 - if (ends_with(de->d_name, ".idx") ||
795 - ends_with(de->d_name, ".pack") ||
796 - ends_with(de->d_name, ".bitmap") ||
797 - ends_with(de->d_name, ".keep") ||
798 - ends_with(de->d_name, ".promisor"))
799 - string_list_append(&garbage, path.buf);
800 - else
801 - report_garbage(PACKDIR_FILE_GARBAGE, path.buf);
769 + fn(path.buf, path.len, de->d_name, data);
770 }
771 +
772 closedir(dir);
804 - report_pack_garbage(&garbage);
805 - string_list_clear(&garbage, 0);
773 strbuf_release(&path);
774 }
775
776 +struct prepare_pack_data {
777 + struct repository *r;
778 + struct string_list *garbage;
779 + int local;
780 +};
781 +
782 +static void prepare_pack(const char *full_name, size_t full_name_len,
783 + const char *file_name, void *_data)
784 +{
785 + struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
786 + struct packed_git *p;
787 + size_t base_len = full_name_len;
788 +
789 + if (strip_suffix_mem(full_name, &base_len, ".idx")) {
790 + /* Don't reopen a pack we already have. */
791 + for (p = data->r->objects->packed_git; p; p = p->next) {
792 + size_t len;
793 + if (strip_suffix(p->pack_name, ".pack", &len) &&
794 + len == base_len &&
795 + !memcmp(p->pack_name, full_name, len))
796 + break;
797 + }
798 +
799 + if (!p) {
800 + p = add_packed_git(full_name, full_name_len, data->local);
801 + if (p)
802 + install_packed_git(data->r, p);
803 + }
804 + }
805 +
806 + if (!report_garbage)
807 + return;
808 +
809 + if (ends_with(file_name, ".idx") ||
810 + ends_with(file_name, ".pack") ||
811 + ends_with(file_name, ".bitmap") ||
812 + ends_with(file_name, ".keep") ||
813 + ends_with(file_name, ".promisor"))
814 + string_list_append(data->garbage, full_name);
815 + else
816 + report_garbage(PACKDIR_FILE_GARBAGE, full_name);
817 +}
818 +
819 +static void prepare_packed_git_one(struct repository *r, char *objdir, int local)
820 +{
821 + struct prepare_pack_data data;
822 + struct string_list garbage = STRING_LIST_INIT_DUP;
823 +
824 + data.r = r;
825 + data.garbage = &garbage;
826 + data.local = local;
827 +
828 + for_each_file_in_pack_dir(objdir, prepare_pack, &data);
829 +
830 + report_pack_garbage(data.garbage);
831 + string_list_clear(data.garbage, 0);
832 +}
833 +
834 static void prepare_packed_git(struct repository *r);
835 /*
836 * Give a fast, rough count of the number of objects in the repository. This
packfile.h
+6
@@ -28,6 +28,12 @@ extern char *sha1_pack_index_name(const unsigned char *sha1);
28
29 extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
30
31 +typedef void each_file_in_pack_dir_fn(const char *full_path, size_t full_path_len,
32 + const char *file_pach, void *data);
33 +void for_each_file_in_pack_dir(const char *objdir,
34 + each_file_in_pack_dir_fn fn,
35 + void *data);
36 +
37 /* A hook to report invalid files in pack directory */
38 #define PACKDIR_FILE_PACK 1
39 #define PACKDIR_FILE_IDX 2