diff options
Diffstat (limited to '')
| -rw-r--r-- | builtin/bisect.c | 38 | ||||
| -rw-r--r-- | builtin/checkout.c | 6 | ||||
| -rw-r--r-- | builtin/describe.c | 18 | ||||
| -rw-r--r-- | builtin/fast-export.c | 79 | ||||
| -rw-r--r-- | builtin/fast-import.c | 284 | ||||
| -rw-r--r-- | builtin/fetch.c | 13 | ||||
| -rw-r--r-- | builtin/fsck.c | 33 | ||||
| -rw-r--r-- | builtin/gc.c | 15 | ||||
| -rw-r--r-- | builtin/last-modified.c | 250 | ||||
| -rw-r--r-- | builtin/ls-remote.c | 2 | ||||
| -rw-r--r-- | builtin/name-rev.c | 17 | ||||
| -rw-r--r-- | builtin/pack-objects.c | 65 | ||||
| -rw-r--r-- | builtin/receive-pack.c | 13 | ||||
| -rw-r--r-- | builtin/remote.c | 44 | ||||
| -rw-r--r-- | builtin/replace.c | 21 | ||||
| -rw-r--r-- | builtin/repo.c | 377 | ||||
| -rw-r--r-- | builtin/rev-parse.c | 12 | ||||
| -rw-r--r-- | builtin/show-branch.c | 35 | ||||
| -rw-r--r-- | builtin/show-ref.c | 50 | ||||
| -rw-r--r-- | builtin/submodule--helper.c | 10 | ||||
| -rw-r--r-- | builtin/tag.c | 2 | ||||
| -rw-r--r-- | builtin/verify-tag.c | 2 | ||||
| -rw-r--r-- | builtin/worktree.c | 6 |
23 files changed, 975 insertions, 417 deletions
diff --git a/builtin/bisect.c b/builtin/bisect.c index 993caf545d..4cc118fb57 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -27,13 +27,14 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN") #define BUILTIN_GIT_BISECT_START_USAGE \ - N_("git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]" \ - " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]" \ - " [<pathspec>...]") -#define BUILTIN_GIT_BISECT_STATE_USAGE \ - N_("git bisect (good|bad) [<rev>...]") + N_("git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]\n" \ + " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]") +#define BUILTIN_GIT_BISECT_BAD_USAGE \ + N_("git bisect (bad|new|<term-new>) [<rev>]") +#define BUILTIN_GIT_BISECT_GOOD_USAGE \ + N_("git bisect (good|old|<term-old>) [<rev>...]") #define BUILTIN_GIT_BISECT_TERMS_USAGE \ - "git bisect terms [--term-good | --term-bad]" + "git bisect terms [--term-(good|old) | --term-(bad|new)]" #define BUILTIN_GIT_BISECT_SKIP_USAGE \ N_("git bisect skip [(<rev>|<range>)...]") #define BUILTIN_GIT_BISECT_NEXT_USAGE \ @@ -41,17 +42,20 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN") #define BUILTIN_GIT_BISECT_RESET_USAGE \ N_("git bisect reset [<commit>]") #define BUILTIN_GIT_BISECT_VISUALIZE_USAGE \ - "git bisect visualize" + "git bisect (visualize|view)" #define BUILTIN_GIT_BISECT_REPLAY_USAGE \ N_("git bisect replay <logfile>") #define BUILTIN_GIT_BISECT_LOG_USAGE \ "git bisect log" #define BUILTIN_GIT_BISECT_RUN_USAGE \ N_("git bisect run <cmd> [<arg>...]") +#define BUILTIN_GIT_BISECT_HELP_USAGE \ + "git bisect help" static const char * const git_bisect_usage[] = { BUILTIN_GIT_BISECT_START_USAGE, - BUILTIN_GIT_BISECT_STATE_USAGE, + BUILTIN_GIT_BISECT_BAD_USAGE, + BUILTIN_GIT_BISECT_GOOD_USAGE, BUILTIN_GIT_BISECT_TERMS_USAGE, BUILTIN_GIT_BISECT_SKIP_USAGE, BUILTIN_GIT_BISECT_NEXT_USAGE, @@ -60,6 +64,7 @@ static const char * const git_bisect_usage[] = { BUILTIN_GIT_BISECT_REPLAY_USAGE, BUILTIN_GIT_BISECT_LOG_USAGE, BUILTIN_GIT_BISECT_RUN_USAGE, + BUILTIN_GIT_BISECT_HELP_USAGE, NULL }; @@ -358,10 +363,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) return 0; } -static int inc_nr(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flag UNUSED, void *cb_data) +static int inc_nr(const struct reference *ref UNUSED, void *cb_data) { unsigned int *nr = (unsigned int *)cb_data; (*nr)++; @@ -549,12 +551,11 @@ finish: return res; } -static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flags UNUSED, void *cb) +static int add_bisect_ref(const struct reference *ref, void *cb) { struct add_bisect_ref_data *data = cb; - add_pending_oid(data->revs, refname, oid, data->object_flags); + add_pending_oid(data->revs, ref->name, ref->oid, data->object_flags); return 0; } @@ -1165,12 +1166,9 @@ static int bisect_visualize(struct bisect_terms *terms, int argc, return run_command(&cmd); } -static int get_first_good(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid, - int flag UNUSED, void *cb_data) +static int get_first_good(const struct reference *ref, void *cb_data) { - oidcpy(cb_data, oid); + oidcpy(cb_data, ref->oid); return 1; } diff --git a/builtin/checkout.c b/builtin/checkout.c index f9453473fe..66b69df6e6 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1063,11 +1063,9 @@ static void update_refs_for_switch(const struct checkout_opts *opts, report_tracking(new_branch_info); } -static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED, - const struct object_id *oid, - int flags UNUSED, void *cb_data) +static int add_pending_uninteresting_ref(const struct reference *ref, void *cb_data) { - add_pending_oid(cb_data, refname, oid, UNINTERESTING); + add_pending_oid(cb_data, ref->name, ref->oid, UNINTERESTING); return 0; } diff --git a/builtin/describe.c b/builtin/describe.c index ffaf8d9f0a..443546aaac 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -154,20 +154,19 @@ static void add_to_known_names(const char *path, } } -static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int get_name(const struct reference *ref, void *cb_data UNUSED) { int is_tag = 0; struct object_id peeled; int is_annotated, prio; const char *path_to_match = NULL; - if (skip_prefix(path, "refs/tags/", &path_to_match)) { + if (skip_prefix(ref->name, "refs/tags/", &path_to_match)) { is_tag = 1; } else if (all) { if ((exclude_patterns.nr || patterns.nr) && - !skip_prefix(path, "refs/heads/", &path_to_match) && - !skip_prefix(path, "refs/remotes/", &path_to_match)) { + !skip_prefix(ref->name, "refs/heads/", &path_to_match) && + !skip_prefix(ref->name, "refs/remotes/", &path_to_match)) { /* Only accept reference of known type if there are match/exclude patterns */ return 0; } @@ -209,10 +208,10 @@ static int get_name(const char *path, const char *referent UNUSED, const struct } /* Is it annotated? */ - if (!peel_iterated_oid(the_repository, oid, &peeled)) { - is_annotated = !oideq(oid, &peeled); + if (!reference_get_peeled_oid(the_repository, ref, &peeled)) { + is_annotated = !oideq(ref->oid, &peeled); } else { - oidcpy(&peeled, oid); + oidcpy(&peeled, ref->oid); is_annotated = 0; } @@ -229,7 +228,8 @@ static int get_name(const char *path, const char *referent UNUSED, const struct else prio = 0; - add_to_known_names(all ? path + 5 : path + 10, &peeled, prio, oid); + add_to_known_names(all ? ref->name + 5 : ref->name + 10, + &peeled, prio, ref->oid); return 0; } diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 7adbc55f0d..0421360ab7 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -65,7 +65,7 @@ static int parse_opt_sign_mode(const struct option *opt, return 0; if (parse_sign_mode(arg, val)) - return error("Unknown %s mode: %s", opt->long_name, arg); + return error(_("unknown %s mode: %s"), opt->long_name, arg); return 0; } @@ -82,7 +82,7 @@ static int parse_opt_tag_of_filtered_mode(const struct option *opt, else if (!strcmp(arg, "rewrite")) *val = REWRITE; else - return error("Unknown tag-of-filtered mode: %s", arg); + return error(_("unknown tag-of-filtered mode: %s"), arg); return 0; } @@ -107,7 +107,7 @@ static int parse_opt_reencode_mode(const struct option *opt, if (!strcasecmp(arg, "abort")) *val = REENCODE_ABORT; else - return error("Unknown reencoding mode: %s", arg); + return error(_("unknown reencoding mode: %s"), arg); } return 0; @@ -318,16 +318,16 @@ static void export_blob(const struct object_id *oid) } else { buf = odb_read_object(the_repository->objects, oid, &type, &size); if (!buf) - die("could not read blob %s", oid_to_hex(oid)); + die(_("could not read blob %s"), oid_to_hex(oid)); if (check_object_signature(the_repository, oid, buf, size, type) < 0) - die("oid mismatch in blob %s", oid_to_hex(oid)); + die(_("oid mismatch in blob %s"), oid_to_hex(oid)); object = parse_object_buffer(the_repository, oid, type, size, buf, &eaten); } if (!object) - die("Could not read blob %s", oid_to_hex(oid)); + die(_("could not read blob %s"), oid_to_hex(oid)); mark_next_object(object); @@ -336,7 +336,7 @@ static void export_blob(const struct object_id *oid) printf("original-oid %s\n", oid_to_hex(oid)); printf("data %"PRIuMAX"\n", (uintmax_t)size); if (size && fwrite(buf, size, 1, stdout) != 1) - die_errno("could not write blob '%s'", oid_to_hex(oid)); + die_errno(_("could not write blob '%s'"), oid_to_hex(oid)); printf("\n"); show_progress(); @@ -499,10 +499,10 @@ static void show_filemodify(struct diff_queue_struct *q, break; default: - die("Unexpected comparison status '%c' for %s, %s", - q->queue[i]->status, - ospec->path ? ospec->path : "none", - spec->path ? spec->path : "none"); + die(_("unexpected comparison status '%c' for %s, %s"), + q->queue[i]->status, + ospec->path ? ospec->path : _("none"), + spec->path ? spec->path : _("none")); } } } @@ -699,14 +699,14 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, author = strstr(commit_buffer_cursor, "\nauthor "); if (!author) - die("could not find author in commit %s", + die(_("could not find author in commit %s"), oid_to_hex(&commit->object.oid)); author++; commit_buffer_cursor = author_end = strchrnul(author, '\n'); committer = strstr(commit_buffer_cursor, "\ncommitter "); if (!committer) - die("could not find committer in commit %s", + die(_("could not find committer in commit %s"), oid_to_hex(&commit->object.oid)); committer++; commit_buffer_cursor = committer_end = strchrnul(committer, '\n'); @@ -781,8 +781,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, case REENCODE_NO: break; case REENCODE_ABORT: - die("Encountered commit-specific encoding %.*s in commit " - "%s; use --reencode=[yes|no] to handle it", + die(_("encountered commit-specific encoding %.*s in commit " + "%s; use --reencode=[yes|no] to handle it"), (int)encoding_len, encoding, oid_to_hex(&commit->object.oid)); } @@ -798,11 +798,11 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, if (signatures.nr) { switch (signed_commit_mode) { case SIGN_ABORT: - die("encountered signed commit %s; use " - "--signed-commits=<mode> to handle it", + die(_("encountered signed commit %s; use " + "--signed-commits=<mode> to handle it"), oid_to_hex(&commit->object.oid)); case SIGN_WARN_VERBATIM: - warning("exporting %"PRIuMAX" signature(s) for commit %s", + warning(_("exporting %"PRIuMAX" signature(s) for commit %s"), (uintmax_t)signatures.nr, oid_to_hex(&commit->object.oid)); /* fallthru */ case SIGN_VERBATIM: @@ -812,7 +812,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, } break; case SIGN_WARN_STRIP: - warning("stripping signature(s) from commit %s", + warning(_("stripping signature(s) from commit %s"), oid_to_hex(&commit->object.oid)); /* fallthru */ case SIGN_STRIP: @@ -890,7 +890,8 @@ static void handle_tag(const char *name, struct tag *tag) tagged = ((struct tag *)tagged)->tagged; } if (tagged->type == OBJ_TREE) { - warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.", + warning(_("omitting tag %s,\nsince tags of trees (or tags " + "of tags of trees, etc.) are not supported."), oid_to_hex(&tag->object.oid)); return; } @@ -898,7 +899,7 @@ static void handle_tag(const char *name, struct tag *tag) buf = odb_read_object(the_repository->objects, &tag->object.oid, &type, &size); if (!buf) - die("could not read tag %s", oid_to_hex(&tag->object.oid)); + die(_("could not read tag %s"), oid_to_hex(&tag->object.oid)); message = memmem(buf, size, "\n\n", 2); if (message) { message += 2; @@ -935,17 +936,17 @@ static void handle_tag(const char *name, struct tag *tag) if (sig_offset < message_size) switch (signed_tag_mode) { case SIGN_ABORT: - die("encountered signed tag %s; use " - "--signed-tags=<mode> to handle it", + die(_("encountered signed tag %s; use " + "--signed-tags=<mode> to handle it"), oid_to_hex(&tag->object.oid)); case SIGN_WARN_VERBATIM: - warning("exporting signed tag %s", + warning(_("exporting signed tag %s"), oid_to_hex(&tag->object.oid)); /* fallthru */ case SIGN_VERBATIM: break; case SIGN_WARN_STRIP: - warning("stripping signature from tag %s", + warning(_("stripping signature from tag %s"), oid_to_hex(&tag->object.oid)); /* fallthru */ case SIGN_STRIP: @@ -960,8 +961,8 @@ static void handle_tag(const char *name, struct tag *tag) if (!tagged_mark) { switch (tag_of_filtered_mode) { case TAG_FILTERING_ABORT: - die("tag %s tags unexported object; use " - "--tag-of-filtered-object=<mode> to handle it", + die(_("tag %s tags unexported object; use " + "--tag-of-filtered-object=<mode> to handle it"), oid_to_hex(&tag->object.oid)); case DROP: /* Ignore this tag altogether */ @@ -969,7 +970,7 @@ static void handle_tag(const char *name, struct tag *tag) return; case REWRITE: if (tagged->type == OBJ_TAG && !mark_tags) { - die(_("Error: Cannot export nested tags unless --mark-tags is specified.")); + die(_("cannot export nested tags unless --mark-tags is specified.")); } else if (tagged->type == OBJ_COMMIT) { p = rewrite_commit((struct commit *)tagged); if (!p) { @@ -1025,7 +1026,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_n tag = (struct tag *)tag->tagged; } if (!tag) - die("Tag %s points nowhere?", e->name); + die(_("tag %s points nowhere?"), e->name); return (struct commit *)tag; } default: @@ -1063,7 +1064,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) commit = get_commit(e, full_name); if (!commit) { - warning("%s: Unexpected object of type %s, skipping.", + warning(_("%s: unexpected object of type %s, skipping."), e->name, type_name(e->item->type)); free(full_name); @@ -1078,7 +1079,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) free(full_name); continue; default: /* OBJ_TAG (nested tags) is already handled */ - warning("Tag points to object of unexpected type %s, skipping.", + warning(_("tag points to object of unexpected type %s, skipping."), type_name(commit->object.type)); free(full_name); continue; @@ -1174,7 +1175,7 @@ static void export_marks(char *file) f = fopen_for_writing(file); if (!f) - die_errno("Unable to open marks file %s for writing.", file); + die_errno(_("unable to open marks file %s for writing."), file); for (i = 0; i < idnums.size; i++) { if (deco->base && deco->base->type == 1) { @@ -1191,7 +1192,7 @@ static void export_marks(char *file) e |= ferror(f); e |= fclose(f); if (e) - error("Unable to write marks file %s.", file); + error(_("unable to write marks file %s."), file); } static void import_marks(char *input_file, int check_exists) @@ -1214,20 +1215,20 @@ static void import_marks(char *input_file, int check_exists) line_end = strchr(line, '\n'); if (line[0] != ':' || !line_end) - die("corrupt mark line: %s", line); + die(_("corrupt mark line: %s"), line); *line_end = '\0'; mark = strtoumax(line + 1, &mark_end, 10); if (!mark || mark_end == line + 1 || *mark_end != ' ' || get_oid_hex(mark_end + 1, &oid)) - die("corrupt mark line: %s", line); + die(_("corrupt mark line: %s"), line); if (last_idnum < mark) last_idnum = mark; type = odb_read_object_info(the_repository->objects, &oid, NULL); if (type < 0) - die("object not found: %s", oid_to_hex(&oid)); + die(_("object not found: %s"), oid_to_hex(&oid)); if (type != OBJ_COMMIT) /* only commits */ @@ -1235,12 +1236,12 @@ static void import_marks(char *input_file, int check_exists) commit = lookup_commit(the_repository, &oid); if (!commit) - die("not a commit? can't happen: %s", oid_to_hex(&oid)); + die(_("not a commit? can't happen: %s"), oid_to_hex(&oid)); object = &commit->object; if (object->flags & SHOWN) - error("Object %s already has a mark", oid_to_hex(&oid)); + error(_("object %s already has a mark"), oid_to_hex(&oid)); mark_object(object, mark); @@ -1394,7 +1395,7 @@ int cmd_fast_export(int argc, get_tags_and_duplicates(&revs.cmdline); if (prepare_revision_walk(&revs)) - die("revision walk setup failed"); + die(_("revision walk setup failed")); revs.reverse = 1; revs.diffopt.format_callback = show_filemodify; diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 54d3e592c6..4cd0b079b6 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -339,12 +339,12 @@ static void write_crash_report(const char *err) struct recent_command *rc; if (!rpt) { - error_errno("can't write crash report %s", loc); + error_errno(_("can't write crash report %s"), loc); free(loc); return; } - fprintf(stderr, "fast-import: dumping crash report to %s\n", loc); + fprintf(stderr, _("fast-import: dumping crash report to %s\n"), loc); fprintf(rpt, "fast-import crash report:\n"); fprintf(rpt, " fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid()); @@ -588,7 +588,7 @@ static void *find_mark(struct mark_set *s, uintmax_t idnum) oe = s->data.marked[idnum]; } if (!oe) - die("mark :%" PRIuMAX " not declared", orig_idnum); + die(_("mark :%" PRIuMAX " not declared"), orig_idnum); return oe; } @@ -628,9 +628,9 @@ static struct branch *new_branch(const char *name) struct branch *b = lookup_branch(name); if (b) - die("Invalid attempt to create duplicate branch: %s", name); + die(_("invalid attempt to create duplicate branch: %s"), name); if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL)) - die("Branch name doesn't conform to GIT standards: %s", name); + die(_("branch name doesn't conform to Git standards: %s"), name); b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch)); b->name = mem_pool_strdup(&fi_mem_pool, name); @@ -801,7 +801,7 @@ static const char *create_index(void) *c++ = &e->idx; last = idx + object_count; if (c != last) - die("internal consistency error creating the index"); + die(_("internal consistency error creating the index")); tmpfile = write_idx_file(the_repository, NULL, idx, object_count, &pack_idx_opts, pack_data->hash); @@ -819,18 +819,18 @@ static char *keep_pack(const char *curr_index_name) keep_fd = safe_create_file_with_leading_directories(pack_data->repo, name.buf); if (keep_fd < 0) - die_errno("cannot create keep file"); + die_errno(_("cannot create keep file")); write_or_die(keep_fd, keep_msg, strlen(keep_msg)); if (close(keep_fd)) - die_errno("failed to write keep file"); + die_errno(_("failed to write keep file")); odb_pack_name(pack_data->repo, &name, pack_data->hash, "pack"); if (finalize_object_file(pack_data->repo, pack_data->pack_name, name.buf)) - die("cannot store pack file"); + die(_("cannot store pack file")); odb_pack_name(pack_data->repo, &name, pack_data->hash, "idx"); if (finalize_object_file(pack_data->repo, curr_index_name, name.buf)) - die("cannot store index file"); + die(_("cannot store index file")); free((void *)curr_index_name); return strbuf_detach(&name, NULL); } @@ -853,7 +853,7 @@ static int loosen_small_pack(const struct packed_git *p) struct child_process unpack = CHILD_PROCESS_INIT; if (lseek(p->pack_fd, 0, SEEK_SET) < 0) - die_errno("Failed seeking to start of '%s'", p->pack_name); + die_errno(_("failed seeking to start of '%s'"), p->pack_name); unpack.in = p->pack_fd; unpack.git_cmd = 1; @@ -903,7 +903,7 @@ static void end_packfile(void) new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles, idx_name, 1); if (!new_p) - die("core git rejected index %s", idx_name); + die(_("core Git rejected index %s"), idx_name); all_packs[pack_id] = new_p; free(idx_name); @@ -979,7 +979,7 @@ static int store_object( if (e->idx.offset) { duplicate_count_by_type[type]++; return 1; - } else if (find_oid_pack(&oid, packfile_store_get_packs(packs))) { + } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) { e->type = type; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1090,7 +1090,7 @@ static int store_object( static void truncate_pack(struct hashfile_checkpoint *checkpoint) { if (hashfile_truncate(pack_file, checkpoint)) - die_errno("cannot truncate pack to skip duplicate"); + die_errno(_("cannot truncate pack to skip duplicate")); pack_size = checkpoint->offset; } @@ -1138,7 +1138,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) size_t cnt = in_sz < len ? in_sz : (size_t)len; size_t n = fread(in_buf, 1, cnt, stdin); if (!n && feof(stdin)) - die("EOF in data (%" PRIuMAX " bytes remaining)", len); + die(_("EOF in data (%" PRIuMAX " bytes remaining)"), len); git_hash_update(&c, in_buf, n); s.next_in = in_buf; @@ -1162,7 +1162,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) case Z_STREAM_END: continue; default: - die("unexpected deflate failure: %d", status); + die(_("unexpected deflate failure: %d"), status); } } git_deflate_end(&s); @@ -1180,7 +1180,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) duplicate_count_by_type[OBJ_BLOB]++; truncate_pack(&checkpoint); - } else if (find_oid_pack(&oid, packfile_store_get_packs(packs))) { + } else if (packfile_list_find_oid(packfile_store_get_packs(packs), &oid)) { e->type = OBJ_BLOB; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ @@ -1264,16 +1264,16 @@ static void load_tree(struct tree_entry *root) myoe = find_object(oid); if (myoe && myoe->pack_id != MAX_PACK_ID) { if (myoe->type != OBJ_TREE) - die("Not a tree: %s", oid_to_hex(oid)); + die(_("not a tree: %s"), oid_to_hex(oid)); t->delta_depth = myoe->depth; buf = gfi_unpack_entry(myoe, &size); if (!buf) - die("Can't load tree %s", oid_to_hex(oid)); + die(_("can't load tree %s"), oid_to_hex(oid)); } else { enum object_type type; buf = odb_read_object(the_repository->objects, oid, &type, &size); if (!buf || type != OBJ_TREE) - die("Can't load tree %s", oid_to_hex(oid)); + die(_("can't load tree %s"), oid_to_hex(oid)); } c = buf; @@ -1287,7 +1287,7 @@ static void load_tree(struct tree_entry *root) e->tree = NULL; c = parse_mode(c, &e->versions[1].mode); if (!c) - die("Corrupt mode in %s", oid_to_hex(oid)); + die(_("corrupt mode in %s"), oid_to_hex(oid)); e->versions[0].mode = e->versions[1].mode; e->name = to_atom(c, strlen(c)); c += e->name->str_len + 1; @@ -1399,7 +1399,7 @@ static void tree_content_replace( struct tree_content *newtree) { if (!S_ISDIR(mode)) - die("Root cannot be a non-directory"); + die(_("root cannot be a non-directory")); oidclr(&root->versions[0].oid, the_repository->hash_algo); oidcpy(&root->versions[1].oid, oid); if (root->tree) @@ -1422,9 +1422,9 @@ static int tree_content_set( slash1 = strchrnul(p, '/'); n = slash1 - p; if (!n) - die("Empty path component found in input"); + die(_("empty path component found in input")); if (!*slash1 && !S_ISDIR(mode) && subtree) - die("Non-directories cannot have subtrees"); + die(_("non-directories cannot have subtrees")); if (!root->tree) load_tree(root); @@ -1576,7 +1576,7 @@ static int tree_content_get( slash1 = strchrnul(p, '/'); n = slash1 - p; if (!n && !allow_root) - die("Empty path component found in input"); + die(_("empty path component found in input")); if (!root->tree) load_tree(root); @@ -1622,8 +1622,8 @@ static int update_branch(struct branch *b) !strcmp(b->name + strlen(replace_prefix), oid_to_hex(&b->oid))) { if (!quiet) - warning("Dropping %s since it would point to " - "itself (i.e. to %s)", + warning(_("dropping %s since it would point to " + "itself (i.e. to %s)"), b->name, oid_to_hex(&b->oid)); refs_delete_ref(get_main_ref_store(the_repository), NULL, b->name, NULL, 0); @@ -1646,14 +1646,14 @@ static int update_branch(struct branch *b) new_cmit = lookup_commit_reference_gently(the_repository, &b->oid, 0); if (!old_cmit || !new_cmit) - return error("Branch %s is missing commits.", b->name); + return error(_("branch %s is missing commits."), b->name); ret = repo_in_merge_bases(the_repository, old_cmit, new_cmit); if (ret < 0) exit(128); if (!ret) { - warning("Not updating %s" - " (new tip %s does not contain %s)", + warning(_("not updating %s" + " (new tip %s does not contain %s)"), b->name, oid_to_hex(&b->oid), oid_to_hex(&old_oid)); return -1; @@ -1729,13 +1729,13 @@ static void dump_marks(void) return; if (safe_create_leading_directories_const(the_repository, export_marks_file)) { - failure |= error_errno("unable to create leading directories of %s", + failure |= error_errno(_("unable to create leading directories of %s"), export_marks_file); return; } if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) { - failure |= error_errno("Unable to write marks file %s", + failure |= error_errno(_("unable to write marks file %s"), export_marks_file); return; } @@ -1744,14 +1744,14 @@ static void dump_marks(void) if (!f) { int saved_errno = errno; rollback_lock_file(&mark_lock); - failure |= error("Unable to write marks file %s: %s", + failure |= error(_("unable to write marks file %s: %s"), export_marks_file, strerror(saved_errno)); return; } for_each_mark(marks, 0, dump_marks_fn, f); if (commit_lock_file(&mark_lock)) { - failure |= error_errno("Unable to write file %s", + failure |= error_errno(_("unable to write file %s"), export_marks_file); return; } @@ -1765,7 +1765,7 @@ static void insert_object_entry(struct mark_set **s, struct object_id *oid, uint enum object_type type = odb_read_object_info(the_repository->objects, oid, NULL); if (type < 0) - die("object not found: %s", oid_to_hex(oid)); + die(_("object not found: %s"), oid_to_hex(oid)); e = insert_object(oid); e->type = type; e->pack_id = MAX_PACK_ID; @@ -1792,13 +1792,13 @@ static void read_mark_file(struct mark_set **s, FILE *f, mark_set_inserter_t ins end = strchr(line, '\n'); if (line[0] != ':' || !end) - die("corrupt mark line: %s", line); + die(_("corrupt mark line: %s"), line); *end = 0; mark = strtoumax(line + 1, &end, 10); if (!mark || end == line + 1 || *end != ' ' || get_oid_hex_any(end + 1, &oid) == GIT_HASH_UNKNOWN) - die("corrupt mark line: %s", line); + die(_("corrupt mark line: %s"), line); inserter(s, &oid, mark); } } @@ -1811,7 +1811,7 @@ static void read_marks(void) else if (import_marks_file_ignore_missing && errno == ENOENT) goto done; /* Marks file does not exist */ else - die_errno("cannot read '%s'", import_marks_file); + die_errno(_("cannot read '%s'"), import_marks_file); read_mark_file(&marks, f, insert_object_entry); fclose(f); done: @@ -1897,7 +1897,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res) strbuf_reset(sb); if (!skip_prefix(command_buf.buf, "data ", &data)) - die("Expected 'data n' command, found: %s", command_buf.buf); + die(_("expected 'data n' command, found: %s"), command_buf.buf); if (skip_prefix(data, "<<", &data)) { char *term = xstrdup(data); @@ -1905,7 +1905,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res) for (;;) { if (strbuf_getline_lf(&command_buf, stdin) == EOF) - die("EOF in data (terminator '%s' not found)", term); + die(_("EOF in data (terminator '%s' not found)"), term); if (term_len == command_buf.len && !strcmp(term, command_buf.buf)) break; @@ -1923,12 +1923,12 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res) return 0; } if (length < len) - die("data is too large to use in this context"); + die(_("data is too large to use in this context")); while (n < length) { size_t s = strbuf_fread(sb, length - n, stdin); if (!s && feof(stdin)) - die("EOF in data (%lu bytes remaining)", + die(_("EOF in data (%lu bytes remaining)"), (unsigned long)(length - n)); n += s; } @@ -1985,15 +1985,15 @@ static char *parse_ident(const char *buf) ltgt = buf + strcspn(buf, "<>"); if (*ltgt != '<') - die("Missing < in ident string: %s", buf); + die(_("missing < in ident string: %s"), buf); if (ltgt != buf && ltgt[-1] != ' ') - die("Missing space before < in ident string: %s", buf); + die(_("missing space before < in ident string: %s"), buf); ltgt = ltgt + 1 + strcspn(ltgt + 1, "<>"); if (*ltgt != '>') - die("Missing > in ident string: %s", buf); + die(_("missing > in ident string: %s"), buf); ltgt++; if (*ltgt != ' ') - die("Missing space after > in ident string: %s", buf); + die(_("missing space after > in ident string: %s"), buf); ltgt++; name_len = ltgt - buf; strbuf_add(&ident, buf, name_len); @@ -2001,19 +2001,19 @@ static char *parse_ident(const char *buf) switch (whenspec) { case WHENSPEC_RAW: if (validate_raw_date(ltgt, &ident, 1) < 0) - die("Invalid raw date \"%s\" in ident: %s", ltgt, buf); + die(_("invalid raw date \"%s\" in ident: %s"), ltgt, buf); break; case WHENSPEC_RAW_PERMISSIVE: if (validate_raw_date(ltgt, &ident, 0) < 0) - die("Invalid raw date \"%s\" in ident: %s", ltgt, buf); + die(_("invalid raw date \"%s\" in ident: %s"), ltgt, buf); break; case WHENSPEC_RFC2822: if (parse_date(ltgt, &ident) < 0) - die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf); + die(_("invalid rfc2822 date \"%s\" in ident: %s"), ltgt, buf); break; case WHENSPEC_NOW: if (strcmp("now", ltgt)) - die("Date in ident must be 'now': %s", buf); + die(_("date in ident must be 'now': %s"), buf); datestamp(&ident); break; } @@ -2107,7 +2107,7 @@ static void construct_path_with_fanout(const char *hex_sha1, { unsigned int i = 0, j = 0; if (fanout >= the_hash_algo->rawsz) - die("Too large fanout (%u)", fanout); + die(_("too large fanout (%u)"), fanout); while (fanout) { path[i++] = hex_sha1[j++]; path[i++] = hex_sha1[j++]; @@ -2181,7 +2181,7 @@ static uintmax_t do_change_note_fanout( /* Rename fullpath to realpath */ if (!tree_content_remove(orig_root, fullpath, &leaf, 0)) - die("Failed to remove path %s", fullpath); + die(_("failed to remove path %s"), fullpath); tree_content_set(orig_root, realpath, &leaf.versions[1].oid, leaf.versions[1].mode, @@ -2254,7 +2254,7 @@ static uintmax_t parse_mark_ref(const char *p, char **endptr) p++; mark = strtoumax(p, endptr, 10); if (*endptr == p) - die("No value after ':' in mark: %s", command_buf.buf); + die(_("no value after ':' in mark: %s"), command_buf.buf); return mark; } @@ -2269,7 +2269,7 @@ static uintmax_t parse_mark_ref_eol(const char *p) mark = parse_mark_ref(p, &end); if (*end != '\0') - die("Garbage after mark: %s", command_buf.buf); + die(_("garbage after mark: %s"), command_buf.buf); return mark; } @@ -2284,7 +2284,7 @@ static uintmax_t parse_mark_ref_space(const char **p) mark = parse_mark_ref(*p, &end); if (*end++ != ' ') - die("Missing space after mark: %s", command_buf.buf); + die(_("missing space after mark: %s"), command_buf.buf); *p = end; return mark; } @@ -2300,9 +2300,9 @@ static void parse_path(struct strbuf *sb, const char *p, const char **endp, { if (*p == '"') { if (unquote_c_style(sb, p, endp)) - die("Invalid %s: %s", field, command_buf.buf); + die(_("invalid %s: %s"), field, command_buf.buf); if (strlen(sb->buf) != sb->len) - die("NUL in %s: %s", field, command_buf.buf); + die(_("NUL in %s: %s"), field, command_buf.buf); } else { /* * Unless we are parsing the last field of a line, @@ -2325,7 +2325,7 @@ static void parse_path_eol(struct strbuf *sb, const char *p, const char *field) parse_path(sb, p, &end, 1, field); if (*end) - die("Garbage after %s: %s", field, command_buf.buf); + die(_("garbage after %s: %s"), field, command_buf.buf); } /* @@ -2338,7 +2338,7 @@ static void parse_path_space(struct strbuf *sb, const char *p, { parse_path(sb, p, endp, 0, field); if (**endp != ' ') - die("Missing space after %s: %s", field, command_buf.buf); + die(_("missing space after %s: %s"), field, command_buf.buf); (*endp)++; } @@ -2351,7 +2351,7 @@ static void file_change_m(const char *p, struct branch *b) p = parse_mode(p, &mode); if (!p) - die("Corrupt mode: %s", command_buf.buf); + die(_("corrupt mode: %s"), command_buf.buf); switch (mode) { case 0644: case 0755: @@ -2364,7 +2364,7 @@ static void file_change_m(const char *p, struct branch *b) /* ok */ break; default: - die("Corrupt mode: %s", command_buf.buf); + die(_("corrupt mode: %s"), command_buf.buf); } if (*p == ':') { @@ -2375,10 +2375,10 @@ static void file_change_m(const char *p, struct branch *b) oe = NULL; /* not used with inline_data, but makes gcc happy */ } else { if (parse_mapped_oid_hex(p, &oid, &p)) - die("Invalid dataref: %s", command_buf.buf); + die(_("invalid dataref: %s"), command_buf.buf); oe = find_object(&oid); if (*p++ != ' ') - die("Missing space after SHA1: %s", command_buf.buf); + die(_("missing space after SHA1: %s"), command_buf.buf); } strbuf_reset(&path); @@ -2394,11 +2394,11 @@ static void file_change_m(const char *p, struct branch *b) if (S_ISGITLINK(mode)) { if (inline_data) - die("Git links cannot be specified 'inline': %s", + die(_("Git links cannot be specified 'inline': %s"), command_buf.buf); else if (oe) { if (oe->type != OBJ_COMMIT) - die("Not a commit (actually a %s): %s", + die(_("not a commit (actually a %s): %s"), type_name(oe->type), command_buf.buf); } /* @@ -2407,7 +2407,7 @@ static void file_change_m(const char *p, struct branch *b) */ } else if (inline_data) { if (S_ISDIR(mode)) - die("Directories cannot be specified 'inline': %s", + die(_("directories cannot be specified 'inline': %s"), command_buf.buf); while (read_next_command() != EOF) { const char *v; @@ -2425,11 +2425,11 @@ static void file_change_m(const char *p, struct branch *b) odb_read_object_info(the_repository->objects, &oid, NULL); if (type < 0) - die("%s not found: %s", - S_ISDIR(mode) ? "Tree" : "Blob", - command_buf.buf); + die(_("%s not found: %s"), + S_ISDIR(mode) ? _("tree") : _("blob"), + command_buf.buf); if (type != expected) - die("Not a %s (actually a %s): %s", + die(_("not a %s (actually a %s): %s"), type_name(expected), type_name(type), command_buf.buf); } @@ -2440,7 +2440,7 @@ static void file_change_m(const char *p, struct branch *b) } if (!verify_path(path.buf, mode)) - die("invalid path '%s'", path.buf); + die(_("invalid path '%s'"), path.buf); tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL); } @@ -2470,7 +2470,7 @@ static void file_change_cr(const char *p, struct branch *b, int rename) else tree_content_get(&b->branch_tree, source.buf, &leaf, 1); if (!leaf.versions[1].mode) - die("Path %s not in branch", source.buf); + die(_("path %s not in branch"), source.buf); if (!*dest.buf) { /* C "path/to/subdir" "" */ tree_content_replace(&b->branch_tree, &leaf.versions[1].oid, @@ -2479,7 +2479,7 @@ static void file_change_cr(const char *p, struct branch *b, int rename) return; } if (!verify_path(dest.buf, leaf.versions[1].mode)) - die("invalid path '%s'", dest.buf); + die(_("invalid path '%s'"), dest.buf); tree_content_set(&b->branch_tree, dest.buf, &leaf.versions[1].oid, leaf.versions[1].mode, @@ -2521,23 +2521,23 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa oe = NULL; /* not used with inline_data, but makes gcc happy */ } else { if (parse_mapped_oid_hex(p, &oid, &p)) - die("Invalid dataref: %s", command_buf.buf); + die(_("invalid dataref: %s"), command_buf.buf); oe = find_object(&oid); if (*p++ != ' ') - die("Missing space after SHA1: %s", command_buf.buf); + die(_("missing space after SHA1: %s"), command_buf.buf); } /* <commit-ish> */ s = lookup_branch(p); if (s) { if (is_null_oid(&s->oid)) - die("Can't add a note on empty branch."); + die(_("can't add a note on empty branch.")); oidcpy(&commit_oid, &s->oid); } else if (*p == ':') { uintmax_t commit_mark = parse_mark_ref_eol(p); struct object_entry *commit_oe = find_mark(marks, commit_mark); if (commit_oe->type != OBJ_COMMIT) - die("Mark :%" PRIuMAX " not a commit", commit_mark); + die(_("mark :%" PRIuMAX " not a commit"), commit_mark); oidcpy(&commit_oid, &commit_oe->idx.oid); } else if (!repo_get_oid(the_repository, p, &commit_oid)) { unsigned long size; @@ -2545,25 +2545,25 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa &commit_oid, OBJ_COMMIT, &size, &commit_oid); if (!buf || size < the_hash_algo->hexsz + 6) - die("Not a valid commit: %s", p); + die(_("not a valid commit: %s"), p); free(buf); } else - die("Invalid ref name or SHA1 expression: %s", p); + die(_("invalid ref name or SHA1 expression: %s"), p); if (inline_data) { read_next_command(); parse_and_store_blob(&last_blob, &oid, 0); } else if (oe) { if (oe->type != OBJ_BLOB) - die("Not a blob (actually a %s): %s", + die(_("not a blob (actually a %s): %s"), type_name(oe->type), command_buf.buf); } else if (!is_null_oid(&oid)) { enum object_type type = odb_read_object_info(the_repository->objects, &oid, NULL); if (type < 0) - die("Blob not found: %s", command_buf.buf); + die(_("blob not found: %s"), command_buf.buf); if (type != OBJ_BLOB) - die("Not a blob (actually a %s): %s", + die(_("not a blob (actually a %s): %s"), type_name(type), command_buf.buf); } @@ -2592,10 +2592,10 @@ static void file_change_deleteall(struct branch *b) static void parse_from_commit(struct branch *b, char *buf, unsigned long size) { if (!buf || size < the_hash_algo->hexsz + 6) - die("Not a valid commit: %s", oid_to_hex(&b->oid)); + die(_("not a valid commit: %s"), oid_to_hex(&b->oid)); if (memcmp("tree ", buf, 5) || get_oid_hex(buf + 5, &b->branch_tree.versions[1].oid)) - die("The commit %s is corrupt", oid_to_hex(&b->oid)); + die(_("the commit %s is corrupt"), oid_to_hex(&b->oid)); oidcpy(&b->branch_tree.versions[0].oid, &b->branch_tree.versions[1].oid); } @@ -2625,7 +2625,7 @@ static int parse_objectish(struct branch *b, const char *objectish) s = lookup_branch(objectish); if (b == s) - die("Can't create a branch from itself: %s", b->name); + die(_("can't create a branch from itself: %s"), b->name); else if (s) { struct object_id *t = &s->branch_tree.versions[1].oid; oidcpy(&b->oid, &s->oid); @@ -2635,7 +2635,7 @@ static int parse_objectish(struct branch *b, const char *objectish) uintmax_t idnum = parse_mark_ref_eol(objectish); struct object_entry *oe = find_mark(marks, idnum); if (oe->type != OBJ_COMMIT) - die("Mark :%" PRIuMAX " not a commit", idnum); + die(_("mark :%" PRIuMAX " not a commit"), idnum); if (!oideq(&b->oid, &oe->idx.oid)) { oidcpy(&b->oid, &oe->idx.oid); if (oe->pack_id != MAX_PACK_ID) { @@ -2652,7 +2652,7 @@ static int parse_objectish(struct branch *b, const char *objectish) b->delete = 1; } else - die("Invalid ref name or SHA1 expression: %s", objectish); + die(_("invalid ref name or SHA1 expression: %s"), objectish); if (b->branch_tree.tree && !oideq(&oid, &b->branch_tree.versions[1].oid)) { release_tree_content_recursive(b->branch_tree.tree); @@ -2699,7 +2699,7 @@ static struct hash_list *parse_merge(unsigned int *count) uintmax_t idnum = parse_mark_ref_eol(from); struct object_entry *oe = find_mark(marks, idnum); if (oe->type != OBJ_COMMIT) - die("Mark :%" PRIuMAX " not a commit", idnum); + die(_("mark :%" PRIuMAX " not a commit"), idnum); oidcpy(&n->oid, &oe->idx.oid); } else if (!repo_get_oid(the_repository, from, &n->oid)) { unsigned long size; @@ -2707,10 +2707,10 @@ static struct hash_list *parse_merge(unsigned int *count) &n->oid, OBJ_COMMIT, &size, &n->oid); if (!buf || size < the_hash_algo->hexsz + 6) - die("Not a valid commit: %s", from); + die(_("not a valid commit: %s"), from); free(buf); } else - die("Invalid ref name or SHA1 expression: %s", from); + die(_("invalid ref name or SHA1 expression: %s"), from); n->next = NULL; *tail = n; @@ -2734,8 +2734,8 @@ static void parse_one_signature(struct signature_data *sig, const char *v) char *space = strchr(args, ' '); if (!space) - die("Expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', " - "got 'gpgsig %s'", args); + die(_("expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', " + "got 'gpgsig %s'"), args); *space = '\0'; sig->hash_algo = args; @@ -2744,13 +2744,13 @@ static void parse_one_signature(struct signature_data *sig, const char *v) /* Validate hash algorithm */ if (strcmp(sig->hash_algo, "sha1") && strcmp(sig->hash_algo, "sha256")) - die("Unknown git hash algorithm in gpgsig: '%s'", sig->hash_algo); + die(_("unknown git hash algorithm in gpgsig: '%s'"), sig->hash_algo); /* Validate signature format */ if (!valid_signature_format(sig->sig_format)) - die("Invalid signature format in gpgsig: '%s'", sig->sig_format); + die(_("invalid signature format in gpgsig: '%s'"), sig->sig_format); if (!strcmp(sig->sig_format, "unknown")) - warning("'unknown' signature format in gpgsig"); + warning(_("'unknown' signature format in gpgsig")); /* Read signature data */ read_next_command(); @@ -2789,8 +2789,8 @@ static void store_signature(struct signature_data *stored_sig, const char *hash_type) { if (stored_sig->hash_algo) { - warning("multiple %s signatures found, " - "ignoring additional signature", + warning(_("multiple %s signatures found, " + "ignoring additional signature"), hash_type); strbuf_release(&new_sig->data); free(new_sig->hash_algo); @@ -2845,15 +2845,15 @@ static void parse_new_commit(const char *arg) read_next_command(); } if (!committer) - die("Expected committer but didn't get one"); + die(_("expected committer but didn't get one")); while (skip_prefix(command_buf.buf, "gpgsig ", &v)) { switch (signed_commit_mode) { /* First, modes that don't need the signature to be parsed */ case SIGN_ABORT: - die("encountered signed commit; use " - "--signed-commits=<mode> to handle it"); + die(_("encountered signed commit; use " + "--signed-commits=<mode> to handle it")); case SIGN_WARN_STRIP: warning(_("stripping a commit signature")); /* fallthru */ @@ -3025,11 +3025,11 @@ static void parse_new_tag(const char *arg) /* from ... */ if (!skip_prefix(command_buf.buf, "from ", &from)) - die("Expected from command, got %s", command_buf.buf); + die(_("expected 'from' command, got '%s'"), command_buf.buf); s = lookup_branch(from); if (s) { if (is_null_oid(&s->oid)) - die("Can't tag an empty branch."); + die(_("can't tag an empty branch.")); oidcpy(&oid, &s->oid); type = OBJ_COMMIT; } else if (*from == ':') { @@ -3044,11 +3044,11 @@ static void parse_new_tag(const char *arg) type = odb_read_object_info(the_repository->objects, &oid, NULL); if (type < 0) - die("Not a valid object: %s", from); + die(_("not a valid object: %s"), from); } else type = oe->type; } else - die("Invalid ref name or SHA1 expression: %s", from); + die(_("invalid ref name or SHA1 expression: %s"), from); read_next_command(); /* original-oid ... */ @@ -3139,7 +3139,7 @@ static void parse_reset_branch(const char *arg) static void cat_blob_write(const char *buf, unsigned long size) { if (write_in_full(cat_blob_fd, buf, size) < 0) - die_errno("Write to frontend failed"); + die_errno(_("write to frontend failed")); } static void cat_blob(struct object_entry *oe, struct object_id *oid) @@ -3168,9 +3168,9 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid) return; } if (!buf) - die("Can't read object %s", oid_to_hex(oid)); + die(_("can't read object %s"), oid_to_hex(oid)); if (type != OBJ_BLOB) - die("Object %s is a %s but a blob was expected.", + die(_("object %s is a %s but a blob was expected."), oid_to_hex(oid), type_name(type)); strbuf_reset(&line); strbuf_addf(&line, "%s %s %"PRIuMAX"\n", oid_to_hex(oid), @@ -3194,11 +3194,11 @@ static void parse_get_mark(const char *p) /* get-mark SP <object> LF */ if (*p != ':') - die("Not a mark: %s", p); + die(_("not a mark: %s"), p); oe = find_mark(marks, parse_mark_ref_eol(p)); if (!oe) - die("Unknown mark: %s", command_buf.buf); + die(_("unknown mark: %s"), command_buf.buf); xsnprintf(output, sizeof(output), "%s\n", oid_to_hex(&oe->idx.oid)); cat_blob_write(output, the_hash_algo->hexsz + 1); @@ -3213,13 +3213,13 @@ static void parse_cat_blob(const char *p) if (*p == ':') { oe = find_mark(marks, parse_mark_ref_eol(p)); if (!oe) - die("Unknown mark: %s", command_buf.buf); + die(_("unknown mark: %s"), command_buf.buf); oidcpy(&oid, &oe->idx.oid); } else { if (parse_mapped_oid_hex(p, &oid, &p)) - die("Invalid dataref: %s", command_buf.buf); + die(_("invalid dataref: %s"), command_buf.buf); if (*p) - die("Garbage after SHA1: %s", command_buf.buf); + die(_("garbage after SHA1: %s"), command_buf.buf); oe = find_object(&oid); } @@ -3237,7 +3237,7 @@ static struct object_entry *dereference(struct object_entry *oe, enum object_type type = odb_read_object_info(the_repository->objects, oid, NULL); if (type < 0) - die("object not found: %s", oid_to_hex(oid)); + die(_("object not found: %s"), oid_to_hex(oid)); /* cache it! */ oe = insert_object(oid); oe->type = type; @@ -3251,7 +3251,7 @@ static struct object_entry *dereference(struct object_entry *oe, case OBJ_TAG: break; default: - die("Not a tree-ish: %s", command_buf.buf); + die(_("not a tree-ish: %s"), command_buf.buf); } if (oe->pack_id != MAX_PACK_ID) { /* in a pack being written */ @@ -3262,19 +3262,19 @@ static struct object_entry *dereference(struct object_entry *oe, &unused, &size); } if (!buf) - die("Can't load object %s", oid_to_hex(oid)); + die(_("can't load object %s"), oid_to_hex(oid)); /* Peel one layer. */ switch (oe->type) { case OBJ_TAG: if (size < hexsz + strlen("object ") || get_oid_hex(buf + strlen("object "), oid)) - die("Invalid SHA1 in tag: %s", command_buf.buf); + die(_("invalid SHA1 in tag: %s"), command_buf.buf); break; case OBJ_COMMIT: if (size < hexsz + strlen("tree ") || get_oid_hex(buf + strlen("tree "), oid)) - die("Invalid SHA1 in commit: %s", command_buf.buf); + die(_("invalid SHA1 in commit: %s"), command_buf.buf); } free(buf); @@ -3309,9 +3309,9 @@ static void build_mark_map(struct string_list *from, struct string_list *to) for_each_string_list_item(fromp, from) { top = string_list_lookup(to, fromp->string); if (!fromp->util) { - die(_("Missing from marks for submodule '%s'"), fromp->string); + die(_("missing from marks for submodule '%s'"), fromp->string); } else if (!top || !top->util) { - die(_("Missing to marks for submodule '%s'"), fromp->string); + die(_("missing to marks for submodule '%s'"), fromp->string); } build_mark_map_one(fromp->util, top->util); } @@ -3325,14 +3325,14 @@ static struct object_entry *parse_treeish_dataref(const char **p) if (**p == ':') { /* <mark> */ e = find_mark(marks, parse_mark_ref_space(p)); if (!e) - die("Unknown mark: %s", command_buf.buf); + die(_("unknown mark: %s"), command_buf.buf); oidcpy(&oid, &e->idx.oid); } else { /* <sha1> */ if (parse_mapped_oid_hex(*p, &oid, p)) - die("Invalid dataref: %s", command_buf.buf); + die(_("invalid dataref: %s"), command_buf.buf); e = find_object(&oid); if (*(*p)++ != ' ') - die("Missing space after tree-ish: %s", command_buf.buf); + die(_("missing space after tree-ish: %s"), command_buf.buf); } while (!e || e->type != OBJ_TREE) @@ -3376,7 +3376,7 @@ static void parse_ls(const char *p, struct branch *b) /* ls SP (<tree-ish> SP)? <path> */ if (*p == '"') { if (!b) - die("Not in a commit: %s", command_buf.buf); + die(_("not in a commit: %s"), command_buf.buf); root = &b->branch_tree; } else { struct object_entry *e = parse_treeish_dataref(&p); @@ -3439,12 +3439,12 @@ static void parse_alias(void) /* mark ... */ parse_mark(); if (!next_mark) - die(_("Expected 'mark' command, got %s"), command_buf.buf); + die(_("expected 'mark' command, got %s"), command_buf.buf); /* to ... */ memset(&b, 0, sizeof(b)); if (!parse_objectish_with_prefix(&b, "to ")) - die(_("Expected 'to' command, got %s"), command_buf.buf); + die(_("expected 'to' command, got %s"), command_buf.buf); e = find_object(&b.oid); assert(e); insert_mark(&marks, next_mark, e); @@ -3462,7 +3462,7 @@ static void option_import_marks(const char *marks, { if (import_marks_file) { if (from_stream) - die("Only one import-marks command allowed per stream"); + die(_("only one import-marks command allowed per stream")); /* read previous mark file */ if(!import_marks_file_from_stream) @@ -3486,7 +3486,7 @@ static void option_date_format(const char *fmt) else if (!strcmp(fmt, "now")) whenspec = WHENSPEC_NOW; else - die("unknown --date-format argument %s", fmt); + die(_("unknown --date-format argument %s"), fmt); } static unsigned long ulong_arg(const char *option, const char *arg) @@ -3494,7 +3494,7 @@ static unsigned long ulong_arg(const char *option, const char *arg) char *endptr; unsigned long rv = strtoul(arg, &endptr, 0); if (strchr(arg, '-') || endptr == arg || *endptr) - die("%s: argument must be a non-negative integer", option); + die(_("%s: argument must be a non-negative integer"), option); return rv; } @@ -3502,7 +3502,7 @@ static void option_depth(const char *depth) { max_depth = ulong_arg("--depth", depth); if (max_depth > MAX_DEPTH) - die("--depth cannot exceed %u", MAX_DEPTH); + die(_("--depth cannot exceed %u"), MAX_DEPTH); } static void option_active_branches(const char *branches) @@ -3520,7 +3520,7 @@ static void option_cat_blob_fd(const char *fd) { unsigned long n = ulong_arg("--cat-blob-fd", fd); if (n > (unsigned long) INT_MAX) - die("--cat-blob-fd cannot exceed %d", INT_MAX); + die(_("--cat-blob-fd cannot exceed %d"), INT_MAX); cat_blob_fd = (int) n; } @@ -3540,7 +3540,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list) char *s = xstrdup(arg); char *f = strchr(s, ':'); if (!f) - die(_("Expected format name:filename for submodule rewrite option")); + die(_("expected format name:filename for submodule rewrite option")); *f = '\0'; f++; CALLOC_ARRAY(ms, 1); @@ -3548,7 +3548,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list) f = prefix_filename(global_prefix, f); fp = fopen(f, "r"); if (!fp) - die_errno("cannot read '%s'", f); + die_errno(_("cannot read '%s'"), f); read_mark_file(&ms, fp, insert_oid_entry); fclose(fp); free(f); @@ -3565,10 +3565,10 @@ static int parse_one_option(const char *option) if (!git_parse_ulong(option, &v)) return 0; if (v < 8192) { - warning("max-pack-size is now in bytes, assuming --max-pack-size=%lum", v); + warning(_("max-pack-size is now in bytes, assuming --max-pack-size=%lum"), v); v *= 1024 * 1024; } else if (v < 1024 * 1024) { - warning("minimum max-pack-size is 1 MiB"); + warning(_("minimum max-pack-size is 1 MiB")); v = 1024 * 1024; } max_packsize = v; @@ -3655,23 +3655,23 @@ static int parse_one_feature(const char *feature, int from_stream) static void parse_feature(const char *feature) { if (seen_data_command) - die("Got feature command '%s' after data command", feature); + die(_("got feature command '%s' after data command"), feature); if (parse_one_feature(feature, 1)) return; - die("This version of fast-import does not support feature %s.", feature); + die(_("this version of fast-import does not support feature %s."), feature); } static void parse_option(const char *option) { if (seen_data_command) - die("Got option command '%s' after data command", option); + die(_("got option command '%s' after data command"), option); if (parse_one_option(option)) return; - die("This version of fast-import does not support option: %s", option); + die(_("this version of fast-import does not support option: %s"), option); } static void git_pack_config(void) @@ -3715,7 +3715,7 @@ static void parse_argv(void) break; if (!skip_prefix(a, "--", &a)) - die("unknown option %s", a); + die(_("unknown option %s"), a); if (parse_one_option(a)) continue; @@ -3728,7 +3728,7 @@ static void parse_argv(void) continue; } - die("unknown option --%s", a); + die(_("unknown option --%s"), a); } if (i != global_argc) usage(fast_import_usage); @@ -3817,7 +3817,7 @@ int cmd_fast_import(int argc, else if (starts_with(command_buf.buf, "option ")) /* ignore non-git options*/; else - die("Unsupported command: %s", command_buf.buf); + die(_("unsupported command: %s"), command_buf.buf); if (checkpoint_requested) checkpoint(); @@ -3828,7 +3828,7 @@ int cmd_fast_import(int argc, parse_argv(); if (require_explicit_termination && feof(stdin)) - die("stream ends early"); + die(_("stream ends early")); end_packfile(); diff --git a/builtin/fetch.c b/builtin/fetch.c index c7ff3480fb..7052e6ff21 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -289,13 +289,11 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map, return ent; } -static int add_one_refname(const char *refname, const char *referent UNUSED, - const struct object_id *oid, - int flag UNUSED, void *cbdata) +static int add_one_refname(const struct reference *ref, void *cbdata) { struct hashmap *refname_map = cbdata; - (void) refname_hash_add(refname_map, refname, oid); + (void) refname_hash_add(refname_map, ref->name, ref->oid); return 0; } @@ -1416,14 +1414,11 @@ static void set_option(struct transport *transport, const char *name, const char } -static int add_oid(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid, - int flags UNUSED, void *cb_data) +static int add_oid(const struct reference *ref, void *cb_data) { struct oid_array *oids = cb_data; - oid_array_append(oids, oid); + oid_array_append(oids, ref->oid); return 0; } diff --git a/builtin/fsck.c b/builtin/fsck.c index b1a650c673..c489582faa 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -530,14 +530,13 @@ static int fsck_handle_reflog(const char *logname, void *cb_data) return 0; } -static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED) { struct object *obj; - obj = parse_object(the_repository, oid); + obj = parse_object(the_repository, ref->oid); if (!obj) { - if (is_promisor_object(the_repository, oid)) { + if (is_promisor_object(the_repository, ref->oid)) { /* * Increment default_refs anyway, because this is a * valid ref. @@ -546,19 +545,19 @@ static int fsck_handle_ref(const char *refname, const char *referent UNUSED, con return 0; } error(_("%s: invalid sha1 pointer %s"), - refname, oid_to_hex(oid)); + ref->name, oid_to_hex(ref->oid)); errors_found |= ERROR_REACHABLE; /* We'll continue with the rest despite the error.. */ return 0; } - if (obj->type != OBJ_COMMIT && is_branch(refname)) { - error(_("%s: not a commit"), refname); + if (obj->type != OBJ_COMMIT && is_branch(ref->name)) { + error(_("%s: not a commit"), ref->name); errors_found |= ERROR_REFS; } default_refs++; obj->flags |= USED; fsck_put_object_name(&fsck_walk_options, - oid, "%s", refname); + ref->oid, "%s", ref->name); mark_object_reachable(obj); return 0; @@ -580,13 +579,19 @@ static void get_default_heads(void) worktrees = get_worktrees(); for (p = worktrees; *p; p++) { struct worktree *wt = *p; - struct strbuf ref = STRBUF_INIT; + struct strbuf refname = STRBUF_INIT; - strbuf_worktree_ref(wt, &ref, "HEAD"); - fsck_head_link(ref.buf, &head_points_at, &head_oid); - if (head_points_at && !is_null_oid(&head_oid)) - fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL); - strbuf_release(&ref); + strbuf_worktree_ref(wt, &refname, "HEAD"); + fsck_head_link(refname.buf, &head_points_at, &head_oid); + if (head_points_at && !is_null_oid(&head_oid)) { + struct reference ref = { + .name = refname.buf, + .oid = &head_oid, + }; + + fsck_handle_ref(&ref, NULL); + } + strbuf_release(&refname); if (include_reflogs) refs_for_each_reflog(get_worktree_ref_store(wt), diff --git a/builtin/gc.c b/builtin/gc.c index d212cbb9b8..aad1496f07 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1103,24 +1103,21 @@ struct cg_auto_data { int limit; }; -static int dfs_on_ref(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid, - int flags UNUSED, - void *cb_data) +static int dfs_on_ref(const struct reference *ref, void *cb_data) { struct cg_auto_data *data = (struct cg_auto_data *)cb_data; int result = 0; + const struct object_id *maybe_peeled = ref->oid; struct object_id peeled; struct commit_list *stack = NULL; struct commit *commit; - if (!peel_iterated_oid(the_repository, oid, &peeled)) - oid = &peeled; - if (odb_read_object_info(the_repository->objects, oid, NULL) != OBJ_COMMIT) + if (!reference_get_peeled_oid(the_repository, ref, &peeled)) + maybe_peeled = &peeled; + if (odb_read_object_info(the_repository->objects, maybe_peeled, NULL) != OBJ_COMMIT) return 0; - commit = lookup_commit(the_repository, oid); + commit = lookup_commit(the_repository, maybe_peeled); if (!commit) return 0; if (repo_parse_commit(the_repository, commit) || diff --git a/builtin/last-modified.c b/builtin/last-modified.c index ae8b36a2c3..b0ecbdc540 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -2,26 +2,32 @@ #include "bloom.h" #include "builtin.h" #include "commit-graph.h" +#include "commit-slab.h" #include "commit.h" #include "config.h" -#include "environment.h" #include "diff.h" #include "diffcore.h" #include "environment.h" +#include "ewah/ewok.h" #include "hashmap.h" #include "hex.h" -#include "log-tree.h" #include "object-name.h" #include "object.h" #include "parse-options.h" +#include "prio-queue.h" #include "quote.h" #include "repository.h" #include "revision.h" +/* Remember to update object flag allocation in object.h */ +#define PARENT1 (1u<<16) /* used instead of SEEN */ +#define PARENT2 (1u<<17) /* used instead of BOTTOM, BOUNDARY */ + struct last_modified_entry { struct hashmap_entry hashent; struct object_id oid; struct bloom_key key; + size_t diff_idx; const char path[FLEX_ARRAY]; }; @@ -37,13 +43,45 @@ static int last_modified_entry_hashcmp(const void *unused UNUSED, return strcmp(ent1->path, path ? path : ent2->path); } +/* + * Hold a bitmap for each commit we're working with. In the bitmap, each bit + * represents a path in `lm->all_paths`. An active bit indicates the path still + * needs to be associated to a commit. + */ +define_commit_slab(active_paths_for_commit, struct bitmap *); + struct last_modified { struct hashmap paths; struct rev_info rev; bool recursive; bool show_trees; + + const char **all_paths; + size_t all_paths_nr; + struct active_paths_for_commit active_paths; + + /* 'scratch' to avoid allocating a bitmap every process_parent() */ + struct bitmap *scratch; }; +static struct bitmap *active_paths_for(struct last_modified *lm, struct commit *c) +{ + struct bitmap **bitmap = active_paths_for_commit_at(&lm->active_paths, c); + if (!*bitmap) + *bitmap = bitmap_word_alloc(lm->all_paths_nr / BITS_IN_EWORD + 1); + + return *bitmap; +} + +static void active_paths_free(struct last_modified *lm, struct commit *c) +{ + struct bitmap **bitmap = active_paths_for_commit_at(&lm->active_paths, c); + if (*bitmap) { + bitmap_free(*bitmap); + *bitmap = NULL; + } +} + static void last_modified_release(struct last_modified *lm) { struct hashmap_iter iter; @@ -54,6 +92,8 @@ static void last_modified_release(struct last_modified *lm) hashmap_clear_and_free(&lm->paths, struct last_modified_entry, hashent); release_revisions(&lm->rev); + + free(lm->all_paths); } struct last_modified_callback_data { @@ -146,7 +186,7 @@ static void mark_path(const char *path, const struct object_id *oid, * Is it arriving at a version of interest, or is it from a side branch * which did not contribute to the final state? */ - if (!oideq(oid, &ent->oid)) + if (oid && !oideq(oid, &ent->oid)) return; last_modified_emit(data->lm, path, data->commit); @@ -196,7 +236,17 @@ static void last_modified_diff(struct diff_queue_struct *q, } } -static bool maybe_changed_path(struct last_modified *lm, struct commit *origin) +static void pass_to_parent(struct bitmap *c, + struct bitmap *p, + size_t pos) +{ + bitmap_unset(c, pos); + bitmap_set(p, pos); +} + +static bool maybe_changed_path(struct last_modified *lm, + struct commit *origin, + struct bitmap *active) { struct bloom_filter *filter; struct last_modified_entry *ent; @@ -213,6 +263,9 @@ static bool maybe_changed_path(struct last_modified *lm, struct commit *origin) return true; hashmap_for_each_entry(&lm->paths, &iter, ent, hashent) { + if (active && !bitmap_get(active, ent->diff_idx)) + continue; + if (bloom_filter_contains(filter, &ent->key, lm->rev.bloom_filter_settings)) return true; @@ -220,42 +273,202 @@ static bool maybe_changed_path(struct last_modified *lm, struct commit *origin) return false; } +static void process_parent(struct last_modified *lm, + struct prio_queue *queue, + struct commit *c, struct bitmap *active_c, + struct commit *parent, int parent_i) +{ + struct bitmap *active_p; + + repo_parse_commit(lm->rev.repo, parent); + active_p = active_paths_for(lm, parent); + + /* + * The first time entering this function for this commit (i.e. first parent) + * see if Bloom filters will tell us it's worth to do the diff. + */ + if (parent_i || maybe_changed_path(lm, c, active_c)) { + diff_tree_oid(&parent->object.oid, + &c->object.oid, "", &lm->rev.diffopt); + diffcore_std(&lm->rev.diffopt); + } + + /* + * Test each path for TREESAME-ness against the parent. If a path is + * TREESAME, pass it on to this parent. + * + * First, collect all paths that are *not* TREESAME in 'scratch'. + * Then, pass paths that *are* TREESAME and active to the parent. + */ + for (int i = 0; i < diff_queued_diff.nr; i++) { + struct diff_filepair *fp = diff_queued_diff.queue[i]; + const char *path = fp->two->path; + struct last_modified_entry *ent = + hashmap_get_entry_from_hash(&lm->paths, strhash(path), path, + struct last_modified_entry, hashent); + if (ent) { + size_t k = ent->diff_idx; + if (bitmap_get(active_c, k)) + bitmap_set(lm->scratch, k); + } + } + for (size_t i = 0; i < lm->all_paths_nr; i++) { + if (bitmap_get(active_c, i) && !bitmap_get(lm->scratch, i)) + pass_to_parent(active_c, active_p, i); + } + + /* + * If parent has any active paths, put it on the queue (if not already). + */ + if (!bitmap_is_empty(active_p) && !(parent->object.flags & PARENT1)) { + parent->object.flags |= PARENT1; + prio_queue_put(queue, parent); + } + if (!(parent->object.flags & PARENT1)) + active_paths_free(lm, parent); + + memset(lm->scratch->words, 0x0, lm->scratch->word_alloc); + diff_queue_clear(&diff_queued_diff); +} + static int last_modified_run(struct last_modified *lm) { + int max_count, queue_popped = 0; + struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; + struct prio_queue not_queue = { compare_commits_by_gen_then_commit_date }; + struct commit_list *list; struct last_modified_callback_data data = { .lm = lm }; lm->rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; lm->rev.diffopt.format_callback = last_modified_diff; lm->rev.diffopt.format_callback_data = &data; + lm->rev.no_walk = 1; prepare_revision_walk(&lm->rev); - while (hashmap_get_size(&lm->paths)) { - data.commit = get_revision(&lm->rev); - if (!data.commit) - BUG("paths remaining beyond boundary in last-modified"); + max_count = lm->rev.max_count; + + init_active_paths_for_commit(&lm->active_paths); + lm->scratch = bitmap_word_alloc(lm->all_paths_nr); + + /* + * lm->rev.commits holds the set of boundary commits for our walk. + * + * Loop through each such commit, and place it in the appropriate queue. + */ + for (list = lm->rev.commits; list; list = list->next) { + struct commit *c = list->item; + + if (c->object.flags & BOTTOM) { + prio_queue_put(¬_queue, c); + c->object.flags |= PARENT2; + } else if (!(c->object.flags & PARENT1)) { + /* + * If the commit is a starting point (and hasn't been + * seen yet), then initialize the set of interesting + * paths, too. + */ + struct bitmap *active; + + prio_queue_put(&queue, c); + c->object.flags |= PARENT1; + + active = active_paths_for(lm, c); + for (size_t i = 0; i < lm->all_paths_nr; i++) + bitmap_set(active, i); + } + } - if (data.commit->object.flags & BOUNDARY) { + while (queue.nr) { + int parent_i; + struct commit_list *p; + struct commit *c = prio_queue_get(&queue); + struct bitmap *active_c = active_paths_for(lm, c); + + if ((0 <= max_count && max_count < ++queue_popped) || + (c->object.flags & PARENT2)) { + /* + * Either a boundary commit, or we have already seen too + * many others. Either way, stop here. + */ + c->object.flags |= PARENT2 | BOUNDARY; + data.commit = c; diff_tree_oid(lm->rev.repo->hash_algo->empty_tree, - &data.commit->object.oid, "", - &lm->rev.diffopt); + &c->object.oid, + "", &lm->rev.diffopt); diff_flush(&lm->rev.diffopt); + goto cleanup; + } - break; + /* + * Otherwise, make sure that 'c' isn't reachable from anything + * in the '--not' queue. + */ + repo_parse_commit(lm->rev.repo, c); + + while (not_queue.nr) { + struct commit_list *np; + struct commit *n = prio_queue_get(¬_queue); + + repo_parse_commit(lm->rev.repo, n); + + for (np = n->parents; np; np = np->next) { + if (!(np->item->object.flags & PARENT2)) { + prio_queue_put(¬_queue, np->item); + np->item->object.flags |= PARENT2; + } + } + + if (commit_graph_generation(n) < commit_graph_generation(c)) + break; } - if (!maybe_changed_path(lm, data.commit)) - continue; + /* + * Look at each parent and pass on each path that's TREESAME + * with that parent. Stop early when no active paths remain. + */ + for (p = c->parents, parent_i = 0; p; p = p->next, parent_i++) { + process_parent(lm, &queue, + c, active_c, + p->item, parent_i); + + if (bitmap_is_empty(active_c)) + break; + } + + /* + * Paths that remain active, or not TREESAME with any parent, + * were changed by 'c'. + */ + if (!bitmap_is_empty(active_c)) { + data.commit = c; + for (size_t i = 0; i < lm->all_paths_nr; i++) { + if (bitmap_get(active_c, i)) + mark_path(lm->all_paths[i], NULL, &data); + } + } - log_tree_commit(&lm->rev, data.commit); +cleanup: + active_paths_free(lm, c); } + if (hashmap_get_size(&lm->paths)) + BUG("paths remaining beyond boundary in last-modified"); + + clear_prio_queue(¬_queue); + clear_prio_queue(&queue); + clear_active_paths_for_commit(&lm->active_paths); + bitmap_free(lm->scratch); + return 0; } static int last_modified_init(struct last_modified *lm, struct repository *r, const char *prefix, int argc, const char **argv) { + struct hashmap_iter iter; + struct last_modified_entry *ent; + hashmap_init(&lm->paths, last_modified_entry_hashcmp, NULL, 0); repo_init_revisions(r, &lm->rev, prefix); @@ -280,6 +493,13 @@ static int last_modified_init(struct last_modified *lm, struct repository *r, if (populate_paths_from_revs(lm) < 0) return error(_("unable to setup last-modified")); + CALLOC_ARRAY(lm->all_paths, hashmap_get_size(&lm->paths)); + lm->all_paths_nr = 0; + hashmap_for_each_entry(&lm->paths, &iter, ent, hashent) { + ent->diff_idx = lm->all_paths_nr++; + lm->all_paths[ent->diff_idx] = ent->path; + } + return 0; } diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index df09000b30..fe77829557 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -156,7 +156,7 @@ int cmd_ls_remote(int argc, continue; if (!tail_match(&pattern, ref->name)) continue; - item = ref_array_push(&ref_array, ref->name, &ref->old_oid); + item = ref_array_push(&ref_array, ref->name, &ref->old_oid, NULL); item->symref = xstrdup_or_null(ref->symref); } diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 74512e54a3..615f7d1aae 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -339,10 +339,9 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_) return a->taggerdate != b->taggerdate; } -static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, - int flags UNUSED, void *cb_data) +static int name_ref(const struct reference *ref, void *cb_data) { - struct object *o = parse_object(the_repository, oid); + struct object *o = parse_object(the_repository, ref->oid); struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; @@ -350,14 +349,14 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct struct commit *commit = NULL; timestamp_t taggerdate = TIME_MAX; - if (data->tags_only && !starts_with(path, "refs/tags/")) + if (data->tags_only && !starts_with(ref->name, "refs/tags/")) return 0; if (data->exclude_filters.nr) { struct string_list_item *item; for_each_string_list_item(item, &data->exclude_filters) { - if (subpath_matches(path, item->string) >= 0) + if (subpath_matches(ref->name, item->string) >= 0) return 0; } } @@ -378,7 +377,7 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct * shouldn't stop when seeing 'refs/tags/v1.4' matches * 'refs/tags/v*'. We should show it as 'v1.4'. */ - switch (subpath_matches(path, item->string)) { + switch (subpath_matches(ref->name, item->string)) { case -1: /* did not match */ break; case 0: /* matched fully */ @@ -406,13 +405,13 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct } if (o && o->type == OBJ_COMMIT) { commit = (struct commit *)o; - from_tag = starts_with(path, "refs/tags/"); + from_tag = starts_with(ref->name, "refs/tags/"); if (taggerdate == TIME_MAX) taggerdate = commit->date; } - add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate, - from_tag, deref); + add_to_tip_table(ref->oid, ref->name, can_abbreviate_output, + commit, taggerdate, from_tag, deref); return 0; } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index b5454e5df1..4486b55e6d 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -831,15 +831,14 @@ static enum write_one_status write_one(struct hashfile *f, return WRITE_ONE_WRITTEN; } -static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int mark_tagged(const struct reference *ref, void *cb_data UNUSED) { struct object_id peeled; - struct object_entry *entry = packlist_find(&to_pack, oid); + struct object_entry *entry = packlist_find(&to_pack, ref->oid); if (entry) entry->tagged = 1; - if (!peel_iterated_oid(the_repository, oid, &peeled)) { + if (!reference_get_peeled_oid(the_repository, ref, &peeled)) { entry = packlist_find(&to_pack, &peeled); if (entry) entry->tagged = 1; @@ -1706,8 +1705,8 @@ static int want_object_in_pack_mtime(const struct object_id *oid, uint32_t found_mtime) { int want; + struct packfile_list_entry *e; struct odb_source *source; - struct list_head *pos; if (!exclude && local) { /* @@ -1748,12 +1747,11 @@ static int want_object_in_pack_mtime(const struct object_id *oid, } } - list_for_each(pos, packfile_store_get_packs_mru(the_repository->objects->packfiles)) { - struct packed_git *p = list_entry(pos, struct packed_git, mru); + for (e = the_repository->objects->packfiles->packs.head; e; e = e->next) { + struct packed_git *p = e->pack; want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime); if (!exclude && want > 0) - list_move(&p->mru, - packfile_store_get_packs_mru(the_repository->objects->packfiles)); + packfile_list_prepend(&the_repository->objects->packfiles->packs, p); if (want != -1) return want; } @@ -3306,13 +3304,13 @@ static void add_tag_chain(const struct object_id *oid) } } -static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int add_ref_tag(const struct reference *ref, void *cb_data UNUSED) { struct object_id peeled; - if (!peel_iterated_oid(the_repository, oid, &peeled) && obj_is_packed(&peeled)) - add_tag_chain(oid); + if (!reference_get_peeled_oid(the_repository, ref, &peeled) && + obj_is_packed(&peeled)) + add_tag_chain(ref->oid); return 0; } @@ -4389,27 +4387,27 @@ static void add_unreachable_loose_objects(struct rev_info *revs) static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid) { - struct packfile_store *packs = the_repository->objects->packfiles; - static struct packed_git *last_found = (void *)1; + static struct packed_git *last_found = NULL; struct packed_git *p; - p = (last_found != (void *)1) ? last_found : - packfile_store_get_packs(packs); + if (last_found && find_pack_entry_one(oid, last_found)) + return 1; - while (p) { - if ((!p->pack_local || p->pack_keep || - p->pack_keep_in_core) && - find_pack_entry_one(oid, p)) { + repo_for_each_pack(the_repository, p) { + /* + * We have already checked `last_found`, so there is no need to + * re-check here. + */ + if (p == last_found) + continue; + + if ((!p->pack_local || p->pack_keep || p->pack_keep_in_core) && + find_pack_entry_one(oid, p)) { last_found = p; return 1; } - if (p == last_found) - p = packfile_store_get_packs(packs); - else - p = p->next; - if (p == last_found) - p = p->next; } + return 0; } @@ -4528,19 +4526,16 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED) oid_array_append(&recent_objects, &commit->object.oid); } -static int mark_bitmap_preferred_tip(const char *refname, - const char *referent UNUSED, - const struct object_id *oid, - int flags UNUSED, - void *data UNUSED) +static int mark_bitmap_preferred_tip(const struct reference *ref, void *data UNUSED) { + const struct object_id *maybe_peeled = ref->oid; struct object_id peeled; struct object *object; - if (!peel_iterated_oid(the_repository, oid, &peeled)) - oid = &peeled; + if (!reference_get_peeled_oid(the_repository, ref, &peeled)) + maybe_peeled = &peeled; - object = parse_object_or_die(the_repository, oid, refname); + object = parse_object_or_die(the_repository, maybe_peeled, ref->name); if (object->type == OBJ_COMMIT) object->flags |= NEEDS_BITMAP; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index c9288a9c7e..e8ee0e7321 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -305,13 +305,12 @@ static void show_ref(const char *path, const struct object_id *oid) } } -static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *data) +static int show_ref_cb(const struct reference *ref, void *data) { struct oidset *seen = data; - const char *path = strip_namespace(path_full); + const char *path = strip_namespace(ref->name); - if (ref_is_hidden(path, path_full, &hidden_refs)) + if (ref_is_hidden(path, ref->name, &hidden_refs)) return 0; /* @@ -320,13 +319,13 @@ static int show_ref_cb(const char *path_full, const char *referent UNUSED, const * transfer but will otherwise ignore them. */ if (!path) { - if (oidset_insert(seen, oid)) + if (oidset_insert(seen, ref->oid)) return 0; path = ".have"; } else { - oidset_insert(seen, oid); + oidset_insert(seen, ref->oid); } - show_ref(path, oid); + show_ref(path, ref->oid); return 0; } diff --git a/builtin/remote.c b/builtin/remote.c index 8a7ed4299a..7ffc14ba15 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -570,17 +570,14 @@ struct branches_for_remote { struct known_remotes *keep; }; -static int add_branch_for_removal(const char *refname, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flags UNUSED, void *cb_data) +static int add_branch_for_removal(const struct reference *ref, void *cb_data) { struct branches_for_remote *branches = cb_data; struct refspec_item refspec; struct known_remote *kr; memset(&refspec, 0, sizeof(refspec)); - refspec.dst = (char *)refname; + refspec.dst = (char *)ref->name; if (remote_find_tracking(branches->remote, &refspec)) return 0; free(refspec.src); @@ -588,7 +585,7 @@ static int add_branch_for_removal(const char *refname, /* don't delete a branch if another remote also uses it */ for (kr = branches->keep->list; kr; kr = kr->next) { memset(&refspec, 0, sizeof(refspec)); - refspec.dst = (char *)refname; + refspec.dst = (char *)ref->name; if (!remote_find_tracking(kr->remote, &refspec)) { free(refspec.src); return 0; @@ -596,16 +593,16 @@ static int add_branch_for_removal(const char *refname, } /* don't delete non-remote-tracking refs */ - if (!starts_with(refname, "refs/remotes/")) { + if (!starts_with(ref->name, "refs/remotes/")) { /* advise user how to delete local branches */ - if (starts_with(refname, "refs/heads/")) + if (starts_with(ref->name, "refs/heads/")) string_list_append(branches->skipped, - abbrev_branch(refname)); + abbrev_branch(ref->name)); /* silently skip over other non-remote refs */ return 0; } - string_list_append(branches->branches, refname); + string_list_append(branches->branches, ref->name); return 0; } @@ -713,18 +710,18 @@ out: return error; } -static int rename_one_ref(const char *old_refname, const char *referent, - const struct object_id *oid, - int flags, void *cb_data) +static int rename_one_ref(const struct reference *ref, void *cb_data) { struct strbuf new_referent = STRBUF_INIT; struct strbuf new_refname = STRBUF_INIT; struct rename_info *rename = cb_data; + const struct object_id *oid = ref->oid; + const char *referent = ref->target; int error; - compute_renamed_ref(rename, old_refname, &new_refname); + compute_renamed_ref(rename, ref->name, &new_refname); - if (flags & REF_ISSYMREF) { + if (ref->flags & REF_ISSYMREF) { /* * Stupidly enough `referent` is not pointing to the immediate * target of a symref, but it's the recursively resolved value. @@ -732,25 +729,25 @@ static int rename_one_ref(const char *old_refname, const char *referent, * unborn symrefs don't have any value for the `referent` at all. */ referent = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), - old_refname, RESOLVE_REF_NO_RECURSE, + ref->name, RESOLVE_REF_NO_RECURSE, NULL, NULL); compute_renamed_ref(rename, referent, &new_referent); oid = NULL; } - error = ref_transaction_delete(rename->transaction, old_refname, + error = ref_transaction_delete(rename->transaction, ref->name, oid, referent, REF_NO_DEREF, NULL, rename->err); if (error < 0) goto out; error = ref_transaction_update(rename->transaction, new_refname.buf, oid, null_oid(the_hash_algo), - (flags & REF_ISSYMREF) ? new_referent.buf : NULL, NULL, + (ref->flags & REF_ISSYMREF) ? new_referent.buf : NULL, NULL, REF_SKIP_CREATE_REFLOG | REF_NO_DEREF | REF_SKIP_OID_VERIFICATION, NULL, rename->err); if (error < 0) goto out; - error = rename_one_reflog(old_refname, oid, rename); + error = rename_one_reflog(ref->name, oid, rename); if (error < 0) goto out; @@ -1125,19 +1122,16 @@ static void free_remote_ref_states(struct ref_states *states) string_list_clear_func(&states->push, clear_push_info); } -static int append_ref_to_tracked_list(const char *refname, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flags, void *cb_data) +static int append_ref_to_tracked_list(const struct reference *ref, void *cb_data) { struct ref_states *states = cb_data; struct refspec_item refspec; - if (flags & REF_ISSYMREF) + if (ref->flags & REF_ISSYMREF) return 0; memset(&refspec, 0, sizeof(refspec)); - refspec.dst = (char *)refname; + refspec.dst = (char *)ref->name; if (!remote_find_tracking(states->remote, &refspec)) { string_list_append(&states->tracked, abbrev_branch(refspec.src)); free(refspec.src); diff --git a/builtin/replace.c b/builtin/replace.c index 900b560a77..4c62c5ab58 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -47,30 +47,27 @@ struct show_data { enum replace_format format; }; -static int show_reference(const char *refname, - const char *referent UNUSED, - const struct object_id *oid, - int flag UNUSED, void *cb_data) +static int show_reference(const struct reference *ref, void *cb_data) { struct show_data *data = cb_data; - if (!wildmatch(data->pattern, refname, 0)) { + if (!wildmatch(data->pattern, ref->name, 0)) { if (data->format == REPLACE_FORMAT_SHORT) - printf("%s\n", refname); + printf("%s\n", ref->name); else if (data->format == REPLACE_FORMAT_MEDIUM) - printf("%s -> %s\n", refname, oid_to_hex(oid)); + printf("%s -> %s\n", ref->name, oid_to_hex(ref->oid)); else { /* data->format == REPLACE_FORMAT_LONG */ struct object_id object; enum object_type obj_type, repl_type; - if (repo_get_oid(data->repo, refname, &object)) - return error(_("failed to resolve '%s' as a valid ref"), refname); + if (repo_get_oid(data->repo, ref->name, &object)) + return error(_("failed to resolve '%s' as a valid ref"), ref->name); obj_type = odb_read_object_info(data->repo->objects, &object, NULL); - repl_type = odb_read_object_info(data->repo->objects, oid, NULL); + repl_type = odb_read_object_info(data->repo->objects, ref->oid, NULL); - printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type), - oid_to_hex(oid), type_name(repl_type)); + printf("%s (%s) -> %s (%s)\n", ref->name, type_name(obj_type), + oid_to_hex(ref->oid), type_name(repl_type)); } } diff --git a/builtin/repo.c b/builtin/repo.c index bbb0966f2d..f26640bd6e 100644 --- a/builtin/repo.c +++ b/builtin/repo.c @@ -3,19 +3,27 @@ #include "builtin.h" #include "environment.h" #include "parse-options.h" +#include "path-walk.h" +#include "progress.h" #include "quote.h" +#include "ref-filter.h" #include "refs.h" +#include "revision.h" #include "strbuf.h" +#include "string-list.h" #include "shallow.h" +#include "utf8.h" static const char *const repo_usage[] = { "git repo info [--format=(keyvalue|nul)] [-z] [<key>...]", + "git repo structure [--format=(table|keyvalue|nul)]", NULL }; typedef int get_value_fn(struct repository *repo, struct strbuf *buf); enum output_format { + FORMAT_TABLE, FORMAT_KEYVALUE, FORMAT_NUL_TERMINATED, }; @@ -130,14 +138,16 @@ static int parse_format_cb(const struct option *opt, *format = FORMAT_NUL_TERMINATED; else if (!strcmp(arg, "keyvalue")) *format = FORMAT_KEYVALUE; + else if (!strcmp(arg, "table")) + *format = FORMAT_TABLE; else die(_("invalid format '%s'"), arg); return 0; } -static int repo_info(int argc, const char **argv, const char *prefix, - struct repository *repo) +static int cmd_repo_info(int argc, const char **argv, const char *prefix, + struct repository *repo) { enum output_format format = FORMAT_KEYVALUE; struct option options[] = { @@ -152,16 +162,377 @@ static int repo_info(int argc, const char **argv, const char *prefix, }; argc = parse_options(argc, argv, prefix, options, repo_usage, 0); + if (format != FORMAT_KEYVALUE && format != FORMAT_NUL_TERMINATED) + die(_("unsupported output format")); return print_fields(argc, argv, repo, format); } +struct ref_stats { + size_t branches; + size_t remotes; + size_t tags; + size_t others; +}; + +struct object_stats { + size_t tags; + size_t commits; + size_t trees; + size_t blobs; +}; + +struct repo_structure { + struct ref_stats refs; + struct object_stats objects; +}; + +struct stats_table { + struct string_list rows; + + int name_col_width; + int value_col_width; +}; + +/* + * Holds column data that gets stored for each row. + */ +struct stats_table_entry { + char *value; +}; + +static void stats_table_vaddf(struct stats_table *table, + struct stats_table_entry *entry, + const char *format, va_list ap) +{ + struct strbuf buf = STRBUF_INIT; + struct string_list_item *item; + char *formatted_name; + int name_width; + + strbuf_vaddf(&buf, format, ap); + formatted_name = strbuf_detach(&buf, NULL); + name_width = utf8_strwidth(formatted_name); + + item = string_list_append_nodup(&table->rows, formatted_name); + item->util = entry; + + if (name_width > table->name_col_width) + table->name_col_width = name_width; + if (entry) { + int value_width = utf8_strwidth(entry->value); + if (value_width > table->value_col_width) + table->value_col_width = value_width; + } +} + +static void stats_table_addf(struct stats_table *table, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + stats_table_vaddf(table, NULL, format, ap); + va_end(ap); +} + +static void stats_table_count_addf(struct stats_table *table, size_t value, + const char *format, ...) +{ + struct stats_table_entry *entry; + va_list ap; + + CALLOC_ARRAY(entry, 1); + entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value); + + va_start(ap, format); + stats_table_vaddf(table, entry, format, ap); + va_end(ap); +} + +static inline size_t get_total_reference_count(struct ref_stats *stats) +{ + return stats->branches + stats->remotes + stats->tags + stats->others; +} + +static inline size_t get_total_object_count(struct object_stats *stats) +{ + return stats->tags + stats->commits + stats->trees + stats->blobs; +} + +static void stats_table_setup_structure(struct stats_table *table, + struct repo_structure *stats) +{ + struct object_stats *objects = &stats->objects; + struct ref_stats *refs = &stats->refs; + size_t object_total; + size_t ref_total; + + ref_total = get_total_reference_count(refs); + stats_table_addf(table, "* %s", _("References")); + stats_table_count_addf(table, ref_total, " * %s", _("Count")); + stats_table_count_addf(table, refs->branches, " * %s", _("Branches")); + stats_table_count_addf(table, refs->tags, " * %s", _("Tags")); + stats_table_count_addf(table, refs->remotes, " * %s", _("Remotes")); + stats_table_count_addf(table, refs->others, " * %s", _("Others")); + + object_total = get_total_object_count(objects); + stats_table_addf(table, ""); + stats_table_addf(table, "* %s", _("Reachable objects")); + stats_table_count_addf(table, object_total, " * %s", _("Count")); + stats_table_count_addf(table, objects->commits, " * %s", _("Commits")); + stats_table_count_addf(table, objects->trees, " * %s", _("Trees")); + stats_table_count_addf(table, objects->blobs, " * %s", _("Blobs")); + stats_table_count_addf(table, objects->tags, " * %s", _("Tags")); +} + +static void stats_table_print_structure(const struct stats_table *table) +{ + const char *name_col_title = _("Repository structure"); + const char *value_col_title = _("Value"); + int name_col_width = utf8_strwidth(name_col_title); + int value_col_width = utf8_strwidth(value_col_title); + struct string_list_item *item; + + if (table->name_col_width > name_col_width) + name_col_width = table->name_col_width; + if (table->value_col_width > value_col_width) + value_col_width = table->value_col_width; + + printf("| %-*s | %-*s |\n", name_col_width, name_col_title, + value_col_width, value_col_title); + printf("| "); + for (int i = 0; i < name_col_width; i++) + putchar('-'); + printf(" | "); + for (int i = 0; i < value_col_width; i++) + putchar('-'); + printf(" |\n"); + + for_each_string_list_item(item, &table->rows) { + struct stats_table_entry *entry = item->util; + const char *value = ""; + + if (entry) { + struct stats_table_entry *entry = item->util; + value = entry->value; + } + + printf("| %-*s | %*s |\n", name_col_width, item->string, + value_col_width, value); + } +} + +static void stats_table_clear(struct stats_table *table) +{ + struct stats_table_entry *entry; + struct string_list_item *item; + + for_each_string_list_item(item, &table->rows) { + entry = item->util; + if (entry) + free(entry->value); + } + + string_list_clear(&table->rows, 1); +} + +static void structure_keyvalue_print(struct repo_structure *stats, + char key_delim, char value_delim) +{ + printf("references.branches.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->refs.branches, value_delim); + printf("references.tags.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->refs.tags, value_delim); + printf("references.remotes.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->refs.remotes, value_delim); + printf("references.others.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->refs.others, value_delim); + + printf("objects.commits.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->objects.commits, value_delim); + printf("objects.trees.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->objects.trees, value_delim); + printf("objects.blobs.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->objects.blobs, value_delim); + printf("objects.tags.count%c%" PRIuMAX "%c", key_delim, + (uintmax_t)stats->objects.tags, value_delim); + + fflush(stdout); +} + +struct count_references_data { + struct ref_stats *stats; + struct rev_info *revs; + struct progress *progress; +}; + +static int count_references(const struct reference *ref, void *cb_data) +{ + struct count_references_data *data = cb_data; + struct ref_stats *stats = data->stats; + size_t ref_count; + + switch (ref_kind_from_refname(ref->name)) { + case FILTER_REFS_BRANCHES: + stats->branches++; + break; + case FILTER_REFS_REMOTES: + stats->remotes++; + break; + case FILTER_REFS_TAGS: + stats->tags++; + break; + case FILTER_REFS_OTHERS: + stats->others++; + break; + default: + BUG("unexpected reference type"); + } + + /* + * While iterating through references for counting, also add OIDs in + * preparation for the path walk. + */ + add_pending_oid(data->revs, NULL, ref->oid, 0); + + ref_count = get_total_reference_count(stats); + display_progress(data->progress, ref_count); + + return 0; +} + +static void structure_count_references(struct ref_stats *stats, + struct rev_info *revs, + struct repository *repo, + int show_progress) +{ + struct count_references_data data = { + .stats = stats, + .revs = revs, + }; + + if (show_progress) + data.progress = start_delayed_progress(repo, + _("Counting references"), 0); + + refs_for_each_ref(get_main_ref_store(repo), count_references, &data); + stop_progress(&data.progress); +} + +struct count_objects_data { + struct object_stats *stats; + struct progress *progress; +}; + +static int count_objects(const char *path UNUSED, struct oid_array *oids, + enum object_type type, void *cb_data) +{ + struct count_objects_data *data = cb_data; + struct object_stats *stats = data->stats; + size_t object_count; + + switch (type) { + case OBJ_TAG: + stats->tags += oids->nr; + break; + case OBJ_COMMIT: + stats->commits += oids->nr; + break; + case OBJ_TREE: + stats->trees += oids->nr; + break; + case OBJ_BLOB: + stats->blobs += oids->nr; + break; + default: + BUG("invalid object type"); + } + + object_count = get_total_object_count(stats); + display_progress(data->progress, object_count); + + return 0; +} + +static void structure_count_objects(struct object_stats *stats, + struct rev_info *revs, + struct repository *repo, int show_progress) +{ + struct path_walk_info info = PATH_WALK_INFO_INIT; + struct count_objects_data data = { + .stats = stats, + }; + + info.revs = revs; + info.path_fn = count_objects; + info.path_fn_data = &data; + + if (show_progress) + data.progress = start_delayed_progress(repo, _("Counting objects"), 0); + + walk_objects_by_path(&info); + path_walk_info_clear(&info); + stop_progress(&data.progress); +} + +static int cmd_repo_structure(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + struct stats_table table = { + .rows = STRING_LIST_INIT_DUP, + }; + enum output_format format = FORMAT_TABLE; + struct repo_structure stats = { 0 }; + struct rev_info revs; + int show_progress = -1; + struct option options[] = { + OPT_CALLBACK_F(0, "format", &format, N_("format"), + N_("output format"), + PARSE_OPT_NONEG, parse_format_cb), + OPT_BOOL(0, "progress", &show_progress, N_("show progress")), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, repo_usage, 0); + if (argc) + usage(_("too many arguments")); + + repo_init_revisions(repo, &revs, prefix); + + if (show_progress < 0) + show_progress = isatty(2); + + structure_count_references(&stats.refs, &revs, repo, show_progress); + structure_count_objects(&stats.objects, &revs, repo, show_progress); + + switch (format) { + case FORMAT_TABLE: + stats_table_setup_structure(&table, &stats); + stats_table_print_structure(&table); + break; + case FORMAT_KEYVALUE: + structure_keyvalue_print(&stats, '=', '\n'); + break; + case FORMAT_NUL_TERMINATED: + structure_keyvalue_print(&stats, '\n', '\0'); + break; + default: + BUG("invalid output format"); + } + + stats_table_clear(&table); + release_revisions(&revs); + + return 0; +} + int cmd_repo(int argc, const char **argv, const char *prefix, struct repository *repo) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { - OPT_SUBCOMMAND("info", &fn, repo_info), + OPT_SUBCOMMAND("info", &fn, cmd_repo_info), + OPT_SUBCOMMAND("structure", &fn, cmd_repo_structure), OPT_END() }; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 7b3711cf34..9032cc6327 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -217,19 +217,17 @@ static int show_default(void) return 0; } -static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int show_reference(const struct reference *ref, void *cb_data UNUSED) { - if (ref_excluded(&ref_excludes, refname)) + if (ref_excluded(&ref_excludes, ref->name)) return 0; - show_rev(NORMAL, oid, refname); + show_rev(NORMAL, ref->oid, ref->name); return 0; } -static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int anti_reference(const struct reference *ref, void *cb_data UNUSED) { - show_rev(REVERSED, oid, refname); + show_rev(REVERSED, ref->oid, ref->name); return 0; } diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 441babf2e3..10475a6b5e 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -413,34 +413,32 @@ static int append_ref(const char *refname, const struct object_id *oid, return 0; } -static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int append_head_ref(const struct reference *ref, void *cb_data UNUSED) { struct object_id tmp; int ofs = 11; - if (!starts_with(refname, "refs/heads/")) + if (!starts_with(ref->name, "refs/heads/")) return 0; /* If both heads/foo and tags/foo exists, get_sha1 would * get confused. */ - if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid)) + if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid)) ofs = 5; - return append_ref(refname + ofs, oid, 0); + return append_ref(ref->name + ofs, ref->oid, 0); } -static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cb_data UNUSED) +static int append_remote_ref(const struct reference *ref, void *cb_data UNUSED) { struct object_id tmp; int ofs = 13; - if (!starts_with(refname, "refs/remotes/")) + if (!starts_with(ref->name, "refs/remotes/")) return 0; /* If both heads/foo and tags/foo exists, get_sha1 would * get confused. */ - if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid)) + if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid)) ofs = 5; - return append_ref(refname + ofs, oid, 0); + return append_ref(ref->name + ofs, ref->oid, 0); } static int append_tag_ref(const char *refname, const struct object_id *oid, @@ -454,27 +452,26 @@ static int append_tag_ref(const char *refname, const struct object_id *oid, static const char *match_ref_pattern = NULL; static int match_ref_slash = 0; -static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag, void *cb_data) +static int append_matching_ref(const struct reference *ref, void *cb_data) { /* we want to allow pattern hold/<asterisk> to show all * branches under refs/heads/hold/, and v0.99.9? to show * refs/tags/v0.99.9a and friends. */ const char *tail; - int slash = count_slashes(refname); - for (tail = refname; *tail && match_ref_slash < slash; ) + int slash = count_slashes(ref->name); + for (tail = ref->name; *tail && match_ref_slash < slash; ) if (*tail++ == '/') slash--; if (!*tail) return 0; if (wildmatch(match_ref_pattern, tail, 0)) return 0; - if (starts_with(refname, "refs/heads/")) - return append_head_ref(refname, NULL, oid, flag, cb_data); - if (starts_with(refname, "refs/tags/")) - return append_tag_ref(refname, oid, flag, cb_data); - return append_ref(refname, oid, 0); + if (starts_with(ref->name, "refs/heads/")) + return append_head_ref(ref, cb_data); + if (starts_with(ref->name, "refs/tags/")) + return append_tag_ref(ref->name, ref->oid, ref->flags, cb_data); + return append_ref(ref->name, ref->oid, 0); } static void snarf_refs(int head, int remotes) diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 0b6f9edf86..4d4984e4e0 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -31,31 +31,31 @@ struct show_one_options { }; static void show_one(const struct show_one_options *opts, - const char *refname, const struct object_id *oid) + const struct reference *ref) { const char *hex; struct object_id peeled; - if (!odb_has_object(the_repository->objects, oid, + if (!odb_has_object(the_repository->objects, ref->oid, HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) - die("git show-ref: bad ref %s (%s)", refname, - oid_to_hex(oid)); + die("git show-ref: bad ref %s (%s)", ref->name, + oid_to_hex(ref->oid)); if (opts->quiet) return; - hex = repo_find_unique_abbrev(the_repository, oid, opts->abbrev); + hex = repo_find_unique_abbrev(the_repository, ref->oid, opts->abbrev); if (opts->hash_only) printf("%s\n", hex); else - printf("%s %s\n", hex, refname); + printf("%s %s\n", hex, ref->name); if (!opts->deref_tags) return; - if (!peel_iterated_oid(the_repository, oid, &peeled)) { + if (!reference_get_peeled_oid(the_repository, ref, &peeled)) { hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev); - printf("%s %s^{}\n", hex, refname); + printf("%s %s^{}\n", hex, ref->name); } } @@ -66,26 +66,25 @@ struct show_ref_data { int show_head; }; -static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, - int flag UNUSED, void *cbdata) +static int show_ref(const struct reference *ref, void *cbdata) { struct show_ref_data *data = cbdata; - if (data->show_head && !strcmp(refname, "HEAD")) + if (data->show_head && !strcmp(ref->name, "HEAD")) goto match; if (data->patterns) { - int reflen = strlen(refname); + int reflen = strlen(ref->name); const char **p = data->patterns, *m; while ((m = *p++) != NULL) { int len = strlen(m); if (len > reflen) continue; - if (memcmp(m, refname + reflen - len, len)) + if (memcmp(m, ref->name + reflen - len, len)) continue; if (len == reflen) goto match; - if (refname[reflen - len - 1] == '/') + if (ref->name[reflen - len - 1] == '/') goto match; } return 0; @@ -94,18 +93,15 @@ static int show_ref(const char *refname, const char *referent UNUSED, const stru match: data->found_match++; - show_one(data->show_one_opts, refname, oid); + show_one(data->show_one_opts, ref); return 0; } -static int add_existing(const char *refname, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flag UNUSED, void *cbdata) +static int add_existing(const struct reference *ref, void *cbdata) { struct string_list *list = (struct string_list *)cbdata; - string_list_insert(list, refname); + string_list_insert(list, ref->name); return 0; } @@ -179,12 +175,18 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts, if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) && !refs_read_ref(get_main_ref_store(the_repository), *refs, &oid)) { - show_one(show_one_opts, *refs, &oid); - } - else if (!show_one_opts->quiet) + struct reference ref = { + .name = *refs, + .oid = &oid, + }; + + show_one(show_one_opts, &ref); + } else if (!show_one_opts->quiet) { die("'%s' - not a valid ref", *refs); - else + } else { return 1; + } + refs++; } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index fcd73abe53..35f6cf735e 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -593,16 +593,12 @@ static void print_status(unsigned int flags, char state, const char *path, printf("\n"); } -static int handle_submodule_head_ref(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid, - int flags UNUSED, - void *cb_data) +static int handle_submodule_head_ref(const struct reference *ref, void *cb_data) { struct object_id *output = cb_data; - if (oid) - oidcpy(output, oid); + if (ref->oid) + oidcpy(output, ref->oid); return 0; } diff --git a/builtin/tag.c b/builtin/tag.c index f0665af3ac..01eba90c5c 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -153,7 +153,7 @@ static int verify_tag(const char *name, const char *ref UNUSED, return -1; if (format->format) - pretty_print_ref(name, oid, format); + pretty_print_ref(name, oid, NULL, format); return 0; } diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index cd6bc11095..558121eaa1 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -67,7 +67,7 @@ int cmd_verify_tag(int argc, } if (format.format) - pretty_print_ref(name, &oid, &format); + pretty_print_ref(name, &oid, NULL, &format); } return had_error; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 812774a5ca..b7f323b5e4 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -635,11 +635,7 @@ static void print_preparing_worktree_line(int detach, * * Returns 0 on failure and non-zero on success. */ -static int first_valid_ref(const char *refname UNUSED, - const char *referent UNUSED, - const struct object_id *oid UNUSED, - int flags UNUSED, - void *cb_data UNUSED) +static int first_valid_ref(const struct reference *ref UNUSED, void *cb_data UNUSED) { return 1; } |
