2986
return git_default_config(k, v, cb);
2987
}
2988
2989
+/* Counters for trace2 output when in --stdin-packs mode. */
2990
+static int stdin_packs_found_nr;
2991
+static int stdin_packs_hints_nr;
2992
+
2993
+static int add_object_entry_from_pack(const struct object_id *oid,
2994
+ struct packed_git *p,
2995
+ uint32_t pos,
2996
+ void *_data)
2997
+{
2998
+ struct rev_info *revs = _data;
2999
+ struct object_info oi = OBJECT_INFO_INIT;
3000
+ off_t ofs;
3001
+ enum object_type type;
3002
+
3003
+ display_progress(progress_state, ++nr_seen);
3004
+
3005
+ if (have_duplicate_entry(oid, 0))
3006
+ return 0;
3007
+
3008
+ ofs = nth_packed_object_offset(p, pos);
3009
+ if (!want_object_in_pack(oid, 0, &p, &ofs))
3010
+ return 0;
3011
+
3012
+ oi.typep = &type;
3013
+ if (packed_object_info(the_repository, p, ofs, &oi) < 0)
3014
+ die(_("could not get type of object %s in pack %s"),
3015
+ oid_to_hex(oid), p->pack_name);
3016
+ else if (type == OBJ_COMMIT) {
3017
+ /*
3018
+ * commits in included packs are used as starting points for the
3019
+ * subsequent revision walk
3020
+ */
3021
+ add_pending_oid(revs, NULL, oid, 0);
3022
+ }
3023
+
3024
+ stdin_packs_found_nr++;
3025
+
3026
+ create_object_entry(oid, type, 0, 0, 0, p, ofs);
3027
+
3028
+ return 0;
3029
+}
3030
+
3031
+static void show_commit_pack_hint(struct commit *commit, void *_data)
3032
+{
3033
+ /* nothing to do; commits don't have a namehash */
3034
+}
3035
+
3036
+static void show_object_pack_hint(struct object *object, const char *name,
3037
+ void *_data)
3038
+{
3039
+ struct object_entry *oe = packlist_find(&to_pack, &object->oid);
3040
+ if (!oe)
3041
+ return;
3042
+
3043
+ /*
3044
+ * Our 'to_pack' list was constructed by iterating all objects packed in
3045
+ * included packs, and so doesn't have a non-zero hash field that you
3046
+ * would typically pick up during a reachability traversal.
3047
+ *
3048
+ * Make a best-effort attempt to fill in the ->hash and ->no_try_delta
3049
+ * here using a now in order to perhaps improve the delta selection
3050
+ * process.
3051
+ */
3052
+ oe->hash = pack_name_hash(name);
3053
+ oe->no_try_delta = name && no_try_delta(name);
3054
+
3055
+ stdin_packs_hints_nr++;
3056
+}
3057
+
3058
+static int pack_mtime_cmp(const void *_a, const void *_b)
3059
+{
3060
+ struct packed_git *a = ((const struct string_list_item*)_a)->util;
3061
+ struct packed_git *b = ((const struct string_list_item*)_b)->util;
3062
+
3063
+ /*
3064
+ * order packs by descending mtime so that objects are laid out
3065
+ * roughly as newest-to-oldest
3066
+ */
3067
+ if (a->mtime < b->mtime)
3068
+ return 1;
3069
+ else if (b->mtime < a->mtime)
3070
+ return -1;
3071
+ else
3072
+ return 0;
3073
+}
3074
+
3075
+static void read_packs_list_from_stdin(void)
3076
+{
3077
+ struct strbuf buf = STRBUF_INIT;
3078
+ struct string_list include_packs = STRING_LIST_INIT_DUP;
3079
+ struct string_list exclude_packs = STRING_LIST_INIT_DUP;
3080
+ struct string_list_item *item = NULL;
3081
+
3082
+ struct packed_git *p;
3083
+ struct rev_info revs;
3084
+
3085
+ repo_init_revisions(the_repository, &revs, NULL);
3086
+ /*
3087
+ * Use a revision walk to fill in the namehash of objects in the include
3088
+ * packs. To save time, we'll avoid traversing through objects that are
3089
+ * in excluded packs.
3090
+ *
3091
+ * That may cause us to avoid populating all of the namehash fields of
3092
+ * all included objects, but our goal is best-effort, since this is only
3093
+ * an optimization during delta selection.
3094
+ */
3095
+ revs.no_kept_objects = 1;
3096
+ revs.keep_pack_cache_flags |= IN_CORE_KEEP_PACKS;
3097
+ revs.blob_objects = 1;
3098
+ revs.tree_objects = 1;
3099
+ revs.tag_objects = 1;
3100
+
3101
+ while (strbuf_getline(&buf, stdin) != EOF) {
3102
+ if (!buf.len)
3103
+ continue;
3104
+
3105
+ if (*buf.buf == '^')
3106
+ string_list_append(&exclude_packs, buf.buf + 1);
3107
+ else
3108
+ string_list_append(&include_packs, buf.buf);
3109
+
3110
+ strbuf_reset(&buf);
3111
+ }
3112
+
3113
+ string_list_sort(&include_packs);
3114
+ string_list_sort(&exclude_packs);
3115
+
3116
+ for (p = get_all_packs(the_repository); p; p = p->next) {
3117
+ const char *pack_name = pack_basename(p);
3118
+
3119
+ item = string_list_lookup(&include_packs, pack_name);
3120
+ if (!item)
3121
+ item = string_list_lookup(&exclude_packs, pack_name);
3122
+
3123
+ if (item)
3124
+ item->util = p;
3125
+ }
3126
+
3127
+ /*
3128
+ * First handle all of the excluded packs, marking them as kept in-core
3129
+ * so that later calls to add_object_entry() discards any objects that
3130
+ * are also found in excluded packs.
3131
+ */
3132
+ for_each_string_list_item(item, &exclude_packs) {
3133
+ struct packed_git *p = item->util;
3134
+ if (!p)
3135
+ die(_("could not find pack '%s'"), item->string);
3136
+ p->pack_keep_in_core = 1;
3137
+ }
3138
+
3139
+ /*
3140
+ * Order packs by ascending mtime; use QSORT directly to access the
3141
+ * string_list_item's ->util pointer, which string_list_sort() does not
3142
+ * provide.
3143
+ */
3144
+ QSORT(include_packs.items, include_packs.nr, pack_mtime_cmp);
3145
+
3146
+ for_each_string_list_item(item, &include_packs) {
3147
+ struct packed_git *p = item->util;
3148
+ if (!p)
3149
+ die(_("could not find pack '%s'"), item->string);
3150
+ for_each_object_in_pack(p,
3151
+ add_object_entry_from_pack,
3152
+ &revs,
3153
+ FOR_EACH_OBJECT_PACK_ORDER);
3154
+ }
3155
+
3156
+ if (prepare_revision_walk(&revs))
3157
+ die(_("revision walk setup failed"));
3158
+ traverse_commit_list(&revs,
3159
+ show_commit_pack_hint,
3160
+ show_object_pack_hint,
3161
+ NULL);
3162
+
3163
+ trace2_data_intmax("pack-objects", the_repository, "stdin_packs_found",
3164
+ stdin_packs_found_nr);
3165
+ trace2_data_intmax("pack-objects", the_repository, "stdin_packs_hints",
3166
+ stdin_packs_hints_nr);
3167
+
3168
+ strbuf_release(&buf);
3169
+ string_list_clear(&include_packs, 0);
3170
+ string_list_clear(&exclude_packs, 0);
3171
+}
3172
+
3173
static void read_object_list_from_stdin(void)
3174
{
3175
char line[GIT_MAX_HEXSZ + 1 + PATH_MAX + 2];
3673
struct strvec rp = STRVEC_INIT;
3674
int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
3675
int rev_list_index = 0;
3676
+ int stdin_packs = 0;
3677
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
3678
struct option pack_objects_options[] = {
3679
OPT_SET_INT('q', "quiet", &progress,
3724
OPT_SET_INT_F(0, "indexed-objects", &rev_list_index,
3725
N_("include objects referred to by the index"),
3726
1, PARSE_OPT_NONEG),
3727
+ OPT_BOOL(0, "stdin-packs", &stdin_packs,
3728
+ N_("read packs from stdin")),
3729
OPT_BOOL(0, "stdout", &pack_to_stdout,
3730
N_("output pack to stdout")),
3731
OPT_BOOL(0, "include-tag", &include_tag,
3832
use_internal_rev_list = 1;
3833
strvec_push(&rp, "--indexed-objects");
3834
}
3648
- if (rev_list_unpacked) {
3835
+ if (rev_list_unpacked && !stdin_packs) {
3836
use_internal_rev_list = 1;
3837
strvec_push(&rp, "--unpacked");
3838
}
3877
if (filter_options.choice) {
3878
if (!pack_to_stdout)
3879
die(_("cannot use --filter without --stdout"));
3880
+ if (stdin_packs)
3881
+ die(_("cannot use --filter with --stdin-packs"));
3882
}
3883
3884
+ if (stdin_packs && use_internal_rev_list)
3885
+ die(_("cannot use internal rev list with --stdin-packs"));
3886
+
3887
/*
3888
* "soft" reasons not to use bitmaps - for on-disk repack by default we want
3889
*
3942
3943
if (progress)
3944
progress_state = start_progress(_("Enumerating objects"), 0);
3753
- if (!use_internal_rev_list)
3945
+ if (stdin_packs) {
3946
+ /* avoids adding objects in excluded packs */
3947
+ ignore_packed_keep_in_core = 1;
3948
+ read_packs_list_from_stdin();
3949
+ if (rev_list_unpacked)
3950
+ add_unreachable_loose_objects();
3951
+ } else if (!use_internal_rev_list)
3952
read_object_list_from_stdin();
3953
else {
3954
get_object_list(rp.nr, rp.v);