28
#include "reachable.h"
29
#include "oid-array.h"
30
#include "strvec.h"
31
+#include "strmap.h"
32
#include "list.h"
33
#include "packfile.h"
34
#include "object-file.h"
3821
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
+
3848
static int pack_mtime_cmp(const void *_a, const void *_b)
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;
3852
3853
/*
3854
* order packs by descending mtime so that objects are laid out
3855
* roughly as newest-to-oldest
3856
*/
3832
- if (a->mtime < b->mtime)
3857
+ if (a->p->mtime < b->p->mtime)
3858
return 1;
3834
- else if (b->mtime < a->mtime)
3859
+ else if (b->p->mtime < a->p->mtime)
3860
return -1;
3861
else
3862
return 0;
3863
}
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)
3902
{
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;
3905
struct packed_git *p;
3906
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)
3913
continue;
3914
+ else if (*key == '^')
3915
+ kind = STDIN_PACK_EXCLUDE_CLOSED;
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;
3927
3928
strbuf_reset(&buf);
3929
}
3930
3860
- string_list_sort_u(&include_packs, 0);
3861
- string_list_sort_u(&exclude_packs, 0);
3862
-
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;
3937
3866
- if ((item = string_list_lookup(&include_packs, pack_name))) {
3938
+ if (info->kind & STDIN_PACK_INCLUDE) {
3939
if (exclude_promisor_objects && p->pack_promisor)
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);
3950
}
3871
- if ((item = string_list_lookup(&exclude_packs, pack_name)))
3872
- item->util = p;
3873
- }
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
+ }
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;
3963
}
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);
3966
3967
strbuf_release(&buf);
3922
- string_list_clear(&include_packs, 0);
3923
- string_list_clear(&exclude_packs, 0);
3968
+ strmap_clear(&packs, 1);
3969
}
3970
3971
static void add_unreachable_loose_objects(struct rev_info *revs);
4002
4003
/* avoids adding objects in excluded packs */
4004
ignore_packed_keep_in_core = 1;
3960
- read_packs_list_from_stdin(&revs);
4005
+ stdin_packs_read_input(&revs);
4006
if (rev_list_unpacked)
4007
add_unreachable_loose_objects(&revs);
4008