41
#include "promisor-remote.h"
42
#include "pack-mtimes.h"
43
#include "parse-options.h"
44
+#include "blob.h"
45
+#include "tree.h"
46
+#include "path-walk.h"
47
48
/*
49
* Objects we are going to pack are collected in the `to_pack` structure.
220
static int pack_to_stdout;
221
static int sparse;
222
static int thin;
223
+static int path_walk;
224
static int num_preferred_base;
225
static struct progress *progress_state;
226
4195
}
4196
}
4197
4198
+static inline int is_oid_uninteresting(struct repository *repo,
4199
+ struct object_id *oid)
4200
+{
4201
+ struct object *o = lookup_object(repo, oid);
4202
+ return !o || (o->flags & UNINTERESTING);
4203
+}
4204
+
4205
+static int add_objects_by_path(const char *path,
4206
+ struct oid_array *oids,
4207
+ enum object_type type,
4208
+ void *data)
4209
+{
4210
+ struct object_entry **delta_list = NULL;
4211
+ size_t oe_start = to_pack.nr_objects;
4212
+ size_t oe_end;
4213
+ unsigned int sub_list_nr;
4214
+ unsigned int *processed = data;
4215
+
4216
+ /*
4217
+ * First, add all objects to the packing data, including the ones
4218
+ * marked UNINTERESTING (translated to 'exclude') as they can be
4219
+ * used as delta bases.
4220
+ */
4221
+ for (size_t i = 0; i < oids->nr; i++) {
4222
+ int exclude;
4223
+ struct object_info oi = OBJECT_INFO_INIT;
4224
+ struct object_id *oid = &oids->oid[i];
4225
+
4226
+ /* Skip objects that do not exist locally. */
4227
+ if (exclude_promisor_objects &&
4228
+ oid_object_info_extended(the_repository, oid, &oi,
4229
+ OBJECT_INFO_FOR_PREFETCH) < 0)
4230
+ continue;
4231
+
4232
+ exclude = is_oid_uninteresting(the_repository, oid);
4233
+
4234
+ if (exclude && !thin)
4235
+ continue;
4236
+
4237
+ add_object_entry(oid, type, path, exclude);
4238
+ }
4239
+
4240
+ oe_end = to_pack.nr_objects;
4241
+
4242
+ /* We can skip delta calculations if it is a no-op. */
4243
+ if (oe_end == oe_start || !window)
4244
+ return 0;
4245
+
4246
+ sub_list_nr = 0;
4247
+ if (oe_end > oe_start)
4248
+ ALLOC_ARRAY(delta_list, oe_end - oe_start);
4249
+
4250
+ for (size_t i = 0; i < oe_end - oe_start; i++) {
4251
+ struct object_entry *entry = to_pack.objects + oe_start + i;
4252
+
4253
+ if (!should_attempt_deltas(entry))
4254
+ continue;
4255
+
4256
+ delta_list[sub_list_nr++] = entry;
4257
+ }
4258
+
4259
+ /*
4260
+ * Find delta bases among this list of objects that all match the same
4261
+ * path. This causes the delta compression to be interleaved in the
4262
+ * object walk, which can lead to confusing progress indicators. This is
4263
+ * also incompatible with threaded delta calculations. In the future,
4264
+ * consider creating a list of regions in the full to_pack.objects array
4265
+ * that could be picked up by the threaded delta computation.
4266
+ */
4267
+ if (sub_list_nr && window) {
4268
+ QSORT(delta_list, sub_list_nr, type_size_sort);
4269
+ find_deltas(delta_list, &sub_list_nr, window, depth, processed);
4270
+ }
4271
+
4272
+ free(delta_list);
4273
+ return 0;
4274
+}
4275
+
4276
+static void get_object_list_path_walk(struct rev_info *revs)
4277
+{
4278
+ struct path_walk_info info = PATH_WALK_INFO_INIT;
4279
+ unsigned int processed = 0;
4280
+
4281
+ info.revs = revs;
4282
+ info.path_fn = add_objects_by_path;
4283
+ info.path_fn_data = &processed;
4284
+
4285
+ /*
4286
+ * Allow the --[no-]sparse option to be interesting here, if only
4287
+ * for testing purposes. Paths with no interesting objects will not
4288
+ * contribute to the resulting pack, but only create noisy preferred
4289
+ * base objects.
4290
+ */
4291
+ info.prune_all_uninteresting = sparse;
4292
+
4293
+ if (walk_objects_by_path(&info))
4294
+ die(_("failed to pack objects via path-walk"));
4295
+}
4296
+
4297
static void get_object_list(struct rev_info *revs, int ac, const char **av)
4298
{
4299
struct setup_revision_opt s_r_opt = {
4349
if (write_bitmap_index)
4350
mark_bitmap_preferred_tips();
4351
4249
- if (prepare_revision_walk(revs))
4250
- die(_("revision walk setup failed"));
4251
- mark_edges_uninteresting(revs, show_edge, sparse);
4252
-
4352
if (!fn_show_object)
4353
fn_show_object = show_object;
4255
- traverse_commit_list(revs,
4256
- show_commit, fn_show_object,
4257
- NULL);
4354
+
4355
+ if (path_walk) {
4356
+ get_object_list_path_walk(revs);
4357
+ } else {
4358
+ if (prepare_revision_walk(revs))
4359
+ die(_("revision walk setup failed"));
4360
+ mark_edges_uninteresting(revs, show_edge, sparse);
4361
+ traverse_commit_list(revs,
4362
+ show_commit, fn_show_object,
4363
+ NULL);
4364
+ }
4365
4366
if (unpack_unreachable_expiration) {
4367
revs->ignore_missing_links = 1;
4571
N_("use the sparse reachability algorithm")),
4572
OPT_BOOL(0, "thin", &thin,
4573
N_("create thin packs")),
4574
+ OPT_BOOL(0, "path-walk", &path_walk,
4575
+ N_("use the path-walk API to walk objects when possible")),
4576
OPT_BOOL(0, "shallow", &shallow,
4577
N_("create packs suitable for shallow fetches")),
4578
OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk,
4658
window = 0;
4659
4660
strvec_push(&rp, "pack-objects");
4552
- if (thin) {
4661
+
4662
+ if (path_walk) {
4663
+ const char *option = NULL;
4664
+ if (filter_options.choice)
4665
+ option = "--filter";
4666
+ else if (use_delta_islands)
4667
+ option = "--delta-islands";
4668
+ else if (shallow)
4669
+ option = "--shallow";
4670
+
4671
+ if (option) {
4672
+ warning(_("cannot use %s with %s"),
4673
+ option, "--path-walk");
4674
+ path_walk = 0;
4675
+ }
4676
+ }
4677
+ if (path_walk) {
4678
+ strvec_push(&rp, "--boundary");
4679
+ /*
4680
+ * We must disable the bitmaps because we are removing
4681
+ * the --objects / --objects-edge[-aggressive] options.
4682
+ */
4683
+ use_bitmap_index = 0;
4684
+ } else if (thin) {
4685
use_internal_rev_list = 1;
4686
strvec_push(&rp, shallow
4687
? "--objects-edge-aggressive"