217
static int incremental;
218
static int ignore_packed_keep_on_disk;
219
static int ignore_packed_keep_in_core;
220
+static int ignore_packed_keep_in_core_open;
221
static int ignore_packed_keep_in_core_has_cruft;
222
static int allow_ofs_delta;
223
static struct pack_idx_option pack_idx_opts;
1619
/*
1620
* Then handle .keep first, as we have a fast(er) path there.
1621
*/
1621
- if (ignore_packed_keep_on_disk || ignore_packed_keep_in_core) {
1622
+ if (ignore_packed_keep_on_disk || ignore_packed_keep_in_core ||
1623
+ ignore_packed_keep_in_core_open) {
1624
/*
1625
* Set the flags for the kept-pack cache to be the ones we want
1626
* to ignore.
1634
flags |= KEPT_PACK_ON_DISK;
1635
if (ignore_packed_keep_in_core)
1636
flags |= KEPT_PACK_IN_CORE;
1637
+ if (ignore_packed_keep_in_core_open)
1638
+ flags |= KEPT_PACK_IN_CORE_OPEN;
1639
1640
/*
1641
* If the object is in a pack that we want to ignore, *and* we
1647
return 0;
1648
if (ignore_packed_keep_in_core && p->pack_keep_in_core)
1649
return 0;
1650
+ if (ignore_packed_keep_in_core_open && p->pack_keep_in_core_open)
1651
+ return 0;
1652
if (has_object_kept_pack(p->repo, oid, flags))
1653
return 0;
1654
} else {
3748
void *_data)
3749
{
3750
off_t ofs;
3751
+ struct object_info oi = OBJECT_INFO_INIT;
3752
enum object_type type = OBJ_NONE;
3753
3754
display_progress(progress_state, ++nr_seen);
3756
if (have_duplicate_entry(oid, 0))
3757
return 0;
3758
3752
- ofs = nth_packed_object_offset(p, pos);
3753
- if (!want_object_in_pack(oid, 0, &p, &ofs))
3754
- return 0;
3759
+ stdin_packs_found_nr++;
3760
3756
- if (p) {
3757
- struct object_info oi = OBJECT_INFO_INIT;
3758
-
3759
- oi.typep = &type;
3760
- if (packed_object_info(p, ofs, &oi) < 0) {
3761
- die(_("could not get type of object %s in pack %s"),
3762
- oid_to_hex(oid), p->pack_name);
3763
- } else if (type == OBJ_COMMIT) {
3764
- struct rev_info *revs = _data;
3765
- /*
3766
- * commits in included packs are used as starting points for the
3767
- * subsequent revision walk
3768
- */
3769
- add_pending_oid(revs, NULL, oid, 0);
3770
- }
3761
+ ofs = nth_packed_object_offset(p, pos);
3762
3772
- stdin_packs_found_nr++;
3763
+ oi.typep = &type;
3764
+ if (packed_object_info(p, ofs, &oi) < 0) {
3765
+ die(_("could not get type of object %s in pack %s"),
3766
+ oid_to_hex(oid), p->pack_name);
3767
+ } else if (type == OBJ_COMMIT) {
3768
+ struct rev_info *revs = _data;
3769
+ /*
3770
+ * commits in included packs are used as starting points
3771
+ * for the subsequent revision walk
3772
+ *
3773
+ * Note that we do want to walk through commits that are
3774
+ * present in excluded-open ('!') packs to pick up any
3775
+ * objects reachable from them not present in the
3776
+ * excluded-closed ('^') packs.
3777
+ *
3778
+ * However, we'll only add those objects to the packing
3779
+ * list after checking `want_object_in_pack()` below.
3780
+ */
3781
+ add_pending_oid(revs, NULL, oid, 0);
3782
}
3783
3784
+ if (!want_object_in_pack(oid, 0, &p, &ofs))
3785
+ return 0;
3786
+
3787
create_object_entry(oid, type, 0, 0, 0, p, ofs);
3788
3789
return 0;
3844
* - STDIN_PACK_EXCLUDE_CLOSED: objects in any packs with this flag
3845
* bit set should be excluded from the output pack.
3846
*
3835
- * Objects in packs whose 'kind' bits include STDIN_PACK_INCLUDE are
3836
- * used as traversal tips when invoked with --stdin-packs=follow.
3847
+ * - STDIN_PACK_EXCLUDE_OPEN: objects in any packs with this flag
3848
+ * bit set should be excluded from the output pack, but are not
3849
+ * guaranteed to be closed under reachability.
3850
+ *
3851
+ * Objects in packs whose 'kind' bits include STDIN_PACK_INCLUDE or
3852
+ * STDIN_PACK_EXCLUDE_OPEN are used as traversal tips when invoked
3853
+ * with --stdin-packs=follow.
3854
*/
3855
enum stdin_pack_info_kind {
3856
STDIN_PACK_INCLUDE = (1<<0),
3857
STDIN_PACK_EXCLUDE_CLOSED = (1<<1),
3858
+ STDIN_PACK_EXCLUDE_OPEN = (1<<2),
3859
};
3860
3861
struct stdin_pack_info {
3880
return 0;
3881
}
3882
3883
+static int stdin_packs_include_check_obj(struct object *obj, void *data UNUSED)
3884
+{
3885
+ return !has_object_kept_pack(to_pack.repo, &obj->oid,
3886
+ KEPT_PACK_IN_CORE);
3887
+}
3888
+
3889
+static int stdin_packs_include_check(struct commit *commit, void *data)
3890
+{
3891
+ return stdin_packs_include_check_obj((struct object *)commit, data);
3892
+}
3893
+
3894
static void stdin_packs_add_pack_entries(struct strmap *packs,
3895
struct rev_info *revs)
3896
{
3917
for_each_string_list_item(item, &keys) {
3918
struct stdin_pack_info *info = item->util;
3919
3891
- if (info->kind & STDIN_PACK_INCLUDE)
3920
+ if (info->kind & STDIN_PACK_EXCLUDE_OPEN) {
3921
+ /*
3922
+ * When open-excluded packs ("!") are present, stop
3923
+ * the parent walk at closed-excluded ("^") packs.
3924
+ * Objects behind a "^" boundary are guaranteed to
3925
+ * have closure and should not be rescued.
3926
+ */
3927
+ revs->include_check = stdin_packs_include_check;
3928
+ revs->include_check_obj = stdin_packs_include_check_obj;
3929
+ }
3930
+
3931
+ if ((info->kind & STDIN_PACK_INCLUDE) ||
3932
+ (info->kind & STDIN_PACK_EXCLUDE_OPEN))
3933
for_each_object_in_pack(info->p,
3934
add_object_entry_from_pack,
3935
revs,
3939
string_list_clear(&keys, 0);
3940
}
3941
3901
-static void stdin_packs_read_input(struct rev_info *revs)
3942
+static void stdin_packs_read_input(struct rev_info *revs,
3943
+ enum stdin_packs_mode mode)
3944
{
3945
struct strbuf buf = STRBUF_INIT;
3946
struct strmap packs = STRMAP_INIT;
3955
continue;
3956
else if (*key == '^')
3957
kind = STDIN_PACK_EXCLUDE_CLOSED;
3958
+ else if (*key == '!' && mode == STDIN_PACKS_MODE_FOLLOW)
3959
+ kind = STDIN_PACK_EXCLUDE_OPEN;
3960
3961
if (kind != STDIN_PACK_INCLUDE)
3962
key++;
4003
p->pack_keep_in_core = 1;
4004
}
4005
4006
+ if (info->kind & STDIN_PACK_EXCLUDE_OPEN) {
4007
+ /*
4008
+ * Marking excluded open packs as kept in-core
4009
+ * (open) for the same reason as we marked
4010
+ * exclude closed packs as kept in-core.
4011
+ *
4012
+ * Use a separate flag here to ensure we don't
4013
+ * halt our traversal at these packs, since they
4014
+ * are not guaranteed to have closure.
4015
+ *
4016
+ */
4017
+ p->pack_keep_in_core_open = 1;
4018
+ }
4019
+
4020
info->p = p;
4021
}
4022
4060
4061
/* avoids adding objects in excluded packs */
4062
ignore_packed_keep_in_core = 1;
4005
- stdin_packs_read_input(&revs);
4063
+ if (mode == STDIN_PACKS_MODE_FOLLOW) {
4064
+ /*
4065
+ * In '--stdin-packs=follow' mode, additionally ignore
4066
+ * objects in excluded-open packs to prevent them from
4067
+ * appearing in the resulting pack.
4068
+ */
4069
+ ignore_packed_keep_in_core_open = 1;
4070
+ }
4071
+ stdin_packs_read_input(&revs, mode);
4072
if (rev_list_unpacked)
4073
add_unreachable_loose_objects(&revs);
4074