Merge branch 'tb/send-pack-no-ref-delta' into seen
'git send-pack' has been taught to refrain from sending 'REF_DELTA' encoded packfiles when the other side asks it to. * tb/send-pack-no-ref-delta: send-pack: honor `no-ref-delta` capability pack-objects: support reuse with `--no-ref-delta` pack-objects: introduce `--no-ref-delta` t/helper: teach pack-deltas to list delta entries
commit
0b0563df31
|
|
@ -10,7 +10,8 @@ SYNOPSIS
|
|||
--------
|
||||
[verse]
|
||||
'git pack-objects' [-q | --progress | --all-progress] [--all-progress-implied]
|
||||
[--no-reuse-delta] [--delta-base-offset] [--non-empty]
|
||||
[--no-reuse-delta] [--delta-base-offset] [--no-ref-delta]
|
||||
[--non-empty]
|
||||
[--local] [--incremental] [--window=<n>] [--depth=<n>]
|
||||
[--revs [--unpacked | --all]] [--keep-pack=<pack-name>]
|
||||
[--cruft] [--cruft-expiration=<time>]
|
||||
|
|
@ -322,6 +323,11 @@ Note: Porcelain commands such as `git gc` (see linkgit:git-gc[1]),
|
|||
in modern Git when they put objects in your repository into pack files.
|
||||
So does `git bundle` (see linkgit:git-bundle[1]) when it creates a bundle.
|
||||
|
||||
--no-ref-delta::
|
||||
Do not emit deltas which represent their base by their literal
|
||||
object ID. This is independent of `--delta-base-offset`;
|
||||
without that option, no deltas are emitted.
|
||||
|
||||
--threads=<n>::
|
||||
Specifies the number of threads to spawn when searching for best
|
||||
delta matches. This requires that pack-objects be compiled with
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ were sent. Server MUST NOT ignore capabilities that client requested
|
|||
and server advertised. As a consequence of these rules, server MUST
|
||||
NOT advertise capabilities it does not understand.
|
||||
|
||||
The 'atomic', 'report-status', 'report-status-v2', 'delete-refs', 'quiet',
|
||||
and 'push-cert' capabilities are sent and recognized by the receive-pack
|
||||
(push to server) process.
|
||||
The 'atomic', 'report-status', 'report-status-v2', 'delete-refs',
|
||||
'no-ref-delta', 'quiet', and 'push-cert' capabilities are sent and
|
||||
recognized by the receive-pack (push to server) process.
|
||||
|
||||
The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
|
||||
by both upload-pack and receive-pack protocols. The 'agent' and 'session-id'
|
||||
|
|
@ -174,6 +174,17 @@ The server can send, and the client can understand, PACKv2 with delta referring
|
|||
its base by position in pack rather than by an obj-id. That is, they can
|
||||
send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
|
||||
|
||||
no-ref-delta
|
||||
------------
|
||||
|
||||
The receive-pack server can request, and the client can send, PACKv2
|
||||
without deltas referring to their bases by an obj-id. That is, the
|
||||
client MUST NOT send OBJ_REF_DELTA (aka type 7) in a packfile when the
|
||||
server advertises this capability.
|
||||
|
||||
This does not imply that the server understands OBJ_OFS_DELTA entries;
|
||||
that is negotiated separately with the 'ofs-delta' capability.
|
||||
|
||||
agent
|
||||
-----
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,8 @@ static inline void oe_set_delta_size(struct packing_data *pack,
|
|||
|
||||
static const char *const pack_usage[] = {
|
||||
N_("git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]\n"
|
||||
" [--no-reuse-delta] [--delta-base-offset] [--non-empty]\n"
|
||||
" [--no-reuse-delta] [--delta-base-offset] [--no-ref-delta]\n"
|
||||
" [--non-empty]\n"
|
||||
" [--local] [--incremental] [--window=<n>] [--depth=<n>]\n"
|
||||
" [--revs [--unpacked | --all]] [--keep-pack=<pack-name>]\n"
|
||||
" [--cruft] [--cruft-expiration=<time>]\n"
|
||||
|
|
@ -223,6 +224,7 @@ static int ignore_packed_keep_in_core_open;
|
|||
static const char *stdin_packs_refs_snapshot;
|
||||
static int ignore_packed_keep_in_core_has_cruft;
|
||||
static int allow_ofs_delta;
|
||||
static int allow_ref_delta = 1;
|
||||
static struct pack_idx_option pack_idx_opts;
|
||||
static const char *base_name;
|
||||
static int progress = 1;
|
||||
|
|
@ -2208,6 +2210,13 @@ static int can_reuse_delta(const struct object_id *base_oid,
|
|||
*/
|
||||
base = packlist_find(&to_pack, base_oid);
|
||||
if (base) {
|
||||
/*
|
||||
* A preferred base is omitted from the resulting pack, so it
|
||||
* can only be referenced by object ID.
|
||||
*/
|
||||
if (base->preferred_base && !allow_ref_delta)
|
||||
return 0;
|
||||
|
||||
if (!in_same_island(&delta->idx.oid, &base->idx.oid))
|
||||
return 0;
|
||||
*base_out = base;
|
||||
|
|
@ -2219,7 +2228,8 @@ static int can_reuse_delta(const struct object_id *base_oid,
|
|||
* even if it was buried too deep in history to make it into the
|
||||
* packing list.
|
||||
*/
|
||||
if (thin && bitmap_has_oid_in_uninteresting(bitmap_git, base_oid)) {
|
||||
if (allow_ref_delta && thin &&
|
||||
bitmap_has_oid_in_uninteresting(bitmap_git, base_oid)) {
|
||||
if (use_delta_islands) {
|
||||
if (!in_same_island(&delta->idx.oid, base_oid))
|
||||
return 0;
|
||||
|
|
@ -3409,6 +3419,9 @@ static int should_attempt_deltas(struct object_entry *entry)
|
|||
if (entry->no_try_delta)
|
||||
return 0;
|
||||
|
||||
if (entry->preferred_base && !allow_ref_delta)
|
||||
return 0;
|
||||
|
||||
if (!entry->preferred_base) {
|
||||
if (oe_type(entry) < 0)
|
||||
die(_("unable to get type of object %s"),
|
||||
|
|
@ -3651,7 +3664,8 @@ static void prepare_pack(int window, int depth)
|
|||
if (!pack_to_stdout)
|
||||
do_check_packed_object_crc = 1;
|
||||
|
||||
if (!to_pack.nr_objects || !window || !depth)
|
||||
if (!to_pack.nr_objects || !window || !depth ||
|
||||
(!allow_ref_delta && !allow_ofs_delta))
|
||||
return;
|
||||
|
||||
if (path_walk)
|
||||
|
|
@ -4918,7 +4932,7 @@ static int pack_options_allow_reuse(void)
|
|||
!ignore_packed_keep_on_disk &&
|
||||
!ignore_packed_keep_in_core &&
|
||||
(!local || !have_non_local_packs) &&
|
||||
!incremental;
|
||||
!incremental && (allow_ref_delta || allow_ofs_delta);
|
||||
}
|
||||
|
||||
static int get_object_list_from_bitmap(struct rev_info *revs)
|
||||
|
|
@ -4940,7 +4954,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
|
|||
&reuse_packfiles,
|
||||
&reuse_packfiles_nr,
|
||||
&reuse_packfile_bitmap,
|
||||
allow_pack_reuse == MULTI_PACK_REUSE);
|
||||
allow_pack_reuse == MULTI_PACK_REUSE,
|
||||
allow_ref_delta);
|
||||
|
||||
if (reuse_packfiles) {
|
||||
reuse_packfile_objects = bitmap_popcount(reuse_packfile_bitmap);
|
||||
|
|
@ -5373,6 +5388,8 @@ int cmd_pack_objects(int argc,
|
|||
N_("reuse existing objects")),
|
||||
OPT_BOOL(0, "delta-base-offset", &allow_ofs_delta,
|
||||
N_("use OFS_DELTA objects")),
|
||||
OPT_BOOL(0, "ref-delta", &allow_ref_delta,
|
||||
N_("use REF_DELTA objects")),
|
||||
OPT_INTEGER(0, "threads", &delta_search_threads,
|
||||
N_("use threads when searching for best delta matches")),
|
||||
OPT_BOOL(0, "non-empty", &non_empty,
|
||||
|
|
@ -5573,7 +5590,7 @@ int cmd_pack_objects(int argc,
|
|||
if (unpack_unreachable || keep_unreachable || pack_loose_unreachable)
|
||||
use_internal_rev_list = 1;
|
||||
|
||||
if (!reuse_object)
|
||||
if (!reuse_object || (!allow_ref_delta && !allow_ofs_delta))
|
||||
reuse_delta = 0;
|
||||
if (cfg->pack_compression_level == -1)
|
||||
cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
|
|||
static int receive_unpack_limit = -1;
|
||||
static int transfer_unpack_limit = -1;
|
||||
static int advertise_atomic_push = 1;
|
||||
static int advertise_no_ref_delta;
|
||||
static int advertise_push_options;
|
||||
static int advertise_sid;
|
||||
static int unpack_limit = 100;
|
||||
|
|
@ -287,6 +288,8 @@ static void show_ref(const char *path, const struct object_id *oid)
|
|||
strbuf_addstr(&cap, " atomic");
|
||||
if (prefer_ofs_delta)
|
||||
strbuf_addstr(&cap, " ofs-delta");
|
||||
if (advertise_no_ref_delta)
|
||||
strbuf_addstr(&cap, " no-ref-delta");
|
||||
if (push_cert_nonce)
|
||||
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
|
||||
if (advertise_push_options)
|
||||
|
|
@ -2629,6 +2632,8 @@ int cmd_receive_pack(int argc,
|
|||
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
|
||||
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
||||
OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL),
|
||||
OPT_HIDDEN_BOOL(0, "advertise-no-ref-delta-for-testing",
|
||||
&advertise_no_ref_delta, NULL),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2286,7 +2286,8 @@ static int try_partial_reuse(struct bitmap_index *bitmap_git,
|
|||
uint32_t pack_pos,
|
||||
off_t offset,
|
||||
struct bitmap *reuse,
|
||||
struct pack_window **w_curs)
|
||||
struct pack_window **w_curs,
|
||||
int allow_ref_delta)
|
||||
{
|
||||
off_t delta_obj_offset;
|
||||
enum object_type type;
|
||||
|
|
@ -2305,6 +2306,9 @@ static int try_partial_reuse(struct bitmap_index *bitmap_git,
|
|||
uint32_t base_pos;
|
||||
uint32_t base_bitmap_pos;
|
||||
|
||||
if (type == OBJ_REF_DELTA && !allow_ref_delta)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find the position of the base object so we can look it up
|
||||
* in our bitmaps. If we can't come up with an offset, or if
|
||||
|
|
@ -2377,20 +2381,19 @@ static int try_partial_reuse(struct bitmap_index *bitmap_git,
|
|||
|
||||
static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git,
|
||||
struct bitmapped_pack *pack,
|
||||
struct bitmap *reuse)
|
||||
struct bitmap *reuse,
|
||||
int allow_ref_delta)
|
||||
{
|
||||
struct bitmap *result = bitmap_git->result;
|
||||
struct pack_window *w_curs = NULL;
|
||||
size_t pos = pack->bitmap_pos / BITS_IN_EWORD;
|
||||
|
||||
if (!pack->bitmap_pos) {
|
||||
if (allow_ref_delta && !pack->bitmap_pos) {
|
||||
/*
|
||||
* If we're processing the first (in the case of a MIDX, the
|
||||
* preferred pack) or the only (in the case of single-pack
|
||||
* bitmaps) pack, then we can reuse whole words at a time.
|
||||
*
|
||||
* This is because we know that any deltas in this range *must*
|
||||
* have their bases chosen from the same pack, since:
|
||||
* bitmaps) pack, then any delta in this range must have its
|
||||
* base chosen from the same pack:
|
||||
*
|
||||
* - In the single pack case, there is no other pack to choose
|
||||
* them from.
|
||||
|
|
@ -2399,6 +2402,10 @@ static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git
|
|||
* all ties are broken in favor of that pack (i.e. the one
|
||||
* we're currently processing). So any duplicate bases will be
|
||||
* resolved in favor of the pack we're processing.
|
||||
*
|
||||
* When REF_DELTAs are allowed, we can therefore reuse whole
|
||||
* words at a time without inspecting object headers. Otherwise,
|
||||
* inspect each object below to avoid reusing a REF_DELTA entry.
|
||||
*/
|
||||
while (pos < result->word_alloc &&
|
||||
pos < pack->bitmap_nr / BITS_IN_EWORD &&
|
||||
|
|
@ -2448,7 +2455,8 @@ static void reuse_partial_packfile_from_bitmap_1(struct bitmap_index *bitmap_git
|
|||
}
|
||||
|
||||
if (try_partial_reuse(bitmap_git, pack, bit_pos,
|
||||
pack_pos, ofs, reuse, &w_curs) < 0) {
|
||||
pack_pos, ofs, reuse, &w_curs,
|
||||
allow_ref_delta) < 0) {
|
||||
/*
|
||||
* try_partial_reuse indicated we couldn't reuse
|
||||
* any bits, so there is no point in trying more
|
||||
|
|
@ -2483,7 +2491,8 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
|
|||
struct bitmapped_pack **packs_out,
|
||||
size_t *packs_nr_out,
|
||||
struct bitmap **reuse_out,
|
||||
int multi_pack_reuse)
|
||||
int multi_pack_reuse,
|
||||
int allow_ref_delta)
|
||||
{
|
||||
struct repository *r = bitmap_repo(bitmap_git);
|
||||
struct bitmapped_pack *packs = NULL;
|
||||
|
|
@ -2578,7 +2587,8 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
|
|||
reuse = bitmap_word_alloc(word_alloc);
|
||||
|
||||
for (i = 0; i < packs_nr; i++)
|
||||
reuse_partial_packfile_from_bitmap_1(bitmap_git, &packs[i], reuse);
|
||||
reuse_partial_packfile_from_bitmap_1(bitmap_git, &packs[i], reuse,
|
||||
allow_ref_delta);
|
||||
|
||||
if (bitmap_is_empty(reuse)) {
|
||||
free(packs);
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
|
|||
struct bitmapped_pack **packs_out,
|
||||
size_t *packs_nr_out,
|
||||
struct bitmap **reuse_out,
|
||||
int multi_pack_reuse);
|
||||
int multi_pack_reuse,
|
||||
int allow_ref_delta);
|
||||
int rebuild_existing_bitmaps(struct bitmap_index *, struct packing_data *mapping,
|
||||
kh_oid_map_t *reused_bitmaps, int show_progress);
|
||||
void free_bitmap_index(struct bitmap_index *);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ static int pack_objects(struct repository *r,
|
|||
strvec_push(&po.args, "--thin");
|
||||
if (args->use_ofs_delta)
|
||||
strvec_push(&po.args, "--delta-base-offset");
|
||||
if (args->no_ref_delta)
|
||||
strvec_push(&po.args, "--no-ref-delta");
|
||||
if (args->quiet || !args->progress)
|
||||
strvec_push(&po.args, "-q");
|
||||
if (args->progress)
|
||||
|
|
@ -570,6 +572,8 @@ int send_pack(struct repository *r,
|
|||
allow_deleting_refs = 1;
|
||||
if (server_supports("ofs-delta"))
|
||||
args->use_ofs_delta = 1;
|
||||
if (server_supports("no-ref-delta"))
|
||||
args->no_ref_delta = 1;
|
||||
if (server_supports("side-band-64k"))
|
||||
use_sideband = 1;
|
||||
if (server_supports("quiet"))
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ struct send_pack_args {
|
|||
force_update:1,
|
||||
use_thin_pack:1,
|
||||
use_ofs_delta:1,
|
||||
no_ref_delta:1,
|
||||
dry_run:1,
|
||||
/* One of the SEND_PACK_PUSH_CERT_* constants. */
|
||||
push_cert:2,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "hash.h"
|
||||
#include "hex.h"
|
||||
#include "pack.h"
|
||||
#include "packfile.h"
|
||||
#include "pack-objects.h"
|
||||
#include "parse-options.h"
|
||||
#include "setup.h"
|
||||
|
|
@ -15,6 +16,7 @@
|
|||
|
||||
static const char *usage_str[] = {
|
||||
"test-tool pack-deltas --num-objects <num-objects>",
|
||||
"test-tool pack-deltas --list-deltas <pack>.idx",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -81,19 +83,86 @@ static void write_ref_delta(struct hashfile *f,
|
|||
free(delta_buf);
|
||||
}
|
||||
|
||||
static int list_delta(const struct object_id *oid,
|
||||
struct packed_git *p,
|
||||
uint32_t pos,
|
||||
void *_w_curs)
|
||||
{
|
||||
struct pack_window **w_curs = _w_curs;
|
||||
off_t obj_offset = nth_packed_object_offset(p, pos);
|
||||
off_t cur = obj_offset;
|
||||
size_t size;
|
||||
enum object_type type = unpack_object_header(p, w_curs, &cur,
|
||||
&size);
|
||||
|
||||
if (type < 0)
|
||||
die("unable to parse object at position %"PRIu32, pos);
|
||||
if (type != OBJ_REF_DELTA && type != OBJ_OFS_DELTA)
|
||||
return 0;
|
||||
|
||||
if (type == OBJ_REF_DELTA) {
|
||||
struct object_id base_oid;
|
||||
const unsigned char *base = use_pack(p, w_curs, cur,
|
||||
NULL);
|
||||
|
||||
oidread(&base_oid, base, p->repo->hash_algo);
|
||||
printf("%s REF_DELTA %s\n", oid_to_hex(oid),
|
||||
oid_to_hex(&base_oid));
|
||||
} else {
|
||||
off_t base_offset = get_delta_base(p, w_curs, &cur,
|
||||
type, obj_offset);
|
||||
|
||||
if (!base_offset)
|
||||
die("unable to read base of object %s", oid_to_hex(oid));
|
||||
printf("%s OFS_DELTA %"PRIuMAX"\n", oid_to_hex(oid),
|
||||
(uintmax_t)base_offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void list_deltas(const char *idx_name)
|
||||
{
|
||||
struct packed_git *p;
|
||||
struct pack_window *w_curs = NULL;
|
||||
|
||||
p = add_packed_git(the_repository, idx_name, strlen(idx_name), 1);
|
||||
if (!p || open_pack_index(p))
|
||||
die("unable to open pack index %s", idx_name);
|
||||
|
||||
if (for_each_object_in_pack(p, list_delta, &w_curs,
|
||||
ODB_FOR_EACH_OBJECT_PACK_ORDER))
|
||||
die("unable to iterate over objects in %s", idx_name);
|
||||
|
||||
unuse_pack(&w_curs);
|
||||
close_pack(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
int cmd__pack_deltas(int argc, const char **argv)
|
||||
{
|
||||
int num_objects = -1;
|
||||
int list_deltas_mode = 0;
|
||||
struct hashfile *f;
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
struct option options[] = {
|
||||
OPT_INTEGER('n', "num-objects", &num_objects, N_("the number of objects to write")),
|
||||
OPT_BOOL(0, "list-deltas", &list_deltas_mode,
|
||||
N_("list REF_DELTA and OFS_DELTA entries")),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, NULL,
|
||||
options, usage_str, 0);
|
||||
|
||||
if (list_deltas_mode) {
|
||||
if (argc != 1 || num_objects >= 0)
|
||||
usage_with_options(usage_str, options);
|
||||
setup_git_directory(the_repository);
|
||||
list_deltas(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc || num_objects < 0)
|
||||
usage_with_options(usage_str, options);
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,9 @@ test_expect_success 'unpack without delta (core.fsyncmethod=batch)' '
|
|||
|
||||
test_expect_success 'pack with REF_DELTA' '
|
||||
packname_2=$(git pack-objects --progress test-2 <obj-list 2>stderr) &&
|
||||
check_deltas stderr -gt 0
|
||||
check_deltas stderr -gt 0 &&
|
||||
test-tool pack-deltas --list-deltas test-2-$packname_2.idx >deltas &&
|
||||
test_grep " REF_DELTA " deltas
|
||||
'
|
||||
|
||||
test_expect_success 'unpack with REF_DELTA' '
|
||||
|
|
@ -204,7 +206,80 @@ test_expect_success 'unpack with REF_DELTA (core.fsyncmethod=batch)' '
|
|||
test_expect_success 'pack with OFS_DELTA' '
|
||||
packname_3=$(git pack-objects --progress --delta-base-offset test-3 \
|
||||
<obj-list 2>stderr) &&
|
||||
check_deltas stderr -gt 0
|
||||
check_deltas stderr -gt 0 &&
|
||||
test-tool pack-deltas --list-deltas test-3-$packname_3.idx >deltas &&
|
||||
test_grep " OFS_DELTA " deltas
|
||||
'
|
||||
|
||||
test_expect_success 'pack without REF_DELTA' '
|
||||
git pack-objects --no-ref-delta --stdout <obj-list >no-ref.pack &&
|
||||
git index-pack -o no-ref.idx no-ref.pack &&
|
||||
|
||||
test-tool pack-deltas --list-deltas no-ref.idx >deltas &&
|
||||
test_must_be_empty deltas
|
||||
'
|
||||
|
||||
test_expect_success 'pack without REF_DELTA with OFS_DELTA' '
|
||||
git pack-objects --delta-base-offset --no-ref-delta --stdout \
|
||||
<obj-list >no-ref-ofs.pack &&
|
||||
git index-pack -o no-ref-ofs.idx no-ref-ofs.pack &&
|
||||
|
||||
test-tool pack-deltas --list-deltas no-ref-ofs.idx >deltas &&
|
||||
test_grep " OFS_DELTA " deltas &&
|
||||
test_grep ! " REF_DELTA " deltas
|
||||
'
|
||||
|
||||
test_expect_success 'pack without REF_DELTA reuses deltas as OFS_DELTA' '
|
||||
# Install the REF_DELTA pack above and disable delta search, so any
|
||||
# output delta must be a reused REF_DELTA rewritten as OFS_DELTA.
|
||||
test_when_finished "rm -f .git/objects/pack/pack-$packname_2.*" &&
|
||||
git index-pack --stdin <test-2-${packname_2}.pack >/dev/null &&
|
||||
|
||||
git pack-objects --window=0 --delta-base-offset \
|
||||
--no-ref-delta --stdout <obj-list >reused.pack &&
|
||||
git index-pack -o reused.idx reused.pack &&
|
||||
test-tool pack-deltas --list-deltas reused.idx >deltas &&
|
||||
test_grep " OFS_DELTA " deltas &&
|
||||
test_grep ! " REF_DELTA " deltas
|
||||
'
|
||||
|
||||
test_expect_success 'pack without REF_DELTA skips excluded delta bases' '
|
||||
test_when_finished "git read-tree $tree" &&
|
||||
|
||||
echo bar >>d &&
|
||||
git update-index --add d &&
|
||||
thin_tree=$(git write-tree) &&
|
||||
thin_commit=$(git commit-tree $thin_tree -p $commit </dev/null) &&
|
||||
|
||||
{
|
||||
echo $thin_commit &&
|
||||
echo ^$commit
|
||||
} >thin-revs &&
|
||||
|
||||
# Each type appears only once in the output, so any delta must
|
||||
# use an excluded base and therefore be a REF_DELTA.
|
||||
git pack-objects --thin --stdout --revs \
|
||||
<thin-revs >thin.pack &&
|
||||
git index-pack --fix-thin --stdin thin-fixed.pack \
|
||||
<thin.pack >/dev/null &&
|
||||
|
||||
test-tool pack-deltas --list-deltas thin-fixed.idx >deltas &&
|
||||
test_grep ! " OFS_DELTA " deltas &&
|
||||
test_grep " REF_DELTA " deltas &&
|
||||
|
||||
# Store the REF_DELTA entries above and disable delta search below,
|
||||
# so any output delta would have to reuse an excluded-base
|
||||
# REF_DELTA.
|
||||
git index-pack --stdin <thin-fixed.pack >/dev/null &&
|
||||
|
||||
git pack-objects --thin --window=0 --stdout --revs \
|
||||
--delta-base-offset --no-ref-delta \
|
||||
<thin-revs >no-ref-thin.pack &&
|
||||
git index-pack --fix-thin --stdin no-ref-thin-fixed.pack \
|
||||
<no-ref-thin.pack >/dev/null &&
|
||||
|
||||
test-tool pack-deltas --list-deltas no-ref-thin-fixed.idx >deltas &&
|
||||
test_must_be_empty deltas
|
||||
'
|
||||
|
||||
test_expect_success 'unpack with OFS_DELTA' '
|
||||
|
|
|
|||
|
|
@ -111,6 +111,22 @@ test_expect_success 'reuse all objects from all packs' '
|
|||
test_pack_objects_reused_all 9 3
|
||||
'
|
||||
|
||||
test_expect_success '--no-ref-delta reuses REF_DELTA-free bitmapped packs' '
|
||||
# Whole-word reuse is unavailable under --no-ref-delta, so reusing
|
||||
# every object below exercises the per-object bitmap path.
|
||||
: >trace2.txt &&
|
||||
GIT_TRACE2_EVENT="$PWD/trace2.txt" \
|
||||
git pack-objects --stdout --revs --all --delta-base-offset \
|
||||
--no-ref-delta >got.pack &&
|
||||
|
||||
test_pack_reused 9 <trace2.txt &&
|
||||
test_packs_reused 3 <trace2.txt &&
|
||||
|
||||
git index-pack --strict -o got.idx got.pack &&
|
||||
test-tool pack-deltas --list-deltas got.idx >deltas &&
|
||||
test_grep ! " REF_DELTA " deltas
|
||||
'
|
||||
|
||||
test_expect_success 'reuse objects from first pack with middle gap' '
|
||||
for i in D E F
|
||||
do
|
||||
|
|
|
|||
|
|
@ -1548,6 +1548,20 @@ EOF
|
|||
git push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/main:refs/heads/foo
|
||||
'
|
||||
|
||||
test_expect_success 'push honors no-ref-delta capability' '
|
||||
test_commit no-ref-delta &&
|
||||
|
||||
rcvpck="git receive-pack --advertise-no-ref-delta-for-testing" &&
|
||||
|
||||
GIT_TRACE2_EVENT="$PWD/no-ref-delta" \
|
||||
git push --receive-pack="$rcvpck" no-thin/.git \
|
||||
refs/heads/main:refs/heads/bar &&
|
||||
|
||||
test_subcommand git pack-objects --all-progress-implied --revs \
|
||||
--stdout --thin --delta-base-offset --no-ref-delta -q \
|
||||
<no-ref-delta
|
||||
'
|
||||
|
||||
test_expect_success 'pushing a tag pushes the tagged object' '
|
||||
blob=$(echo unreferenced | git hash-object -w --stdin) &&
|
||||
git tag -m foo tag-of-blob $blob &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue