diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-10-16 10:16:00 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-10-16 10:16:00 +0300 |
commit | 73b9c6f58358c2d6167f7a51ac06eee2fab6f5d8 (patch) | |
tree | 2361d8691ae04f6d9af4b3a71dbec663e36fb488 | |
parent | eea5e03a5a4636a95d18947643252ed52bb298ce (diff) | |
parent | 2fa233a5541d643d1adae43bcac62226cb20d92d (diff) |
Merge branch 'jk/delta-islands-with-bitmap-reuse-delta-fix'
Fix interactions between two recent topics.
* jk/delta-islands-with-bitmap-reuse-delta-fix:
pack-objects: handle island check for "external" delta base
-rw-r--r-- | builtin/pack-objects.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index e6316d294d..c6370f2716 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1469,6 +1469,57 @@ static void cleanup_preferred_base(void) done_pbase_paths_num = done_pbase_paths_alloc = 0; } +/* + * Return 1 iff the object specified by "delta" can be sent + * literally as a delta against the base in "base_sha1". If + * so, then *base_out will point to the entry in our packing + * list, or NULL if we must use the external-base list. + * + * Depth value does not matter - find_deltas() will + * never consider reused delta as the base object to + * deltify other objects against, in order to avoid + * circular deltas. + */ +static int can_reuse_delta(const unsigned char *base_sha1, + struct object_entry *delta, + struct object_entry **base_out) +{ + struct object_entry *base; + + if (!base_sha1) + return 0; + + /* + * First see if we're already sending the base (or it's explicitly in + * our "excluded" list). + */ + base = packlist_find(&to_pack, base_sha1, NULL); + if (base) { + if (!in_same_island(&delta->idx.oid, &base->idx.oid)) + return 0; + *base_out = base; + return 1; + } + + /* + * Otherwise, reachability bitmaps may tell us if the receiver has it, + * even if it was buried too deep in history to make it into the + * packing list. + */ + if (thin && bitmap_has_sha1_in_uninteresting(bitmap_git, base_sha1)) { + if (use_delta_islands) { + struct object_id base_oid; + hashcpy(base_oid.hash, base_sha1); + if (!in_same_island(&delta->idx.oid, &base_oid)) + return 0; + } + *base_out = NULL; + return 1; + } + + return 0; +} + static void check_object(struct object_entry *entry) { unsigned long canonical_size; @@ -1555,22 +1606,7 @@ static void check_object(struct object_entry *entry) break; } - if (base_ref && ( - (base_entry = packlist_find(&to_pack, base_ref, NULL)) || - (thin && - bitmap_has_sha1_in_uninteresting(bitmap_git, base_ref))) && - in_same_island(&entry->idx.oid, &base_entry->idx.oid)) { - /* - * If base_ref was set above that means we wish to - * reuse delta data, and either we found that object in - * the list of objects we want to pack, or it's one we - * know the receiver has. - * - * Depth value does not matter - find_deltas() will - * never consider reused delta as the base object to - * deltify other objects against, in order to avoid - * circular deltas. - */ + if (can_reuse_delta(base_ref, entry, &base_entry)) { oe_set_type(entry, entry->in_pack_type); SET_SIZE(entry, in_pack_size); /* delta size */ SET_DELTA_SIZE(entry, in_pack_size); |