pack-objects: introduce `--no-ref-delta`
Some consumers of 'pack-objects' may wish to avoid packs which contain `REF_DELTA` entries. For instance, a 'receive-pack' implementation which retains the resulting pack without building an index of object IDs may prefer every delta base to be discoverable from an earlier entry in the same pack. Teach 'pack-objects' a new `--no-ref-delta` option to avoid writing `REF_DELTA` entries, without changing whether `OFS_DELTA` is allowed. When used without `--delta-base-offset`, no delta representation remains, so avoid delta search entirely. Otherwise, allow new deltas whose bases appear earlier in the same pack. For now, disable delta- and bitmap-reuse under `--no-ref-delta`, since either may copy an existing `REF_DELTA` entry. This is overly pessimistic, but simplifies the changes in this commit. The next commit re-enables reuse in the cases which do not require `REF_DELTA`. Signed-off-by: Taylor Blau <ttaylorr@openai.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>seen
parent
0ff1a605b8
commit
5e4971b28e
|
|
@ -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>]
|
||||
|
|
@ -297,6 +298,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
|
||||
|
|
|
|||
|
|
@ -190,7 +190,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"
|
||||
|
|
@ -221,6 +222,7 @@ static int ignore_packed_keep_in_core;
|
|||
static int ignore_packed_keep_in_core_open;
|
||||
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;
|
||||
|
|
@ -3405,6 +3407,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"),
|
||||
|
|
@ -3647,7 +3652,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)
|
||||
|
|
@ -4662,7 +4668,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;
|
||||
}
|
||||
|
||||
static int get_object_list_from_bitmap(struct rev_info *revs)
|
||||
|
|
@ -5111,6 +5117,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,
|
||||
|
|
@ -5309,7 +5317,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)
|
||||
reuse_delta = 0;
|
||||
if (cfg->pack_compression_level == -1)
|
||||
cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
|
||||
|
|
|
|||
|
|
@ -211,6 +211,58 @@ test_expect_success 'pack with OFS_DELTA' '
|
|||
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 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 &&
|
||||
|
||||
git pack-objects --thin --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' '
|
||||
check_unpack test-3-${packname_3} obj-list
|
||||
'
|
||||
|
|
|
|||
Loading…
Reference in New Issue