diff options
Diffstat (limited to 'builtin/index-pack.c')
| -rw-r--r-- | builtin/index-pack.c | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/builtin/index-pack.c b/builtin/index-pack.c index f267dce49e..856428fef9 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1,23 +1,30 @@ #include "builtin.h" #include "config.h" #include "delta.h" +#include "environment.h" +#include "gettext.h" +#include "hex.h" #include "pack.h" #include "csum-file.h" #include "blob.h" #include "commit.h" -#include "tag.h" #include "tree.h" #include "progress.h" #include "fsck.h" -#include "exec-cmd.h" +#include "strbuf.h" #include "streaming.h" #include "thread-utils.h" #include "packfile.h" -#include "object-store.h" +#include "pack-revindex.h" +#include "object-file.h" +#include "object-store-ll.h" +#include "oid-array.h" +#include "replace-object.h" #include "promisor-remote.h" +#include "setup.h" static const char index_pack_usage[] = -"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; +"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict[=<msg-id>=<severity>...]] [--fsck-objects[=<msg-id>=<severity>...]] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; struct object_entry { struct pack_idx_entry idx; @@ -122,6 +129,7 @@ static int strict; static int do_fsck_object; static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; static int verbose; +static const char *progress_title; static int show_resolving_progress; static int show_stat; static int check_self_contained_and_connected; @@ -187,9 +195,7 @@ static void init_thread(void) pthread_key_create(&key, NULL); CALLOC_ARRAY(thread_data, nr_threads); for (i = 0; i < nr_threads; i++) { - thread_data[i].pack_fd = open(curr_pack, O_RDONLY); - if (thread_data[i].pack_fd == -1) - die_errno(_("unable to open %s"), curr_pack); + thread_data[i].pack_fd = xopen(curr_pack, O_RDONLY); } threads_active = 1; @@ -213,7 +219,8 @@ static void cleanup_thread(void) } static int mark_link(struct object *obj, enum object_type type, - void *data, struct fsck_options *options) + void *data UNUSED, + struct fsck_options *options UNUSED) { if (!obj) return -1; @@ -324,8 +331,12 @@ static void use(int bytes) if (signed_add_overflows(consumed_bytes, bytes)) die(_("pack too large for current definition of off_t")); consumed_bytes += bytes; - if (max_input_size && consumed_bytes > max_input_size) - die(_("pack exceeds maximum allowed size")); + if (max_input_size && consumed_bytes > max_input_size) { + struct strbuf size_limit = STRBUF_INIT; + strbuf_humanise_bytes(&size_limit, max_input_size); + die(_("pack exceeds maximum allowed size (%s)"), + size_limit.buf); + } } static const char *open_pack_file(const char *pack_name) @@ -450,8 +461,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size, int hdrlen; if (!is_delta_type(type)) { - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX, - type_name(type),(uintmax_t)size) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, size); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, hdr, hdrlen); } else @@ -580,7 +590,7 @@ static void *unpack_data(struct object_entry *obj, if (!n) die(Q_("premature end of pack file, %"PRIuMAX" byte missing", "premature end of pack file, %"PRIuMAX" bytes missing", - (unsigned int)len), + len), (uintmax_t)len); from += n; len -= n; @@ -799,7 +809,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (startup_info->have_repository) { read_lock(); collision_test_needed = - has_object_file_with_flags(oid, OBJECT_INFO_QUICK); + repo_has_object_file_with_flags(the_repository, oid, + OBJECT_INFO_QUICK); read_unlock(); } @@ -819,7 +830,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, die(_("cannot read existing object info %s"), oid_to_hex(oid)); if (has_type != type || has_size != size) die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid)); - has_data = read_object_file(oid, &has_type, &has_size); + has_data = repo_read_object_file(the_repository, oid, + &has_type, &has_size); read_unlock(); if (!data) data = new_data = get_data_from_pack(obj_entry); @@ -972,7 +984,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj, if (!result_data) bad_object(delta_obj->idx.offset, _("failed to apply delta")); hash_object_file(the_hash_algo, result_data, result_size, - type_name(delta_obj->real_type), &delta_obj->idx.oid); + delta_obj->real_type, &delta_obj->idx.oid); sha1_object(result_data, NULL, result_size, delta_obj->real_type, &delta_obj->idx.oid); @@ -1110,6 +1122,7 @@ static void *threaded_second_pass(void *data) list_add(&child->list, &work_head); base_cache_used += child->size; prune_base_data(NULL); + free_base_data(child); } else { /* * This child does not have its own children. It may be @@ -1132,6 +1145,7 @@ static void *threaded_second_pass(void *data) p = next_p; } + FREE_AND_NULL(child); } work_unlock(); } @@ -1150,9 +1164,11 @@ static void parse_pack_objects(unsigned char *hash) struct ofs_delta_entry *ofs_delta = ofs_deltas; struct object_id ref_delta_oid; struct stat st; + git_hash_ctx tmp_ctx; if (verbose) progress = start_progress( + progress_title ? progress_title : from_stdin ? _("Receiving objects") : _("Indexing objects"), nr_objects); for (i = 0; i < nr_objects; i++) { @@ -1185,7 +1201,9 @@ static void parse_pack_objects(unsigned char *hash) /* Check pack integrity */ flush(); - the_hash_algo->final_fn(hash, &input_ctx); + the_hash_algo->init_fn(&tmp_ctx); + the_hash_algo->clone_fn(&tmp_ctx, &input_ctx); + the_hash_algo->final_fn(hash, &tmp_ctx); if (!hasheq(fill(the_hash_algo->rawsz), hash)) die(_("pack is corrupted (SHA1 mismatch)")); use(the_hash_algo->rawsz); @@ -1237,6 +1255,7 @@ static void resolve_deltas(void) base_cache_limit = delta_base_cache_limit * nr_threads; if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) { init_thread(); + work_lock(); for (i = 0; i < nr_threads; i++) { int ret = pthread_create(&thread_data[i].thread, NULL, threaded_second_pass, thread_data + i); @@ -1244,6 +1263,7 @@ static void resolve_deltas(void) die(_("unable to create thread: %s"), strerror(ret)); } + work_unlock(); for (i = 0; i < nr_threads; i++) pthread_join(thread_data[i].thread, NULL); cleanup_thread(); @@ -1286,7 +1306,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha nr_objects - nr_objects_initial); stop_progress_msg(&progress, msg.buf); strbuf_release(&msg); - finalize_hashfile(f, tail_hash, 0); + finalize_hashfile(f, tail_hash, FSYNC_COMPONENT_PACK, 0); hashcpy(read_hash, pack_hash); fixup_pack_header_footer(output_fd, pack_hash, curr_pack, nr_objects, @@ -1383,7 +1403,7 @@ static void fix_unresolved_deltas(struct hashfile *f) sorted_by_pos[i] = &ref_deltas[i]; QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare); - if (has_promisor_remote()) { + if (repo_has_promisor_remote(the_repository)) { /* * Prefetch the delta bases. */ @@ -1409,13 +1429,13 @@ static void fix_unresolved_deltas(struct hashfile *f) if (objects[d->obj_no].real_type != OBJ_REF_DELTA) continue; - data = read_object_file(&d->oid, &type, &size); + data = repo_read_object_file(the_repository, &d->oid, &type, + &size); if (!data) continue; - if (check_object_signature(the_repository, &d->oid, - data, size, - type_name(type))) + if (check_object_signature(the_repository, &d->oid, data, size, + type) < 0) die(_("local object %s is corrupt"), oid_to_hex(&d->oid)); /* @@ -1424,6 +1444,7 @@ static void fix_unresolved_deltas(struct hashfile *f) * object). */ append_obj_to_pack(f, d->oid.hash, data, size, type); + free(data); threaded_second_pass(NULL); display_progress(progress, nr_resolved_deltas); @@ -1486,7 +1507,7 @@ static void rename_tmp_packfile(const char **final_name, if (!*final_name) *final_name = odb_pack_name(name, hash, ext); if (finalize_object_file(curr_name, *final_name)) - die(_("unable to rename temporary '*.%s' file to '%s"), + die(_("unable to rename temporary '*.%s' file to '%s'"), ext, *final_name); } else if (make_read_only_if_same) { chmod(*final_name, 0444); @@ -1503,14 +1524,12 @@ static void final(const char *final_pack_name, const char *curr_pack_name, struct strbuf pack_name = STRBUF_INIT; struct strbuf index_name = STRBUF_INIT; struct strbuf rev_index_name = STRBUF_INIT; - int err; if (!from_stdin) { close(input_fd); } else { - fsync_or_die(output_fd, curr_pack_name); - err = close(output_fd); - if (err) + fsync_component_or_die(FSYNC_COMPONENT_PACK, output_fd, curr_pack_name); + if (close(output_fd)) die_errno(_("error while closing pack file")); } @@ -1545,17 +1564,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name, write_or_die(1, buf.buf, buf.len); strbuf_release(&buf); - /* - * Let's just mimic git-unpack-objects here and write - * the last part of the input buffer to stdout. - */ - while (input_len) { - err = xwrite(1, input_buffer + input_offset, input_len); - if (err <= 0) - break; - input_len -= err; - input_offset += err; - } + /* Write the last part of the buffer to stdout */ + write_in_full(1, input_buffer + input_offset, input_len); } strbuf_release(&rev_index_name); @@ -1563,18 +1573,19 @@ static void final(const char *final_pack_name, const char *curr_pack_name, strbuf_release(&pack_name); } -static int git_index_pack_config(const char *k, const char *v, void *cb) +static int git_index_pack_config(const char *k, const char *v, + const struct config_context *ctx, void *cb) { struct pack_idx_option *opts = cb; if (!strcmp(k, "pack.indexversion")) { - opts->version = git_config_int(k, v); + opts->version = git_config_int(k, v, ctx->kvi); if (opts->version > 2) - die(_("bad pack.indexversion=%"PRIu32), opts->version); + die(_("bad pack.indexVersion=%"PRIu32), opts->version); return 0; } if (!strcmp(k, "pack.threads")) { - nr_threads = git_config_int(k, v); + nr_threads = git_config_int(k, v, ctx->kvi); if (nr_threads < 0) die(_("invalid number of threads specified (%d)"), nr_threads); @@ -1590,7 +1601,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb) else opts->flags &= ~WRITE_REV; } - return git_default_config(k, v, cb); + return git_default_config(k, v, ctx, cb); } static int cmp_uint32(const void *a_, const void *b_) @@ -1703,6 +1714,7 @@ static void show_pack_info(int stat_only) i + 1, chain_histogram[i]); } + free(chain_histogram); } int cmd_index_pack(int argc, const char **argv, const char *prefix) @@ -1733,16 +1745,17 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage(index_pack_usage); - read_replace_refs = 0; + disable_replace_refs(); fsck_options.walk = mark_link; reset_pack_idx_option(&opts); + opts.flags |= WRITE_REV; 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; + if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0)) + rev_index = 0; else rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV)); @@ -1761,8 +1774,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) } else if (!strcmp(arg, "--check-self-contained-and-connected")) { strict = 1; check_self_contained_and_connected = 1; - } else if (!strcmp(arg, "--fsck-objects")) { + } else if (skip_to_optional_arg(arg, "--fsck-objects", &arg)) { do_fsck_object = 1; + fsck_set_msg_types(&fsck_options, arg); } else if (!strcmp(arg, "--verify")) { verify = 1; } else if (!strcmp(arg, "--verify-stat")) { @@ -1800,6 +1814,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) 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")) { @@ -1841,11 +1859,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (!pack_name && !from_stdin) usage(index_pack_usage); if (fix_thin_pack && !from_stdin) - die(_("--fix-thin cannot be used without --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(_("--object-format cannot be used with --stdin")); + 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); @@ -1928,14 +1946,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) 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 == NULL) + if (!pack_name) free((void *) curr_pack); - if (index_name == NULL) + if (!index_name) free((void *) curr_index); - if (rev_index_name == NULL) + if (!rev_index_name) free((void *) curr_rev_index); /* |
