|
28 | 28 | #include "reachable.h" |
29 | 29 | #include "oid-array.h" |
30 | 30 | #include "strvec.h" |
| 31 | +#include "strmap.h" |
31 | 32 | #include "list.h" |
32 | 33 | #include "packfile.h" |
33 | 34 | #include "object-file.h" |
@@ -3820,107 +3821,151 @@ static void show_commit_pack_hint(struct commit *commit, void *data) |
3820 | 3821 |
|
3821 | 3822 | } |
3822 | 3823 |
|
| 3824 | +/* |
| 3825 | + * stdin_pack_info_kind specifies how a pack specified over stdin |
| 3826 | + * should be treated when pack-objects is invoked with --stdin-packs. |
| 3827 | + * |
| 3828 | + * - STDIN_PACK_INCLUDE: objects in any packs with this flag bit set |
| 3829 | + * should be included in the output pack, unless they appear in an |
| 3830 | + * excluded pack. |
| 3831 | + * |
| 3832 | + * - STDIN_PACK_EXCLUDE_CLOSED: objects in any packs with this flag |
| 3833 | + * bit set should be excluded from the output pack. |
| 3834 | + * |
| 3835 | + * Objects in packs whose 'kind' bits include STDIN_PACK_INCLUDE are |
| 3836 | + * used as traversal tips when invoked with --stdin-packs=follow. |
| 3837 | + */ |
| 3838 | +enum stdin_pack_info_kind { |
| 3839 | + STDIN_PACK_INCLUDE = (1<<0), |
| 3840 | + STDIN_PACK_EXCLUDE_CLOSED = (1<<1), |
| 3841 | +}; |
| 3842 | + |
| 3843 | +struct stdin_pack_info { |
| 3844 | + struct packed_git *p; |
| 3845 | + enum stdin_pack_info_kind kind; |
| 3846 | +}; |
| 3847 | + |
3823 | 3848 | static int pack_mtime_cmp(const void *_a, const void *_b) |
3824 | 3849 | { |
3825 | | - struct packed_git *a = ((const struct string_list_item*)_a)->util; |
3826 | | - struct packed_git *b = ((const struct string_list_item*)_b)->util; |
| 3850 | + struct stdin_pack_info *a = ((const struct string_list_item*)_a)->util; |
| 3851 | + struct stdin_pack_info *b = ((const struct string_list_item*)_b)->util; |
3827 | 3852 |
|
3828 | 3853 | /* |
3829 | 3854 | * order packs by descending mtime so that objects are laid out |
3830 | 3855 | * roughly as newest-to-oldest |
3831 | 3856 | */ |
3832 | | - if (a->mtime < b->mtime) |
| 3857 | + if (a->p->mtime < b->p->mtime) |
3833 | 3858 | return 1; |
3834 | | - else if (b->mtime < a->mtime) |
| 3859 | + else if (b->p->mtime < a->p->mtime) |
3835 | 3860 | return -1; |
3836 | 3861 | else |
3837 | 3862 | return 0; |
3838 | 3863 | } |
3839 | 3864 |
|
3840 | | -static void read_packs_list_from_stdin(struct rev_info *revs) |
| 3865 | +static void stdin_packs_add_pack_entries(struct strmap *packs, |
| 3866 | + struct rev_info *revs) |
| 3867 | +{ |
| 3868 | + struct string_list keys = STRING_LIST_INIT_NODUP; |
| 3869 | + struct string_list_item *item; |
| 3870 | + struct hashmap_iter iter; |
| 3871 | + struct strmap_entry *entry; |
| 3872 | + |
| 3873 | + strmap_for_each_entry(packs, &iter, entry) { |
| 3874 | + struct stdin_pack_info *info = entry->value; |
| 3875 | + if (!info->p) |
| 3876 | + die(_("could not find pack '%s'"), entry->key); |
| 3877 | + |
| 3878 | + string_list_append(&keys, entry->key)->util = info; |
| 3879 | + } |
| 3880 | + |
| 3881 | + /* |
| 3882 | + * Order packs by ascending mtime; use QSORT directly to access the |
| 3883 | + * string_list_item's ->util pointer, which string_list_sort() does not |
| 3884 | + * provide. |
| 3885 | + */ |
| 3886 | + QSORT(keys.items, keys.nr, pack_mtime_cmp); |
| 3887 | + |
| 3888 | + for_each_string_list_item(item, &keys) { |
| 3889 | + struct stdin_pack_info *info = item->util; |
| 3890 | + |
| 3891 | + if (info->kind & STDIN_PACK_INCLUDE) |
| 3892 | + for_each_object_in_pack(info->p, |
| 3893 | + add_object_entry_from_pack, |
| 3894 | + revs, |
| 3895 | + ODB_FOR_EACH_OBJECT_PACK_ORDER); |
| 3896 | + } |
| 3897 | + |
| 3898 | + string_list_clear(&keys, 0); |
| 3899 | +} |
| 3900 | + |
| 3901 | +static void stdin_packs_read_input(struct rev_info *revs) |
3841 | 3902 | { |
3842 | 3903 | struct strbuf buf = STRBUF_INIT; |
3843 | | - struct string_list include_packs = STRING_LIST_INIT_DUP; |
3844 | | - struct string_list exclude_packs = STRING_LIST_INIT_DUP; |
3845 | | - struct string_list_item *item = NULL; |
| 3904 | + struct strmap packs = STRMAP_INIT; |
3846 | 3905 | struct packed_git *p; |
3847 | 3906 |
|
3848 | 3907 | while (strbuf_getline(&buf, stdin) != EOF) { |
3849 | | - if (!buf.len) |
| 3908 | + struct stdin_pack_info *info; |
| 3909 | + enum stdin_pack_info_kind kind = STDIN_PACK_INCLUDE; |
| 3910 | + const char *key = buf.buf; |
| 3911 | + |
| 3912 | + if (!*key) |
3850 | 3913 | continue; |
| 3914 | + else if (*key == '^') |
| 3915 | + kind = STDIN_PACK_EXCLUDE_CLOSED; |
3851 | 3916 |
|
3852 | | - if (*buf.buf == '^') |
3853 | | - string_list_append(&exclude_packs, buf.buf + 1); |
3854 | | - else |
3855 | | - string_list_append(&include_packs, buf.buf); |
| 3917 | + if (kind != STDIN_PACK_INCLUDE) |
| 3918 | + key++; |
| 3919 | + |
| 3920 | + info = strmap_get(&packs, key); |
| 3921 | + if (!info) { |
| 3922 | + CALLOC_ARRAY(info, 1); |
| 3923 | + strmap_put(&packs, key, info); |
| 3924 | + } |
| 3925 | + |
| 3926 | + info->kind |= kind; |
3856 | 3927 |
|
3857 | 3928 | strbuf_reset(&buf); |
3858 | 3929 | } |
3859 | 3930 |
|
3860 | | - string_list_sort_u(&include_packs, 0); |
3861 | | - string_list_sort_u(&exclude_packs, 0); |
3862 | | - |
3863 | 3931 | repo_for_each_pack(the_repository, p) { |
3864 | | - const char *pack_name = pack_basename(p); |
| 3932 | + struct stdin_pack_info *info; |
| 3933 | + |
| 3934 | + info = strmap_get(&packs, pack_basename(p)); |
| 3935 | + if (!info) |
| 3936 | + continue; |
3865 | 3937 |
|
3866 | | - if ((item = string_list_lookup(&include_packs, pack_name))) { |
| 3938 | + if (info->kind & STDIN_PACK_INCLUDE) { |
3867 | 3939 | if (exclude_promisor_objects && p->pack_promisor) |
3868 | 3940 | die(_("packfile %s is a promisor but --exclude-promisor-objects was given"), p->pack_name); |
3869 | | - item->util = p; |
| 3941 | + |
| 3942 | + /* |
| 3943 | + * Arguments we got on stdin may not even be |
| 3944 | + * packs. First check that to avoid segfaulting |
| 3945 | + * later on in e.g. pack_mtime_cmp(), excluded |
| 3946 | + * packs are handled below. |
| 3947 | + */ |
| 3948 | + if (!is_pack_valid(p)) |
| 3949 | + die(_("packfile %s cannot be accessed"), p->pack_name); |
3870 | 3950 | } |
3871 | | - if ((item = string_list_lookup(&exclude_packs, pack_name))) |
3872 | | - item->util = p; |
3873 | | - } |
3874 | 3951 |
|
3875 | | - /* |
3876 | | - * Arguments we got on stdin may not even be packs. First |
3877 | | - * check that to avoid segfaulting later on in |
3878 | | - * e.g. pack_mtime_cmp(), excluded packs are handled below. |
3879 | | - * |
3880 | | - * Since we first parsed our STDIN and then sorted the input |
3881 | | - * lines the pack we error on will be whatever line happens to |
3882 | | - * sort first. This is lazy, it's enough that we report one |
3883 | | - * bad case here, we don't need to report the first/last one, |
3884 | | - * or all of them. |
3885 | | - */ |
3886 | | - for_each_string_list_item(item, &include_packs) { |
3887 | | - struct packed_git *p = item->util; |
3888 | | - if (!p) |
3889 | | - die(_("could not find pack '%s'"), item->string); |
3890 | | - if (!is_pack_valid(p)) |
3891 | | - die(_("packfile %s cannot be accessed"), p->pack_name); |
3892 | | - } |
| 3952 | + if (info->kind & STDIN_PACK_EXCLUDE_CLOSED) { |
| 3953 | + /* |
| 3954 | + * Marking excluded packs as kept in-core so |
| 3955 | + * that later calls to add_object_entry() |
| 3956 | + * discards any objects that are also found in |
| 3957 | + * excluded packs. |
| 3958 | + */ |
| 3959 | + p->pack_keep_in_core = 1; |
| 3960 | + } |
3893 | 3961 |
|
3894 | | - /* |
3895 | | - * Then, handle all of the excluded packs, marking them as |
3896 | | - * kept in-core so that later calls to add_object_entry() |
3897 | | - * discards any objects that are also found in excluded packs. |
3898 | | - */ |
3899 | | - for_each_string_list_item(item, &exclude_packs) { |
3900 | | - struct packed_git *p = item->util; |
3901 | | - if (!p) |
3902 | | - die(_("could not find pack '%s'"), item->string); |
3903 | | - p->pack_keep_in_core = 1; |
| 3962 | + info->p = p; |
3904 | 3963 | } |
3905 | 3964 |
|
3906 | | - /* |
3907 | | - * Order packs by ascending mtime; use QSORT directly to access the |
3908 | | - * string_list_item's ->util pointer, which string_list_sort() does not |
3909 | | - * provide. |
3910 | | - */ |
3911 | | - QSORT(include_packs.items, include_packs.nr, pack_mtime_cmp); |
3912 | | - |
3913 | | - for_each_string_list_item(item, &include_packs) { |
3914 | | - struct packed_git *p = item->util; |
3915 | | - for_each_object_in_pack(p, |
3916 | | - add_object_entry_from_pack, |
3917 | | - revs, |
3918 | | - ODB_FOR_EACH_OBJECT_PACK_ORDER); |
3919 | | - } |
| 3965 | + stdin_packs_add_pack_entries(&packs, revs); |
3920 | 3966 |
|
3921 | 3967 | strbuf_release(&buf); |
3922 | | - string_list_clear(&include_packs, 0); |
3923 | | - string_list_clear(&exclude_packs, 0); |
| 3968 | + strmap_clear(&packs, 1); |
3924 | 3969 | } |
3925 | 3970 |
|
3926 | 3971 | static void add_unreachable_loose_objects(struct rev_info *revs); |
@@ -3957,7 +4002,7 @@ static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked) |
3957 | 4002 |
|
3958 | 4003 | /* avoids adding objects in excluded packs */ |
3959 | 4004 | ignore_packed_keep_in_core = 1; |
3960 | | - read_packs_list_from_stdin(&revs); |
| 4005 | + stdin_packs_read_input(&revs); |
3961 | 4006 | if (rev_list_unpacked) |
3962 | 4007 | add_unreachable_loose_objects(&revs); |
3963 | 4008 |
|
|
0 commit comments