in builtin/pack-objects.c [4461:4848]
int cmd_pack_objects(int argc,
const char **argv,
const char *prefix,
struct repository *repo UNUSED)
{
int use_internal_rev_list = 0;
int shallow = 0;
int all_progress_implied = 0;
struct strvec rp = STRVEC_INIT;
int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
int rev_list_index = 0;
int stdin_packs = 0;
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
struct list_objects_filter_options filter_options =
LIST_OBJECTS_FILTER_INIT;
struct option pack_objects_options[] = {
OPT_CALLBACK_F('q', "quiet", &progress, NULL,
N_("do not show progress meter"),
PARSE_OPT_NOARG, option_parse_quiet),
OPT_SET_INT(0, "progress", &progress,
N_("show progress meter"), 1),
OPT_SET_INT(0, "all-progress", &progress,
N_("show progress meter during object writing phase"), 2),
OPT_BOOL(0, "all-progress-implied",
&all_progress_implied,
N_("similar to --all-progress when progress meter is shown")),
OPT_CALLBACK_F(0, "index-version", &pack_idx_opts, N_("<version>[,<offset>]"),
N_("write the pack index file in the specified idx format version"),
PARSE_OPT_NONEG, option_parse_index_version),
OPT_UNSIGNED(0, "max-pack-size", &pack_size_limit,
N_("maximum size of each output pack file")),
OPT_BOOL(0, "local", &local,
N_("ignore borrowed objects from alternate object store")),
OPT_BOOL(0, "incremental", &incremental,
N_("ignore packed objects")),
OPT_INTEGER(0, "window", &window,
N_("limit pack window by objects")),
OPT_UNSIGNED(0, "window-memory", &window_memory_limit,
N_("limit pack window by memory in addition to object limit")),
OPT_INTEGER(0, "depth", &depth,
N_("maximum length of delta chain allowed in the resulting pack")),
OPT_BOOL(0, "reuse-delta", &reuse_delta,
N_("reuse existing deltas")),
OPT_BOOL(0, "reuse-object", &reuse_object,
N_("reuse existing objects")),
OPT_BOOL(0, "delta-base-offset", &allow_ofs_delta,
N_("use OFS_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,
N_("do not create an empty pack output")),
OPT_BOOL(0, "revs", &use_internal_rev_list,
N_("read revision arguments from standard input")),
OPT_SET_INT_F(0, "unpacked", &rev_list_unpacked,
N_("limit the objects to those that are not yet packed"),
1, PARSE_OPT_NONEG),
OPT_SET_INT_F(0, "all", &rev_list_all,
N_("include objects reachable from any reference"),
1, PARSE_OPT_NONEG),
OPT_SET_INT_F(0, "reflog", &rev_list_reflog,
N_("include objects referred by reflog entries"),
1, PARSE_OPT_NONEG),
OPT_SET_INT_F(0, "indexed-objects", &rev_list_index,
N_("include objects referred to by the index"),
1, PARSE_OPT_NONEG),
OPT_BOOL(0, "stdin-packs", &stdin_packs,
N_("read packs from stdin")),
OPT_BOOL(0, "stdout", &pack_to_stdout,
N_("output pack to stdout")),
OPT_BOOL(0, "include-tag", &include_tag,
N_("include tag objects that refer to objects to be packed")),
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
N_("keep unreachable objects")),
OPT_BOOL(0, "pack-loose-unreachable", &pack_loose_unreachable,
N_("pack loose unreachable objects")),
OPT_CALLBACK_F(0, "unpack-unreachable", NULL, N_("time"),
N_("unpack unreachable objects newer than <time>"),
PARSE_OPT_OPTARG, option_parse_unpack_unreachable),
OPT_BOOL(0, "cruft", &cruft, N_("create a cruft pack")),
OPT_CALLBACK_F(0, "cruft-expiration", NULL, N_("time"),
N_("expire cruft objects older than <time>"),
PARSE_OPT_OPTARG, option_parse_cruft_expiration),
OPT_BOOL(0, "sparse", &sparse,
N_("use the sparse reachability algorithm")),
OPT_BOOL(0, "thin", &thin,
N_("create thin packs")),
OPT_BOOL(0, "shallow", &shallow,
N_("create packs suitable for shallow fetches")),
OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk,
N_("ignore packs that have companion .keep file")),
OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
N_("ignore this pack")),
OPT_INTEGER(0, "compression", &pack_compression_level,
N_("pack compression level")),
OPT_BOOL(0, "keep-true-parents", &grafts_keep_true_parents,
N_("do not hide commits by grafts")),
OPT_BOOL(0, "use-bitmap-index", &use_bitmap_index,
N_("use a bitmap index if available to speed up counting objects")),
OPT_SET_INT(0, "write-bitmap-index", &write_bitmap_index,
N_("write a bitmap index together with the pack index"),
WRITE_BITMAP_TRUE),
OPT_SET_INT_F(0, "write-bitmap-index-quiet",
&write_bitmap_index,
N_("write a bitmap index if possible"),
WRITE_BITMAP_QUIET, PARSE_OPT_HIDDEN),
OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
OPT_CALLBACK_F(0, "missing", NULL, N_("action"),
N_("handling for missing objects"), PARSE_OPT_NONEG,
option_parse_missing_action),
OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects,
N_("do not pack objects in promisor packfiles")),
OPT_BOOL(0, "exclude-promisor-objects-best-effort",
&exclude_promisor_objects_best_effort,
N_("implies --missing=allow-any")),
OPT_BOOL(0, "delta-islands", &use_delta_islands,
N_("respect islands during delta compression")),
OPT_STRING_LIST(0, "uri-protocol", &uri_protocols,
N_("protocol"),
N_("exclude any configured uploadpack.blobpackfileuri with this protocol")),
OPT_INTEGER(0, "name-hash-version", &name_hash_version,
N_("use the specified name-hash function to group similar objects")),
OPT_END(),
};
if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS))
BUG("too many dfs states, increase OE_DFS_STATE_BITS");
disable_replace_refs();
sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1);
if (the_repository->gitdir) {
prepare_repo_settings(the_repository);
if (sparse < 0)
sparse = the_repository->settings.pack_use_sparse;
if (the_repository->settings.pack_use_multi_pack_reuse)
allow_pack_reuse = MULTI_PACK_REUSE;
}
reset_pack_idx_option(&pack_idx_opts);
pack_idx_opts.flags |= WRITE_REV;
git_config(git_pack_config, NULL);
if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0))
pack_idx_opts.flags &= ~WRITE_REV;
progress = isatty(2);
argc = parse_options(argc, argv, prefix, pack_objects_options,
pack_usage, 0);
if (argc) {
base_name = argv[0];
argc--;
}
if (pack_to_stdout != !base_name || argc)
usage_with_options(pack_usage, pack_objects_options);
if (depth < 0)
depth = 0;
if (depth >= (1 << OE_DEPTH_BITS)) {
warning(_("delta chain depth %d is too deep, forcing %d"),
depth, (1 << OE_DEPTH_BITS) - 1);
depth = (1 << OE_DEPTH_BITS) - 1;
}
if (cache_max_small_delta_size >= (1U << OE_Z_DELTA_BITS)) {
warning(_("pack.deltaCacheLimit is too high, forcing %d"),
(1U << OE_Z_DELTA_BITS) - 1);
cache_max_small_delta_size = (1U << OE_Z_DELTA_BITS) - 1;
}
if (window < 0)
window = 0;
strvec_push(&rp, "pack-objects");
if (thin) {
use_internal_rev_list = 1;
strvec_push(&rp, shallow
? "--objects-edge-aggressive"
: "--objects-edge");
} else
strvec_push(&rp, "--objects");
if (rev_list_all) {
use_internal_rev_list = 1;
strvec_push(&rp, "--all");
}
if (rev_list_reflog) {
use_internal_rev_list = 1;
strvec_push(&rp, "--reflog");
}
if (rev_list_index) {
use_internal_rev_list = 1;
strvec_push(&rp, "--indexed-objects");
}
if (rev_list_unpacked && !stdin_packs) {
use_internal_rev_list = 1;
strvec_push(&rp, "--unpacked");
}
if (exclude_promisor_objects && exclude_promisor_objects_best_effort)
die(_("options '%s' and '%s' cannot be used together"),
"--exclude-promisor-objects", "--exclude-promisor-objects-best-effort");
if (exclude_promisor_objects) {
use_internal_rev_list = 1;
fetch_if_missing = 0;
strvec_push(&rp, "--exclude-promisor-objects");
} else if (exclude_promisor_objects_best_effort) {
use_internal_rev_list = 1;
fetch_if_missing = 0;
option_parse_missing_action(NULL, "allow-any", 0);
/* revs configured below */
}
if (unpack_unreachable || keep_unreachable || pack_loose_unreachable)
use_internal_rev_list = 1;
if (!reuse_object)
reuse_delta = 0;
if (pack_compression_level == -1)
pack_compression_level = Z_DEFAULT_COMPRESSION;
else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)
die(_("bad pack compression level %d"), pack_compression_level);
if (!delta_search_threads) /* --threads=0 means autodetect */
delta_search_threads = online_cpus();
if (!HAVE_THREADS && delta_search_threads != 1)
warning(_("no threads support, ignoring --threads"));
if (!pack_to_stdout && !pack_size_limit)
pack_size_limit = pack_size_limit_cfg;
if (pack_to_stdout && pack_size_limit)
die(_("--max-pack-size cannot be used to build a pack for transfer"));
if (pack_size_limit && pack_size_limit < 1024*1024) {
warning(_("minimum pack size limit is 1 MiB"));
pack_size_limit = 1024*1024;
}
if (!pack_to_stdout && thin)
die(_("--thin cannot be used to build an indexable pack"));
if (keep_unreachable && unpack_unreachable)
die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "--unpack-unreachable");
if (!rev_list_all || !rev_list_reflog || !rev_list_index)
unpack_unreachable_expiration = 0;
if (stdin_packs && filter_options.choice)
die(_("cannot use --filter with --stdin-packs"));
if (stdin_packs && use_internal_rev_list)
die(_("cannot use internal rev list with --stdin-packs"));
if (cruft) {
if (use_internal_rev_list)
die(_("cannot use internal rev list with --cruft"));
if (stdin_packs)
die(_("cannot use --stdin-packs with --cruft"));
}
/*
* "soft" reasons not to use bitmaps - for on-disk repack by default we want
*
* - to produce good pack (with bitmap index not-yet-packed objects are
* packed in suboptimal order).
*
* - to use more robust pack-generation codepath (avoiding possible
* bugs in bitmap code and possible bitmap index corruption).
*/
if (!pack_to_stdout)
use_bitmap_index_default = 0;
if (use_bitmap_index < 0)
use_bitmap_index = use_bitmap_index_default;
/* "hard" reasons not to use bitmaps; these just won't work at all */
if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow(the_repository))
use_bitmap_index = 0;
if (pack_to_stdout || !rev_list_all)
write_bitmap_index = 0;
if (name_hash_version < 0)
name_hash_version = (int)git_env_ulong("GIT_TEST_NAME_HASH_VERSION", 1);
validate_name_hash_version();
if (use_delta_islands)
strvec_push(&rp, "--topo-order");
if (progress && all_progress_implied)
progress = 2;
add_extra_kept_packs(&keep_pack_list);
if (ignore_packed_keep_on_disk) {
struct packed_git *p;
for (p = get_all_packs(the_repository); p; p = p->next)
if (p->pack_local && p->pack_keep)
break;
if (!p) /* no keep-able packs found */
ignore_packed_keep_on_disk = 0;
}
if (local) {
/*
* unlike ignore_packed_keep_on_disk above, we do not
* want to unset "local" based on looking at packs, as
* it also covers non-local objects
*/
struct packed_git *p;
for (p = get_all_packs(the_repository); p; p = p->next) {
if (!p->pack_local) {
have_non_local_packs = 1;
break;
}
}
}
trace2_region_enter("pack-objects", "enumerate-objects",
the_repository);
prepare_packing_data(the_repository, &to_pack);
if (progress && !cruft)
progress_state = start_progress(the_repository,
_("Enumerating objects"), 0);
if (stdin_packs) {
/* avoids adding objects in excluded packs */
ignore_packed_keep_in_core = 1;
read_packs_list_from_stdin();
if (rev_list_unpacked)
add_unreachable_loose_objects();
} else if (cruft) {
read_cruft_objects();
} else if (!use_internal_rev_list) {
read_object_list_from_stdin();
} else {
struct rev_info revs;
repo_init_revisions(the_repository, &revs, NULL);
list_objects_filter_copy(&revs.filter, &filter_options);
if (exclude_promisor_objects_best_effort) {
revs.include_check = is_not_in_promisor_pack;
revs.include_check_obj = is_not_in_promisor_pack_obj;
}
get_object_list(&revs, rp.nr, rp.v);
release_revisions(&revs);
}
cleanup_preferred_base();
if (include_tag && nr_result)
refs_for_each_tag_ref(get_main_ref_store(the_repository),
add_ref_tag, NULL);
stop_progress(&progress_state);
trace2_region_leave("pack-objects", "enumerate-objects",
the_repository);
if (non_empty && !nr_result)
goto cleanup;
if (nr_result) {
trace2_region_enter("pack-objects", "prepare-pack",
the_repository);
prepare_pack(window, depth);
trace2_region_leave("pack-objects", "prepare-pack",
the_repository);
}
trace2_region_enter("pack-objects", "write-pack-file", the_repository);
write_excluded_by_configs();
write_pack_file();
trace2_region_leave("pack-objects", "write-pack-file", the_repository);
if (progress)
fprintf_ln(stderr,
_("Total %"PRIu32" (delta %"PRIu32"),"
" reused %"PRIu32" (delta %"PRIu32"),"
" pack-reused %"PRIu32" (from %"PRIuMAX")"),
written, written_delta, reused, reused_delta,
reuse_packfile_objects,
(uintmax_t)reuse_packfiles_used_nr);
trace2_data_intmax("pack-objects", the_repository, "written", written);
trace2_data_intmax("pack-objects", the_repository, "written/delta", written_delta);
trace2_data_intmax("pack-objects", the_repository, "reused", reused);
trace2_data_intmax("pack-objects", the_repository, "reused/delta", reused_delta);
trace2_data_intmax("pack-objects", the_repository, "pack-reused", reuse_packfile_objects);
trace2_data_intmax("pack-objects", the_repository, "packs-reused", reuse_packfiles_used_nr);
cleanup:
clear_packing_data(&to_pack);
list_objects_filter_release(&filter_options);
string_list_clear(&keep_pack_list, 0);
strvec_clear(&rp);
return 0;
}