in builtin/index-pack.c [1714:1959]
int cmd_index_pack(int argc, const char **argv, const char *prefix)
{
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
const char *curr_index;
const char *curr_rev_index = NULL;
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
const char *keep_msg = NULL;
const char *promisor_msg = NULL;
struct strbuf index_name_buf = STRBUF_INIT;
struct strbuf rev_index_name_buf = STRBUF_INIT;
struct pack_idx_entry **idx_objects;
struct pack_idx_option opts;
unsigned char pack_hash[GIT_MAX_RAWSZ];
unsigned foreign_nr = 1; /* zero is a "good" value, assume bad */
int report_end_of_input = 0;
int hash_algo = 0;
/*
* index-pack never needs to fetch missing objects except when
* REF_DELTA bases are missing (which are explicitly handled). It only
* accesses the repo to do hash collision checks and to check which
* REF_DELTA bases need to be fetched.
*/
fetch_if_missing = 0;
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(index_pack_usage);
read_replace_refs = 0;
fsck_options.walk = mark_link;
reset_pack_idx_option(&opts);
git_config(git_index_pack_config, &opts);
if (prefix && chdir(prefix))
die(_("Cannot come back to cwd"));
if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0))
rev_index = 1;
else
rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (*arg == '-') {
if (!strcmp(arg, "--stdin")) {
from_stdin = 1;
} else if (!strcmp(arg, "--fix-thin")) {
fix_thin_pack = 1;
} else if (skip_to_optional_arg(arg, "--strict", &arg)) {
strict = 1;
do_fsck_object = 1;
fsck_set_msg_types(&fsck_options, arg);
} else if (!strcmp(arg, "--check-self-contained-and-connected")) {
strict = 1;
check_self_contained_and_connected = 1;
} else if (!strcmp(arg, "--fsck-objects")) {
do_fsck_object = 1;
} else if (!strcmp(arg, "--verify")) {
verify = 1;
} else if (!strcmp(arg, "--verify-stat")) {
verify = 1;
show_stat = 1;
} else if (!strcmp(arg, "--verify-stat-only")) {
verify = 1;
show_stat = 1;
stat_only = 1;
} else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) {
; /* nothing to do */
} else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) {
; /* already parsed */
} else if (starts_with(arg, "--threads=")) {
char *end;
nr_threads = strtoul(arg+10, &end, 0);
if (!arg[10] || *end || nr_threads < 0)
usage(index_pack_usage);
if (!HAVE_THREADS && nr_threads != 1) {
warning(_("no threads support, ignoring %s"), arg);
nr_threads = 1;
}
} else if (starts_with(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;
hdr = (struct pack_header *)input_buffer;
hdr->hdr_signature = htonl(PACK_SIGNATURE);
hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
if (*c != ',')
die(_("bad %s"), arg);
hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
if (*c)
die(_("bad %s"), arg);
input_len = sizeof(*hdr);
} else if (!strcmp(arg, "-v")) {
verbose = 1;
} else if (!strcmp(arg, "--progress-title")) {
if (progress_title || (i+1) >= argc)
usage(index_pack_usage);
progress_title = argv[++i];
} else if (!strcmp(arg, "--show-resolving-progress")) {
show_resolving_progress = 1;
} else if (!strcmp(arg, "--report-end-of-input")) {
report_end_of_input = 1;
} else if (!strcmp(arg, "-o")) {
if (index_name || (i+1) >= argc)
usage(index_pack_usage);
index_name = argv[++i];
} else if (starts_with(arg, "--index-version=")) {
char *c;
opts.version = strtoul(arg + 16, &c, 10);
if (opts.version > 2)
die(_("bad %s"), arg);
if (*c == ',')
opts.off32_limit = strtoul(c+1, &c, 0);
if (*c || opts.off32_limit & 0x80000000)
die(_("bad %s"), arg);
} else if (skip_prefix(arg, "--max-input-size=", &arg)) {
max_input_size = strtoumax(arg, NULL, 10);
} else if (skip_prefix(arg, "--object-format=", &arg)) {
hash_algo = hash_algo_by_name(arg);
if (hash_algo == GIT_HASH_UNKNOWN)
die(_("unknown hash algorithm '%s'"), arg);
repo_set_hash_algo(the_repository, hash_algo);
} else if (!strcmp(arg, "--rev-index")) {
rev_index = 1;
} else if (!strcmp(arg, "--no-rev-index")) {
rev_index = 0;
} else
usage(index_pack_usage);
continue;
}
if (pack_name)
usage(index_pack_usage);
pack_name = arg;
}
if (!pack_name && !from_stdin)
usage(index_pack_usage);
if (fix_thin_pack && !from_stdin)
die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin");
if (from_stdin && !startup_info->have_repository)
die(_("--stdin requires a git repository"));
if (from_stdin && hash_algo)
die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin");
if (!index_name && pack_name)
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY);
if (rev_index) {
opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV;
if (index_name)
rev_index_name = derive_filename(index_name,
"idx", "rev",
&rev_index_name_buf);
}
if (verify) {
if (!index_name)
die(_("--verify with no packfile name given"));
read_idx_option(&opts, index_name);
opts.flags |= WRITE_IDX_VERIFY | WRITE_IDX_STRICT;
}
if (strict)
opts.flags |= WRITE_IDX_STRICT;
if (HAVE_THREADS && !nr_threads) {
nr_threads = online_cpus();
/*
* Experiments show that going above 20 threads doesn't help,
* no matter how many cores you have. Below that, we tend to
* max at half the number of online_cpus(), presumably because
* half of those are hyperthreads rather than full cores. We'll
* never reduce the level below "3", though, to match a
* historical value that nobody complained about.
*/
if (nr_threads < 4)
; /* too few cores to consider capping */
else if (nr_threads < 6)
nr_threads = 3; /* historic cap */
else if (nr_threads < 40)
nr_threads /= 2;
else
nr_threads = 20; /* hard cap */
}
curr_pack = open_pack_file(pack_name);
parse_pack_header();
CALLOC_ARRAY(objects, st_add(nr_objects, 1));
if (show_stat)
CALLOC_ARRAY(obj_stat, st_add(nr_objects, 1));
CALLOC_ARRAY(ofs_deltas, nr_objects);
parse_pack_objects(pack_hash);
if (report_end_of_input)
write_in_full(2, "\0", 1);
resolve_deltas();
conclude_pack(fix_thin_pack, curr_pack, pack_hash);
free(ofs_deltas);
free(ref_deltas);
if (strict)
foreign_nr = check_objects();
if (show_stat)
show_pack_info(stat_only);
ALLOC_ARRAY(idx_objects, nr_objects);
for (i = 0; i < nr_objects; i++)
idx_objects[i] = &objects[i].idx;
curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
if (rev_index)
curr_rev_index = write_rev_file(rev_index_name, idx_objects,
nr_objects, pack_hash,
opts.flags);
free(idx_objects);
if (!verify)
final(pack_name, curr_pack,
index_name, curr_index,
rev_index_name, curr_rev_index,
keep_msg, promisor_msg,
pack_hash);
else
close(input_fd);
if (do_fsck_object && fsck_finish(&fsck_options))
die(_("fsck error in pack objects"));
free(opts.anomaly);
free(objects);
strbuf_release(&index_name_buf);
strbuf_release(&rev_index_name_buf);
if (!pack_name)
free((void *) curr_pack);
if (!index_name)
free((void *) curr_index);
if (!rev_index_name)
free((void *) curr_rev_index);
/*
* Let the caller know this pack is not self contained
*/
if (check_self_contained_and_connected && foreign_nr)
return 1;
return 0;
}