diff options
Diffstat (limited to 'builtin')
58 files changed, 596 insertions, 1636 deletions
diff --git a/builtin/add.c b/builtin/add.c index b2a5c57f0a..145f06ef97 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -336,14 +336,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (!show_only && ignore_missing) die(_("Option --ignore-missing can only be used together with --dry-run")); - if ((0 < addremove_explicit || take_worktree_changes) && !argc) { - static const char *whole[2] = { ":/", NULL }; - argc = 1; - argv = whole; - } - add_new_files = !take_worktree_changes && !refresh_only; - require_pathspec = !take_worktree_changes; + require_pathspec = !(take_worktree_changes || (0 < addremove_explicit)); hold_locked_index(&lock_file, 1); diff --git a/builtin/am.c b/builtin/am.c index 6c8bbca226..95decc6a59 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -27,6 +27,7 @@ #include "notes-utils.h" #include "rerere.h" #include "prompt.h" +#include "mailinfo.h" /** * Returns 1 if the file is empty or does not exist, 0 otherwise. @@ -1258,58 +1259,61 @@ static void am_append_signoff(struct am_state *state) static int parse_mail(struct am_state *state, const char *mail) { FILE *fp; - struct child_process cp = CHILD_PROCESS_INIT; struct strbuf sb = STRBUF_INIT; struct strbuf msg = STRBUF_INIT; struct strbuf author_name = STRBUF_INIT; struct strbuf author_date = STRBUF_INIT; struct strbuf author_email = STRBUF_INIT; int ret = 0; + struct mailinfo mi; - cp.git_cmd = 1; - cp.in = xopen(mail, O_RDONLY, 0); - cp.out = xopen(am_path(state, "info"), O_WRONLY | O_CREAT, 0777); + setup_mailinfo(&mi); - argv_array_push(&cp.args, "mailinfo"); - argv_array_push(&cp.args, state->utf8 ? "-u" : "-n"); + if (state->utf8) + mi.metainfo_charset = get_commit_output_encoding(); + else + mi.metainfo_charset = NULL; switch (state->keep) { case KEEP_FALSE: break; case KEEP_TRUE: - argv_array_push(&cp.args, "-k"); + mi.keep_subject = 1; break; case KEEP_NON_PATCH: - argv_array_push(&cp.args, "-b"); + mi.keep_non_patch_brackets_in_subject = 1; break; default: die("BUG: invalid value for state->keep"); } if (state->message_id) - argv_array_push(&cp.args, "-m"); + mi.add_message_id = 1; switch (state->scissors) { case SCISSORS_UNSET: break; case SCISSORS_FALSE: - argv_array_push(&cp.args, "--no-scissors"); + mi.use_scissors = 0; break; case SCISSORS_TRUE: - argv_array_push(&cp.args, "--scissors"); + mi.use_scissors = 1; break; default: die("BUG: invalid value for state->scissors"); } - argv_array_push(&cp.args, am_path(state, "msg")); - argv_array_push(&cp.args, am_path(state, "patch")); - - if (run_command(&cp) < 0) + mi.input = fopen(mail, "r"); + if (!mi.input) + die("could not open input"); + mi.output = fopen(am_path(state, "info"), "w"); + if (!mi.output) + die("could not open output 'info'"); + if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch"))) die("could not parse patch"); - close(cp.in); - close(cp.out); + fclose(mi.input); + fclose(mi.output); /* Extract message and author information */ fp = xfopen(am_path(state, "info"), "r"); @@ -1341,9 +1345,8 @@ static int parse_mail(struct am_state *state, const char *mail) } strbuf_addstr(&msg, "\n\n"); - if (strbuf_read_file(&msg, am_path(state, "msg"), 0) < 0) - die_errno(_("could not read '%s'"), am_path(state, "msg")); - stripspace(&msg, 0); + strbuf_addbuf(&msg, &mi.log_message); + strbuf_stripspace(&msg, 0); if (state->signoff) am_signoff(&msg); @@ -1366,6 +1369,7 @@ finish: strbuf_release(&author_email); strbuf_release(&author_name); strbuf_release(&sb); + clear_mailinfo(&mi); return ret; } @@ -1437,7 +1441,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit) assert(!state->msg); msg = strstr(buffer, "\n\n"); if (!msg) - die(_("unable to parse commit %s"), sha1_to_hex(commit->object.sha1)); + die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid)); state->msg = xstrdup(msg + 2); state->msg_len = strlen(state->msg); } @@ -1653,7 +1657,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa init_revisions(&rev_info, NULL); rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS; - diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1); + diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix); add_pending_sha1(&rev_info, "HEAD", our_tree, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); @@ -1935,6 +1939,7 @@ next: */ if (!state->rebasing) { am_destroy(state); + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } @@ -2246,8 +2251,8 @@ int cmd_am(int argc, const char **argv, const char *prefix) int in_progress; const char * const usage[] = { - N_("git am [options] [(<mbox>|<Maildir>)...]"), - N_("git am [options] (--continue | --skip | --abort)"), + N_("git am [<options>] [(<mbox>|<Maildir>)...]"), + N_("git am [<options>] (--continue | --skip | --abort)"), NULL }; diff --git a/builtin/blame.c b/builtin/blame.c index 6fc7bff9a3..1df13cf7f4 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -506,7 +506,7 @@ static int fill_blob_sha1_and_mode(struct origin *origin) { if (!is_null_sha1(origin->blob_sha1)) return 0; - if (get_tree_entry(origin->commit->object.sha1, + if (get_tree_entry(origin->commit->object.oid.hash, origin->path, origin->blob_sha1, &origin->mode)) goto error_out; @@ -557,11 +557,11 @@ static struct origin *find_origin(struct scoreboard *sb, PATHSPEC_LITERAL_PATH, "", paths); diff_setup_done(&diff_opts); - if (is_null_sha1(origin->commit->object.sha1)) - do_diff_cache(parent->tree->object.sha1, &diff_opts); + if (is_null_oid(&origin->commit->object.oid)) + do_diff_cache(parent->tree->object.oid.hash, &diff_opts); else - diff_tree_sha1(parent->tree->object.sha1, - origin->commit->tree->object.sha1, + diff_tree_sha1(parent->tree->object.oid.hash, + origin->commit->tree->object.oid.hash, "", &diff_opts); diffcore_std(&diff_opts); @@ -627,11 +627,11 @@ static struct origin *find_rename(struct scoreboard *sb, diff_opts.single_follow = origin->path; diff_setup_done(&diff_opts); - if (is_null_sha1(origin->commit->object.sha1)) - do_diff_cache(parent->tree->object.sha1, &diff_opts); + if (is_null_oid(&origin->commit->object.oid)) + do_diff_cache(parent->tree->object.oid.hash, &diff_opts); else - diff_tree_sha1(parent->tree->object.sha1, - origin->commit->tree->object.sha1, + diff_tree_sha1(parent->tree->object.oid.hash, + origin->commit->tree->object.oid.hash, "", &diff_opts); diffcore_std(&diff_opts); @@ -977,8 +977,8 @@ static void pass_blame_to_parent(struct scoreboard *sb, if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d)) die("unable to generate diff (%s -> %s)", - sha1_to_hex(parent->commit->object.sha1), - sha1_to_hex(target->commit->object.sha1)); + oid_to_hex(&parent->commit->object.oid), + oid_to_hex(&target->commit->object.oid)); /* The rest are the same as the parent */ blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent); *d.dstq = NULL; @@ -1126,7 +1126,7 @@ static void find_copy_in_blob(struct scoreboard *sb, memset(split, 0, sizeof(struct blame_entry [3])); if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d)) die("unable to generate diff (%s)", - sha1_to_hex(parent->commit->object.sha1)); + oid_to_hex(&parent->commit->object.oid)); /* remainder, if any, all match the preimage */ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split); } @@ -1275,11 +1275,11 @@ static void find_copy_in_parent(struct scoreboard *sb, && (!porigin || strcmp(target->path, porigin->path)))) DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER); - if (is_null_sha1(target->commit->object.sha1)) - do_diff_cache(parent->tree->object.sha1, &diff_opts); + if (is_null_oid(&target->commit->object.oid)) + do_diff_cache(parent->tree->object.oid.hash, &diff_opts); else - diff_tree_sha1(parent->tree->object.sha1, - target->commit->tree->object.sha1, + diff_tree_sha1(parent->tree->object.oid.hash, + target->commit->tree->object.oid.hash, "", &diff_opts); if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER)) @@ -1690,7 +1690,7 @@ static void get_commit_info(struct commit *commit, if (len) strbuf_add(&ret->summary, subject, len); else - strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1)); + strbuf_addf(&ret->summary, "(%s)", oid_to_hex(&commit->object.oid)); unuse_commit_buffer(commit, message); } @@ -1733,7 +1733,7 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) printf("boundary\n"); if (suspect->previous) { struct origin *prev = suspect->previous; - printf("previous %s ", sha1_to_hex(prev->commit->object.sha1)); + printf("previous %s ", oid_to_hex(&prev->commit->object.oid)); write_name_quoted(prev->path, stdout, '\n'); } @@ -1752,7 +1752,7 @@ static void found_guilty_entry(struct blame_entry *ent) struct origin *suspect = ent->suspect; printf("%s %d %d %d\n", - sha1_to_hex(suspect->commit->object.sha1), + oid_to_hex(&suspect->commit->object.oid), ent->s_lno + 1, ent->lno + 1, ent->num_lines); emit_one_suspect_detail(suspect, 0); write_filename_info(suspect->path); @@ -1882,7 +1882,7 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent, struct origin *suspect = ent->suspect; char hex[GIT_SHA1_HEXSZ + 1]; - sha1_to_hex_r(hex, suspect->commit->object.sha1); + sha1_to_hex_r(hex, suspect->commit->object.oid.hash); printf("%s %d %d %d\n", hex, ent->s_lno + 1, @@ -1922,7 +1922,7 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP); get_commit_info(suspect->commit, &ci, 1); - sha1_to_hex_r(hex, suspect->commit->object.sha1); + sha1_to_hex_r(hex, suspect->commit->object.oid.hash); cp = nth_line(sb, ent->lno); for (cnt = 0; cnt < ent->num_lines; cnt++) { @@ -2077,7 +2077,7 @@ static int read_ancestry(const char *graft_file) static int update_auto_abbrev(int auto_abbrev, struct origin *suspect) { - const char *uniq = find_unique_abbrev(suspect->commit->object.sha1, + const char *uniq = find_unique_abbrev(suspect->commit->object.oid.hash, auto_abbrev); int len = strlen(uniq); if (auto_abbrev < len) @@ -2153,7 +2153,7 @@ static void sanity_check_refcnt(struct scoreboard *sb) if (ent->suspect->refcnt <= 0) { fprintf(stderr, "%s in %s has negative refcnt %d\n", ent->suspect->path, - sha1_to_hex(ent->suspect->commit->object.sha1), + oid_to_hex(&ent->suspect->commit->object.oid), ent->suspect->refcnt); baa = 1; } @@ -2216,7 +2216,7 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path) struct commit_list *parents; for (parents = work_tree->parents; parents; parents = parents->next) { - const unsigned char *commit_sha1 = parents->item->object.sha1; + const unsigned char *commit_sha1 = parents->item->object.oid.hash; unsigned char blob_sha1[20]; unsigned mode; @@ -2310,7 +2310,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n"); for (parent = commit->parents; parent; parent = parent->next) strbuf_addf(&msg, "parent %s\n", - sha1_to_hex(parent->item->object.sha1)); + oid_to_hex(&parent->item->object.oid)); strbuf_addf(&msg, "author %s\n" "committer %s\n\n" @@ -2402,16 +2402,13 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, return commit; } -static char *prepare_final(struct scoreboard *sb) +static struct commit *find_single_final(struct rev_info *revs, + const char **name_p) { int i; - const char *final_commit_name = NULL; - struct rev_info *revs = sb->revs; + struct commit *found = NULL; + const char *name = NULL; - /* - * There must be one and only one positive commit in the - * revs->pending array. - */ for (i = 0; i < revs->pending.nr; i++) { struct object *obj = revs->pending.objects[i].item; if (obj->flags & UNINTERESTING) @@ -2420,14 +2417,22 @@ static char *prepare_final(struct scoreboard *sb) obj = deref_tag(obj, NULL, 0); if (obj->type != OBJ_COMMIT) die("Non commit %s?", revs->pending.objects[i].name); - if (sb->final) + if (found) die("More than one commit to dig from %s and %s?", - revs->pending.objects[i].name, - final_commit_name); - sb->final = (struct commit *) obj; - final_commit_name = revs->pending.objects[i].name; + revs->pending.objects[i].name, name); + found = (struct commit *)obj; + name = revs->pending.objects[i].name; } - return xstrdup_or_null(final_commit_name); + if (name_p) + *name_p = name; + return found; +} + +static char *prepare_final(struct scoreboard *sb) +{ + const char *name; + sb->final = find_single_final(sb->revs, &name); + return xstrdup_or_null(name); } static char *prepare_initial(struct scoreboard *sb) @@ -2503,6 +2508,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) long dashdash_pos, lno; char *final_commit_name = NULL; enum object_type type; + struct commit *final_commit = NULL; static struct string_list range_list; static int output_option = 0, opt = 0; @@ -2691,12 +2697,12 @@ parse_done: sb.commits.compare = compare_commits_by_commit_date; } else if (contents_from) - die("--contents and --children do not blend well."); - else if (revs.first_parent_only) - die("combining --first-parent and --reverse is not supported"); + die("--contents and --reverse do not blend well."); else { final_commit_name = prepare_initial(&sb); sb.commits.compare = compare_commits_by_reverse_commit_date; + if (revs.first_parent_only) + revs.children.name = NULL; } if (!sb.final) { @@ -2713,6 +2719,12 @@ parse_done: else if (contents_from) die("Cannot use --contents with final commit object name"); + if (reverse && revs.first_parent_only) { + final_commit = find_single_final(sb.revs, NULL); + if (!final_commit) + die("--reverse and --first-parent together require specified latest commit"); + } + /* * If we have bottom, this will mark the ancestors of the * bottom commits we would reach while traversing as @@ -2721,7 +2733,26 @@ parse_done: if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); - if (is_null_sha1(sb.final->object.sha1)) { + if (reverse && revs.first_parent_only) { + struct commit *c = final_commit; + + sb.revs->children.name = "children"; + while (c->parents && + oidcmp(&c->object.oid, &sb.final->object.oid)) { + struct commit_list *l = xcalloc(1, sizeof(*l)); + + l->item = c; + if (add_decoration(&sb.revs->children, + &c->parents->item->object, l)) + die("BUG: not unique item in first-parent chain"); + c = c->parents->item; + } + + if (oidcmp(&c->object.oid, &sb.final->object.oid)) + die("--reverse --first-parent together require range along first-parent chain"); + } + + if (is_null_oid(&sb.final->object.oid)) { o = sb.final->util; sb.final_buf = xmemdupz(o->file.ptr, o->file.size); sb.final_buf_size = o->file.size; diff --git a/builtin/branch.c b/builtin/branch.c index 01f9530822..3f6c825db1 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -349,7 +349,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_array_item *item, fill_tracking_info(&stat, refname, filter->verbose > 1); strbuf_addf(out, " %s %s%s", - find_unique_abbrev(item->commit->object.sha1, filter->abbrev), + find_unique_abbrev(item->commit->object.oid.hash, filter->abbrev), stat.buf, sub); strbuf_release(&stat); strbuf_release(&subject); @@ -592,7 +592,7 @@ static int edit_branch_description(const char *branch_name) strbuf_release(&buf); return -1; } - stripspace(&buf, 1); + strbuf_stripspace(&buf, 1); strbuf_addf(&name, "branch.%s.description", branch_name); status = git_config_set(name.buf, buf.len ? buf.buf : NULL); diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 07baad1e59..c0fd8dbb1c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -426,7 +426,7 @@ static int batch_objects(struct batch_options *opt) static const char * const cat_file_usage[] = { N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv) <object>"), - N_("git cat-file (--batch | --batch-check) [--follow-symlinks] < <list-of-objects>"), + N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"), NULL }; diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 21d2bedcc9..265c9ba022 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -9,7 +9,7 @@ static int cached_attrs; static int stdin_paths; static const char * const check_attr_usage[] = { N_("git check-attr [-a | --all | <attr>...] [--] <pathname>..."), -N_("git check-attr --stdin [-z] [-a | --all | <attr>...] < <list-of-paths>"), +N_("git check-attr --stdin [-z] [-a | --all | <attr>...]"), NULL }; diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index dc8d97c56c..43f361797a 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -8,7 +8,7 @@ static int quiet, verbose, stdin_paths, show_non_matching, no_index; static const char * const check_ignore_usage[] = { "git check-ignore [<options>] <pathname>...", -"git check-ignore [<options>] --stdin < <list-of-paths>", +"git check-ignore [<options>] --stdin", NULL }; diff --git a/builtin/checkout.c b/builtin/checkout.c index bc703c0f5e..e8110a9243 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -37,6 +37,7 @@ struct checkout_opts { int overwrite_ignore; int ignore_skipworktree; int ignore_other_worktrees; + int show_progress; const char *new_branch; const char *new_branch_force; @@ -55,8 +56,8 @@ static int post_checkout_hook(struct commit *old, struct commit *new, int changed) { return run_hook_le(NULL, "post-checkout", - sha1_to_hex(old ? old->object.sha1 : null_sha1), - sha1_to_hex(new ? new->object.sha1 : null_sha1), + sha1_to_hex(old ? old->object.oid.hash : null_sha1), + sha1_to_hex(new ? new->object.oid.hash : null_sha1), changed ? "1" : "0", NULL); /* "new" can be NULL when checking out from the index before a commit exists. */ @@ -400,7 +401,7 @@ static void describe_detached_head(const char *msg, struct commit *commit) if (!parse_commit(commit)) pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb); fprintf(stderr, "%s %s... %s\n", msg, - find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV), sb.buf); + find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV), sb.buf); strbuf_release(&sb); } @@ -417,7 +418,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, opts.reset = 1; opts.merge = 1; opts.fn = oneway_merge; - opts.verbose_update = !o->quiet && isatty(2); + opts.verbose_update = o->show_progress; opts.src_index = &the_index; opts.dst_index = &the_index; parse_tree(tree); @@ -501,7 +502,7 @@ static int merge_working_tree(const struct checkout_opts *opts, topts.update = 1; topts.merge = 1; topts.gently = opts->merge && old->commit; - topts.verbose_update = !opts->quiet && isatty(2); + topts.verbose_update = opts->show_progress; topts.fn = twoway_merge; if (opts->overwrite_ignore) { topts.dir = xcalloc(1, sizeof(*topts.dir)); @@ -509,10 +510,10 @@ static int merge_working_tree(const struct checkout_opts *opts, setup_standard_excludes(topts.dir); } tree = parse_tree_indirect(old->commit ? - old->commit->object.sha1 : + old->commit->object.oid.hash : EMPTY_TREE_SHA1_BIN); init_tree_desc(&trees[0], tree->buffer, tree->size); - tree = parse_tree_indirect(new->commit->object.sha1); + tree = parse_tree_indirect(new->commit->object.oid.hash); init_tree_desc(&trees[1], tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); @@ -640,7 +641,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, old_desc = old->name; if (!old_desc && old->commit) - old_desc = sha1_to_hex(old->commit->object.sha1); + old_desc = oid_to_hex(&old->commit->object.oid); reflog_msg = getenv("GIT_REFLOG_ACTION"); if (!reflog_msg) @@ -652,7 +653,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) { /* Nothing to do. */ } else if (opts->force_detach || !new->path) { /* No longer on any branch. */ - update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL, + update_ref(msg.buf, "HEAD", new->commit->object.oid.hash, NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); if (!opts->quiet) { if (old->path && advice_detached_head) @@ -703,7 +704,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit) { strbuf_addstr(sb, " "); strbuf_addstr(sb, - find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); + find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV)); strbuf_addch(sb, ' '); if (!parse_commit(commit)) pp_commit_easy(CMIT_FMT_ONELINE, commit, sb); @@ -761,7 +762,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs) " git branch <new-branch-name> %s\n\n", /* Give ngettext() the count */ lost), - find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); + find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV)); } /* @@ -779,10 +780,10 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new) setup_revisions(0, NULL, &revs, NULL); object->flags &= ~UNINTERESTING; - add_pending_object(&revs, object, sha1_to_hex(object->sha1)); + add_pending_object(&revs, object, oid_to_hex(&object->oid)); for_each_ref(add_pending_uninteresting_ref, &revs); - add_pending_sha1(&revs, "HEAD", new->object.sha1, UNINTERESTING); + add_pending_sha1(&revs, "HEAD", new->object.oid.hash, UNINTERESTING); refs = revs.pending; revs.leak_pending = 1; @@ -1156,6 +1157,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) N_("second guess 'git checkout <no-such-branch>'")), OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees, N_("do not check if another worktree is holding the given ref")), + OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")), OPT_END(), }; @@ -1163,6 +1165,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) memset(&new, 0, sizeof(new)); opts.overwrite_ignore = 1; opts.prefix = prefix; + opts.show_progress = -1; gitmodules_config(); git_config(git_checkout_config, &opts); @@ -1172,6 +1175,13 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); + if (opts.show_progress < 0) { + if (opts.quiet) + opts.show_progress = 0; + else + opts.show_progress = isatty(2); + } + if (conflict_style) { opts.merge = 1; /* implied */ git_xmerge_config("merge.conflictstyle", conflict_style, NULL); diff --git a/builtin/clean.c b/builtin/clean.c index d7acb94a95..919157bc2f 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -147,30 +147,6 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset) return 0; } -/* - * Return 1 if the given path is the root of a git repository or - * submodule else 0. Will not return 1 for bare repositories with the - * exception of creating a bare repository in "foo/.git" and calling - * is_git_repository("foo"). - */ -static int is_git_repository(struct strbuf *path) -{ - int ret = 0; - int gitfile_error; - size_t orig_path_len = path->len; - assert(orig_path_len != 0); - strbuf_complete(path, '/'); - strbuf_addstr(path, ".git"); - if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf)) - ret = 1; - if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED || - gitfile_error == READ_GITFILE_ERR_READ_FAILED) - ret = 1; /* This could be a real .git file, take the - * safe option and avoid cleaning */ - strbuf_setlen(path, orig_path_len); - return ret; -} - static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, int dry_run, int quiet, int *dir_gone) { @@ -182,7 +158,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, *dir_gone = 1; - if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_git_repository(path)) { + if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) { if (!quiet) { quote_path_relative(path->buf, prefix, "ed); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), diff --git a/builtin/clone.c b/builtin/clone.c index 9eaecd9a7c..a0b3cd9e56 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -559,7 +559,7 @@ static void write_remote_refs(const struct ref *local_refs) for (r = local_refs; r; r = r->next) { if (!r->peer_ref) continue; - if (ref_transaction_create(t, r->peer_ref->name, r->old_sha1, + if (ref_transaction_create(t, r->peer_ref->name, r->old_oid.hash, 0, NULL, &err)) die("%s", err.buf); } @@ -579,9 +579,9 @@ static void write_followtags(const struct ref *refs, const char *msg) continue; if (ends_with(ref->name, "^{}")) continue; - if (!has_sha1_file(ref->old_sha1)) + if (!has_object_file(&ref->old_oid)) continue; - update_ref(msg, ref->name, ref->old_sha1, + update_ref(msg, ref->name, ref->old_oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); } } @@ -601,7 +601,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20]) if (!ref) return -1; - hashcpy(sha1, ref->old_sha1); + hashcpy(sha1, ref->old_oid.hash); *rm = ref->next; return 0; } @@ -650,14 +650,14 @@ static void update_head(const struct ref *our, const struct ref *remote, /* Local default branch link */ create_symref("HEAD", our->name, NULL); if (!option_bare) { - update_ref(msg, "HEAD", our->old_sha1, NULL, 0, + update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); install_branch_config(0, head, option_origin, our->name); } } else if (our) { - struct commit *c = lookup_commit_reference(our->old_sha1); + struct commit *c = lookup_commit_reference(our->old_oid.hash); /* --branch specifies a non-branch (i.e. tags), detach HEAD */ - update_ref(msg, "HEAD", c->object.sha1, + update_ref(msg, "HEAD", c->object.oid.hash, NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); } else if (remote) { /* @@ -665,7 +665,7 @@ static void update_head(const struct ref *our, const struct ref *remote, * HEAD points to a branch but we don't know which one. * Detach HEAD in all these cases. */ - update_ref(msg, "HEAD", remote->old_sha1, + update_ref(msg, "HEAD", remote->old_oid.hash, NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); } } @@ -801,11 +801,15 @@ static void write_refspec_config(const char *src_ref_prefix, static void dissociate_from_references(void) { static const char* argv[] = { "repack", "-a", "-d", NULL }; + char *alternates = git_pathdup("objects/info/alternates"); - if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN)) - die(_("cannot repack to clean up")); - if (unlink(git_path("objects/info/alternates")) && errno != ENOENT) - die_errno(_("cannot unlink temporary alternates file")); + if (!access(alternates, F_OK)) { + if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN)) + die(_("cannot repack to clean up")); + if (unlink(alternates) && errno != ENOENT) + die_errno(_("cannot unlink temporary alternates file")); + } + free(alternates); } int cmd_clone(int argc, const char **argv, const char *prefix) @@ -954,10 +958,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_reference.nr) setup_reference(); - else if (option_dissociate) { - warning(_("--dissociate given, but there is no --reference")); - option_dissociate = 0; - } fetch_pattern = value.buf; refspec = parse_fetch_refspec(1, &fetch_pattern); @@ -1016,7 +1016,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) * remote HEAD check. */ for (ref = refs; ref; ref = ref->next) - if (is_null_sha1(ref->old_sha1)) { + if (is_null_oid(&ref->old_oid)) { complete_refs_before_fetch = 0; break; } diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 25aa2cdef3..3feeffeab1 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -10,17 +10,17 @@ #include "utf8.h" #include "gpg-interface.h" -static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1> <changelog"; +static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>"; static const char *sign_commit; static void new_parent(struct commit *parent, struct commit_list **parents_p) { - unsigned char *sha1 = parent->object.sha1; + struct object_id *oid = &parent->object.oid; struct commit_list *parents; for (parents = *parents_p; parents; parents = parents->next) { if (parents->item == parent) { - error("duplicate parent %s ignored", sha1_to_hex(sha1)); + error("duplicate parent %s ignored", oid_to_hex(oid)); return; } parents_p = &parents->next; diff --git a/builtin/commit.c b/builtin/commit.c index 63772d016a..89bf6ad38a 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -32,6 +32,7 @@ #include "sequencer.h" #include "notes-utils.h" #include "mailmap.h" +#include "sigchain.h" static const char * const builtin_commit_usage[] = { N_("git commit [<options>] [--] <pathspec>..."), @@ -299,7 +300,7 @@ static void create_base_index(const struct commit *current_head) opts.dst_index = &the_index; opts.fn = oneway_merge; - tree = parse_tree_indirect(current_head->object.sha1); + tree = parse_tree_indirect(current_head->object.oid.hash); if (!tree) die(_("failed to unpack HEAD tree object")); parse_tree(tree); @@ -760,7 +761,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, hook_arg2 = ""; } - s->fp = fopen(git_path(commit_editmsg), "w"); + s->fp = fopen_for_writing(git_path(commit_editmsg)); if (s->fp == NULL) die_errno(_("could not open '%s'"), git_path(commit_editmsg)); @@ -775,7 +776,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->hints = 0; if (clean_message_contents) - stripspace(&sb, 0); + strbuf_stripspace(&sb, 0); if (signoff) append_signoff(&sb, ignore_non_trailer(&sb), 0); @@ -1014,7 +1015,7 @@ static int template_untouched(struct strbuf *sb) if (!template_file || strbuf_read_file(&tmpl, template_file, 0) <= 0) return 0; - stripspace(&tmpl, cleanup_mode == CLEANUP_ALL); + strbuf_stripspace(&tmpl, cleanup_mode == CLEANUP_ALL); if (!skip_prefix(sb->buf, tmpl.buf, &start)) start = sb->buf; strbuf_release(&tmpl); @@ -1537,8 +1538,10 @@ static int run_rewrite_hook(const unsigned char *oldsha1, return code; n = snprintf(buf, sizeof(buf), "%s %s\n", sha1_to_hex(oldsha1), sha1_to_hex(newsha1)); + sigchain_push(SIGPIPE, SIG_IGN); write_in_full(proc.in, buf, n); close(proc.in); + sigchain_pop(SIGPIPE); return finish_command(&proc); } @@ -1726,7 +1729,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) wt_status_truncate_message_at_cut_line(&sb); if (cleanup_mode != CLEANUP_NONE) - stripspace(&sb, cleanup_mode == CLEANUP_ALL); + strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL); if (template_untouched(&sb) && !allow_empty_message) { rollback_index_files(); fprintf(stderr, _("Aborting commit; you did not edit the message.\n")); @@ -1766,7 +1769,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (!transaction || ref_transaction_update(transaction, "HEAD", sha1, current_head - ? current_head->object.sha1 : null_sha1, + ? current_head->object.oid.hash : null_sha1, 0, sb.buf, &err) || ref_transaction_commit(transaction, &err)) { rollback_index_files(); @@ -1793,10 +1796,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix) cfg = init_copy_notes_for_rewrite("amend"); if (cfg) { /* we are amending, so current_head is not NULL */ - copy_note_for_rewrite(cfg, current_head->object.sha1, sha1); + copy_note_for_rewrite(cfg, current_head->object.oid.hash, sha1); finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'"); } - run_rewrite_hook(current_head->object.sha1, sha1); + run_rewrite_hook(current_head->object.oid.hash, sha1); } if (!quiet) print_summary(prefix, sha1, !current_head); diff --git a/builtin/count-objects.c b/builtin/count-objects.c index ad0c79954a..ba9291944f 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -15,9 +15,31 @@ static int verbose; static unsigned long loose, packed, packed_loose; static off_t loose_size; -static void real_report_garbage(const char *desc, const char *path) +static const char *bits_to_msg(unsigned seen_bits) +{ + switch (seen_bits) { + case 0: + return "no corresponding .idx or .pack"; + case PACKDIR_FILE_GARBAGE: + return "garbage found"; + case PACKDIR_FILE_PACK: + return "no corresponding .idx"; + case PACKDIR_FILE_IDX: + return "no corresponding .pack"; + case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX: + default: + return NULL; + } +} + +static void real_report_garbage(unsigned seen_bits, const char *path) { struct stat st; + const char *desc = bits_to_msg(seen_bits); + + if (!desc) + return; + if (!stat(path, &st)) size_garbage += st.st_size; warning("%s: %s", desc, path); @@ -27,7 +49,7 @@ static void real_report_garbage(const char *desc, const char *path) static void loose_garbage(const char *path) { if (verbose) - report_garbage("garbage found", path); + report_garbage(PACKDIR_FILE_GARBAGE, path); } static int count_loose(const unsigned char *sha1, const char *path, void *data) diff --git a/builtin/describe.c b/builtin/describe.c index 7df554326b..8a25abe0a0 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -252,14 +252,14 @@ static void describe(const char *arg, int last_one) if (!cmit) die(_("%s is not a valid '%s' object"), arg, commit_type); - n = find_commit_name(cmit->object.sha1); + n = find_commit_name(cmit->object.oid.hash); if (n && (tags || all || n->prio == 2)) { /* * Exact match to an existing ref. */ display_name(n); if (longformat) - show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1); + show_suffix(0, n->tag ? n->tag->tagged->oid.hash : sha1); if (dirty) printf("%s", dirty); printf("\n"); @@ -267,7 +267,7 @@ static void describe(const char *arg, int last_one) } if (!max_candidates) - die(_("no tag exactly matches '%s'"), sha1_to_hex(cmit->object.sha1)); + die(_("no tag exactly matches '%s'"), oid_to_hex(&cmit->object.oid)); if (debug) fprintf(stderr, _("searching to describe %s\n"), arg); @@ -317,7 +317,7 @@ static void describe(const char *arg, int last_one) if (annotated_cnt && !list) { if (debug) fprintf(stderr, _("finished search at %s\n"), - sha1_to_hex(c->object.sha1)); + oid_to_hex(&c->object.oid)); break; } while (parents) { @@ -334,9 +334,9 @@ static void describe(const char *arg, int last_one) } if (!match_cnt) { - const unsigned char *sha1 = cmit->object.sha1; + struct object_id *oid = &cmit->object.oid; if (always) { - printf("%s", find_unique_abbrev(sha1, abbrev)); + printf("%s", find_unique_abbrev(oid->hash, abbrev)); if (dirty) printf("%s", dirty); printf("\n"); @@ -345,11 +345,11 @@ static void describe(const char *arg, int last_one) if (unannotated_cnt) die(_("No annotated tags can describe '%s'.\n" "However, there were unannotated tags: try --tags."), - sha1_to_hex(sha1)); + oid_to_hex(oid)); else die(_("No tags can describe '%s'.\n" "Try --always, or create some tags."), - sha1_to_hex(sha1)); + oid_to_hex(oid)); } qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt); @@ -374,13 +374,13 @@ static void describe(const char *arg, int last_one) _("more than %i tags found; listed %i most recent\n" "gave up search at %s\n"), max_candidates, max_candidates, - sha1_to_hex(gave_up_on->object.sha1)); + oid_to_hex(&gave_up_on->object.oid)); } } display_name(all_matches[0].name); if (abbrev) - show_suffix(all_matches[0].depth, cmit->object.sha1); + show_suffix(all_matches[0].depth, cmit->object.oid.hash); if (dirty) printf("%s", dirty); printf("\n"); diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 12b683d021..2a12b81e06 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -49,9 +49,9 @@ static int stdin_diff_trees(struct tree *tree1, char *line, int len) tree2 = lookup_tree(sha1); if (!tree2 || parse_tree(tree2)) return -1; - printf("%s %s\n", sha1_to_hex(tree1->object.sha1), - sha1_to_hex(tree2->object.sha1)); - diff_tree_sha1(tree1->object.sha1, tree2->object.sha1, + printf("%s %s\n", oid_to_hex(&tree1->object.oid), + oid_to_hex(&tree2->object.oid)); + diff_tree_sha1(tree1->object.oid.hash, tree2->object.oid.hash, "", &log_tree_opt.diffopt); log_tree_diff_flush(&log_tree_opt); return 0; @@ -139,7 +139,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) break; case 1: tree1 = opt->pending.objects[0].item; - diff_tree_commit_sha1(tree1->sha1); + diff_tree_commit_sha1(tree1->oid.hash); break; case 2: tree1 = opt->pending.objects[0].item; @@ -149,8 +149,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) tree2 = tree1; tree1 = tmp; } - diff_tree_sha1(tree1->sha1, - tree2->sha1, + diff_tree_sha1(tree1->oid.hash, + tree2->oid.hash, "", &opt->diffopt); log_tree_diff_flush(opt); break; diff --git a/builtin/diff.c b/builtin/diff.c index 4326fa56bf..52c98a9217 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -175,8 +175,8 @@ static int builtin_diff_tree(struct rev_info *revs, */ if (ent1->item->flags & UNINTERESTING) swap = 1; - sha1[swap] = ent0->item->sha1; - sha1[1 - swap] = ent1->item->sha1; + sha1[swap] = ent0->item->oid.hash; + sha1[1 - swap] = ent1->item->oid.hash; diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt); log_tree_diff_flush(revs); return 0; @@ -196,8 +196,8 @@ static int builtin_diff_combined(struct rev_info *revs, if (!revs->dense_combined_merges && !revs->combine_merges) revs->dense_combined_merges = revs->combine_merges = 1; for (i = 1; i < ents; i++) - sha1_array_append(&parents, ent[i].item->sha1); - diff_tree_combined(ent[0].item->sha1, &parents, + sha1_array_append(&parents, ent[i].item->oid.hash); + diff_tree_combined(ent[0].item->oid.hash, &parents, revs->dense_combined_merges, revs); sha1_array_clear(&parents); return 0; @@ -341,7 +341,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } if (no_index) /* If this is a no-index diff, just run it and exit there. */ - diff_no_index(&rev, argc, argv, prefix); + diff_no_index(&rev, argc, argv); /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; @@ -395,7 +395,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) const char *name = entry->name; int flags = (obj->flags & UNINTERESTING); if (!obj->parsed) - obj = parse_object(obj->sha1); + obj = parse_object(obj->oid.hash); obj = deref_tag(obj, NULL, 0); if (!obj) die(_("invalid object '%s' given."), name); @@ -408,7 +408,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } else if (obj->type == OBJ_BLOB) { if (2 <= blobs) die(_("more than two blobs given: '%s'"), name); - hashcpy(blob[blobs].sha1, obj->sha1); + hashcpy(blob[blobs].sha1, obj->oid.hash); blob[blobs].name = name; blob[blobs].mode = entry->mode; blobs++; diff --git a/builtin/fast-export.c b/builtin/fast-export.c index d23f3beba9..2471297f71 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -544,13 +544,13 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) author = strstr(commit_buffer, "\nauthor "); if (!author) die ("Could not find author in commit %s", - sha1_to_hex(commit->object.sha1)); + oid_to_hex(&commit->object.oid)); author++; author_end = strchrnul(author, '\n'); committer = strstr(author_end, "\ncommitter "); if (!committer) die ("Could not find committer in commit %s", - sha1_to_hex(commit->object.sha1)); + oid_to_hex(&commit->object.oid)); committer++; committer_end = strchrnul(committer, '\n'); message = strstr(committer_end, "\n\n"); @@ -562,11 +562,11 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) get_object_mark(&commit->parents->item->object) != 0 && !full_tree) { parse_commit_or_die(commit->parents->item); - diff_tree_sha1(commit->parents->item->tree->object.sha1, - commit->tree->object.sha1, "", &rev->diffopt); + diff_tree_sha1(commit->parents->item->tree->object.oid.hash, + commit->tree->object.oid.hash, "", &rev->diffopt); } else - diff_root_tree_sha1(commit->tree->object.sha1, + diff_root_tree_sha1(commit->tree->object.oid.hash, "", &rev->diffopt); /* Export the referenced blobs, and remember the marks. */ @@ -661,13 +661,13 @@ static void handle_tag(const char *name, struct tag *tag) } if (tagged->type == OBJ_TREE) { warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); return; } - buf = read_sha1_file(tag->object.sha1, &type, &size); + buf = read_sha1_file(tag->object.oid.hash, &type, &size); if (!buf) - die ("Could not read tag %s", sha1_to_hex(tag->object.sha1)); + die ("Could not read tag %s", oid_to_hex(&tag->object.oid)); message = memmem(buf, size, "\n\n", 2); if (message) { message += 2; @@ -706,16 +706,16 @@ static void handle_tag(const char *name, struct tag *tag) case ABORT: die ("Encountered signed tag %s; use " "--signed-tags=<mode> to handle it.", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); case WARN: warning ("Exporting signed tag %s", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); /* fallthru */ case VERBATIM: break; case WARN_STRIP: warning ("Stripping signature from tag %s", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); /* fallthru */ case STRIP: message_size = signature + 1 - message; @@ -731,14 +731,14 @@ static void handle_tag(const char *name, struct tag *tag) case ABORT: die ("Tag %s tags unexported object; use " "--tag-of-filtered-object=<mode> to handle it.", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); case DROP: /* Ignore this tag altogether */ return; case REWRITE: if (tagged->type != OBJ_COMMIT) { die ("Tag %s tags unexported %s!", - sha1_to_hex(tag->object.sha1), + oid_to_hex(&tag->object.oid), typename(tagged->type)); } p = (struct commit *)tagged; @@ -751,7 +751,7 @@ static void handle_tag(const char *name, struct tag *tag) break; if (!p->parents) die ("Can't find replacement commit for tag %s\n", - sha1_to_hex(tag->object.sha1)); + oid_to_hex(&tag->object.oid)); p = p->parents->item; } tagged_mark = get_object_mark(&p->object); @@ -777,7 +777,7 @@ static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name) /* handle nested tags */ while (tag && tag->object.type == OBJ_TAG) { - parse_object(tag->object.sha1); + parse_object(tag->object.oid.hash); string_list_append(&extra_refs, full_name)->util = tag; tag = (struct tag *)tag->tagged; } @@ -828,7 +828,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) case OBJ_COMMIT: break; case OBJ_BLOB: - export_blob(commit->object.sha1); + export_blob(commit->object.oid.hash); continue; default: /* OBJ_TAG (nested tags) is already handled */ warning("Tag points to object of unexpected type %s, skipping.", @@ -880,7 +880,7 @@ static void export_marks(char *file) FILE *f; int e = 0; - f = fopen(file, "w"); + f = fopen_for_writing(file); if (!f) die_errno("Unable to open marks file %s for writing.", file); @@ -888,7 +888,7 @@ static void export_marks(char *file) if (deco->base && deco->base->type == 1) { mark = ptr_to_mark(deco->decoration); if (fprintf(f, ":%"PRIu32" %s\n", mark, - sha1_to_hex(deco->base->sha1)) < 0) { + oid_to_hex(&deco->base->oid)) < 0) { e = 1; break; } diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 4a6b340ab6..cf3019e05b 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -14,12 +14,14 @@ static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc, const char *name, int namelen) { struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1); - unsigned char sha1[20]; - - if (namelen > 41 && name[40] == ' ' && !get_sha1_hex(name, sha1)) { - hashcpy(ref->old_sha1, sha1); - name += 41; - namelen -= 41; + struct object_id oid; + const int chunksz = GIT_SHA1_HEXSZ + 1; + + if (namelen > chunksz && name[chunksz - 1] == ' ' && + !get_oid_hex(name, &oid)) { + oidcpy(&ref->old_oid, &oid); + name += chunksz; + namelen -= chunksz; } memcpy(ref->name, name, namelen); @@ -210,7 +212,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) while (ref) { printf("%s %s\n", - sha1_to_hex(ref->old_sha1), ref->name); + oid_to_hex(&ref->old_oid), ref->name); ref = ref->next; } diff --git a/builtin/fetch.c b/builtin/fetch.c index ed84963a57..17f40e10f6 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -196,7 +196,7 @@ static int will_fetch(struct ref **head, const unsigned char *sha1) { struct ref *rm = *head; while (rm) { - if (!hashcmp(rm->old_sha1, sha1)) + if (!hashcmp(rm->old_oid.hash, sha1)) return 1; rm = rm->next; } @@ -224,8 +224,8 @@ static void find_non_local_tags(struct transport *transport, * as one to ignore by setting util to NULL. */ if (ends_with(ref->name, "^{}")) { - if (item && !has_sha1_file(ref->old_sha1) && - !will_fetch(head, ref->old_sha1) && + if (item && !has_object_file(&ref->old_oid) && + !will_fetch(head, ref->old_oid.hash) && !has_sha1_file(item->util) && !will_fetch(head, item->util)) item->util = NULL; @@ -251,7 +251,7 @@ static void find_non_local_tags(struct transport *transport, continue; item = string_list_insert(&remote_refs, ref->name); - item->util = (void *)ref->old_sha1; + item->util = (void *)&ref->old_oid; } string_list_clear(&existing_refs, 1); @@ -273,7 +273,7 @@ static void find_non_local_tags(struct transport *transport, { struct ref *rm = alloc_ref(item->string); rm->peer_ref = alloc_ref(item->string); - hashcpy(rm->old_sha1, item->util); + oidcpy(&rm->old_oid, item->util); **tail = rm; *tail = &rm->next; } @@ -419,8 +419,8 @@ static int s_update_ref(const char *action, transaction = ref_transaction_begin(&err); if (!transaction || ref_transaction_update(transaction, ref->name, - ref->new_sha1, - check_old ? ref->old_sha1 : NULL, + ref->new_oid.hash, + check_old ? ref->old_oid.hash : NULL, 0, msg, &err)) goto fail; @@ -453,11 +453,11 @@ static int update_local_ref(struct ref *ref, struct branch *current_branch = branch_get(NULL); const char *pretty_ref = prettify_refname(ref->name); - type = sha1_object_info(ref->new_sha1, NULL); + type = sha1_object_info(ref->new_oid.hash, NULL); if (type < 0) - die(_("object %s not found"), sha1_to_hex(ref->new_sha1)); + die(_("object %s not found"), oid_to_hex(&ref->new_oid)); - if (!hashcmp(ref->old_sha1, ref->new_sha1)) { + if (!oidcmp(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) strbuf_addf(display, "= %-*s %-*s -> %s", TRANSPORT_SUMMARY(_("[up to date]")), @@ -468,7 +468,7 @@ static int update_local_ref(struct ref *ref, if (current_branch && !strcmp(ref->name, current_branch->name) && !(update_head_ok || is_bare_repository()) && - !is_null_sha1(ref->old_sha1)) { + !is_null_oid(&ref->old_oid)) { /* * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... @@ -480,7 +480,7 @@ static int update_local_ref(struct ref *ref, return 1; } - if (!is_null_sha1(ref->old_sha1) && + if (!is_null_oid(&ref->old_oid) && starts_with(ref->name, "refs/tags/")) { int r; r = s_update_ref("updating tag", ref, 0); @@ -492,8 +492,8 @@ static int update_local_ref(struct ref *ref, return r; } - current = lookup_commit_reference_gently(ref->old_sha1, 1); - updated = lookup_commit_reference_gently(ref->new_sha1, 1); + current = lookup_commit_reference_gently(ref->old_oid.hash, 1); + updated = lookup_commit_reference_gently(ref->new_oid.hash, 1); if (!current || !updated) { const char *msg; const char *what; @@ -517,7 +517,7 @@ static int update_local_ref(struct ref *ref, if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_sha1); + check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref(msg, ref, 0); strbuf_addf(display, "%c %-*s %-*s -> %s%s", r ? '!' : '*', @@ -530,12 +530,12 @@ static int update_local_ref(struct ref *ref, if (in_merge_bases(current, updated)) { struct strbuf quickref = STRBUF_INIT; int r; - strbuf_add_unique_abbrev(&quickref, current->object.sha1, DEFAULT_ABBREV); + strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV); strbuf_addstr(&quickref, ".."); - strbuf_add_unique_abbrev(&quickref, ref->new_sha1, DEFAULT_ABBREV); + strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV); if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_sha1); + check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref("fast-forward", ref, 1); strbuf_addf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ', @@ -547,12 +547,12 @@ static int update_local_ref(struct ref *ref, } else if (force || ref->force) { struct strbuf quickref = STRBUF_INIT; int r; - strbuf_add_unique_abbrev(&quickref, current->object.sha1, DEFAULT_ABBREV); + strbuf_add_unique_abbrev(&quickref, current->object.oid.hash, DEFAULT_ABBREV); strbuf_addstr(&quickref, "..."); - strbuf_add_unique_abbrev(&quickref, ref->new_sha1, DEFAULT_ABBREV); + strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV); if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_sha1); + check_for_new_submodule_commits(ref->new_oid.hash); r = s_update_ref("forced-update", ref, 1); strbuf_addf(display, "%c %-*s %-*s -> %s (%s)", r ? '!' : '+', @@ -580,7 +580,7 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20]) if (!ref) return -1; /* end of the list */ *rm = ref->next; - hashcpy(sha1, ref->old_sha1); + hashcpy(sha1, ref->old_oid.hash); return 0; } @@ -631,7 +631,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, continue; } - commit = lookup_commit_reference_gently(rm->old_sha1, 1); + commit = lookup_commit_reference_gently(rm->old_oid.hash, 1); if (!commit) rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE; @@ -640,8 +640,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, if (rm->peer_ref) { ref = alloc_ref(rm->peer_ref->name); - hashcpy(ref->old_sha1, rm->peer_ref->old_sha1); - hashcpy(ref->new_sha1, rm->old_sha1); + oidcpy(&ref->old_oid, &rm->peer_ref->old_oid); + oidcpy(&ref->new_oid, &rm->old_oid); ref->force = rm->peer_ref->force; } @@ -686,7 +686,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, /* fall-through */ case FETCH_HEAD_MERGE: fprintf(fp, "%s\t%s\t%s", - sha1_to_hex(rm->old_sha1), + oid_to_hex(&rm->old_oid), merge_status_marker, note.buf); for (i = 0; i < url_len; ++i) @@ -837,7 +837,7 @@ static void check_not_current_branch(struct ref *ref_map) static int truncate_fetch_head(void) { const char *filename = git_path_fetch_head(); - FILE *fp = fopen(filename, "w"); + FILE *fp = fopen_for_writing(filename); if (!fp) return error(_("cannot open %s: %s\n"), filename, strerror(errno)); @@ -928,7 +928,7 @@ static int do_fetch(struct transport *transport, rm->peer_ref->name); if (peer_item) { struct object_id *old_oid = peer_item->util; - hashcpy(rm->peer_ref->old_sha1, old_oid->hash); + oidcpy(&rm->peer_ref->old_oid, old_oid); } } } @@ -1221,6 +1221,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) list.strdup_strings = 1; string_list_clear(&list, 0); + close_all_packs(); + argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL); if (verbosity < 0) argv_array_push(&argv_gc_auto, "--quiet"); diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 4ba7f282a5..e5658c320e 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -378,7 +378,7 @@ static void shortlog(const char *name, if (!sb.len) string_list_append(&subjects, - sha1_to_hex(commit->object.sha1)); + oid_to_hex(&commit->object.oid)); else string_list_append(&subjects, strbuf_detach(&sb, NULL)); } @@ -537,7 +537,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out) static void find_merge_parents(struct merge_parents *result, struct strbuf *in, unsigned char *head) { - struct commit_list *parents, *next; + struct commit_list *parents; struct commit *head_commit; int pos = 0, i, j; @@ -568,7 +568,7 @@ static void find_merge_parents(struct merge_parents *result, if (!parent) continue; commit_list_insert(parent, &parents); - add_merge_parent(result, obj->sha1, parent->object.sha1); + add_merge_parent(result, obj->oid.hash, parent->object.oid.hash); } head_commit = lookup_commit(head); if (head_commit) @@ -576,13 +576,10 @@ static void find_merge_parents(struct merge_parents *result, parents = reduce_heads(parents); while (parents) { + struct commit *cmit = pop_commit(&parents); for (i = 0; i < result->nr; i++) - if (!hashcmp(result->item[i].commit, - parents->item->object.sha1)) + if (!hashcmp(result->item[i].commit, cmit->object.oid.hash)) result->item[i].used = 1; - next = parents->next; - free(parents); - parents = next; } for (i = j = 0; i < result->nr; i++) { diff --git a/builtin/fsck.c b/builtin/fsck.c index 8b8bb42c51..55eac756f7 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -67,7 +67,7 @@ static void objreport(struct object *obj, const char *msg_type, const char *err) { fprintf(stderr, "%s in %s %s: %s\n", - msg_type, typename(obj->type), sha1_to_hex(obj->sha1), err); + msg_type, typename(obj->type), oid_to_hex(&obj->oid), err); } static int objerror(struct object *obj, const char *err) @@ -97,7 +97,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", - typename(parent->type), sha1_to_hex(parent->sha1)); + typename(parent->type), oid_to_hex(&parent->oid)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : typename(type)), "unknown"); errors_found |= ERROR_REACHABLE; @@ -112,11 +112,11 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt return 0; obj->flags |= REACHABLE; if (!(obj->flags & HAS_OBJ)) { - if (parent && !has_sha1_file(obj->sha1)) { + if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", - typename(parent->type), sha1_to_hex(parent->sha1)); + typename(parent->type), oid_to_hex(&parent->oid)); printf(" to %7s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); + typename(obj->type), oid_to_hex(&obj->oid)); errors_found |= ERROR_REACHABLE; } return 1; @@ -186,11 +186,11 @@ static void check_reachable_object(struct object *obj) * do a full fsck */ if (!(obj->flags & HAS_OBJ)) { - if (has_sha1_pack(obj->sha1)) + if (has_sha1_pack(obj->oid.hash)) return; /* it is in pack - forget about it */ - if (connectivity_only && has_sha1_file(obj->sha1)) + if (connectivity_only && has_object_file(&obj->oid)) return; - printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + printf("missing %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); errors_found |= ERROR_REACHABLE; return; } @@ -215,7 +215,7 @@ static void check_unreachable_object(struct object *obj) * since this is something that is prunable. */ if (show_unreachable) { - printf("unreachable %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); + printf("unreachable %s %s\n", typename(obj->type), oid_to_hex(&obj->oid)); return; } @@ -234,11 +234,11 @@ static void check_unreachable_object(struct object *obj) if (!obj->used) { if (show_dangling) printf("dangling %s %s\n", typename(obj->type), - sha1_to_hex(obj->sha1)); + oid_to_hex(&obj->oid)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", - sha1_to_hex(obj->sha1)); + oid_to_hex(&obj->oid)); FILE *f; if (safe_create_leading_directories_const(filename)) { @@ -249,10 +249,10 @@ static void check_unreachable_object(struct object *obj) if (!(f = fopen(filename, "w"))) die_errno("Could not open '%s'", filename); if (obj->type == OBJ_BLOB) { - if (stream_blob_to_fd(fileno(f), obj->sha1, NULL, 1)) + if (stream_blob_to_fd(fileno(f), obj->oid.hash, NULL, 1)) die_errno("Could not write '%s'", filename); } else - fprintf(f, "%s\n", sha1_to_hex(obj->sha1)); + fprintf(f, "%s\n", oid_to_hex(&obj->oid)); if (fclose(f)) die_errno("Could not finish '%s'", filename); @@ -271,7 +271,7 @@ static void check_unreachable_object(struct object *obj) static void check_object(struct object *obj) { if (verbose) - fprintf(stderr, "Checking %s\n", sha1_to_hex(obj->sha1)); + fprintf(stderr, "Checking %s\n", oid_to_hex(&obj->oid)); if (obj->flags & REACHABLE) check_reachable_object(obj); @@ -307,7 +307,7 @@ static int fsck_obj(struct object *obj) if (verbose) fprintf(stderr, "Checking %s %s\n", - typename(obj->type), sha1_to_hex(obj->sha1)); + typename(obj->type), oid_to_hex(&obj->oid)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); @@ -326,15 +326,15 @@ static int fsck_obj(struct object *obj) free_commit_buffer(commit); if (!commit->parents && show_root) - printf("root %s\n", sha1_to_hex(commit->object.sha1)); + printf("root %s\n", oid_to_hex(&commit->object.oid)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { - printf("tagged %s %s", typename(tag->tagged->type), sha1_to_hex(tag->tagged->sha1)); - printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1)); + printf("tagged %s %s", typename(tag->tagged->type), oid_to_hex(&tag->tagged->oid)); + printf(" (%s) in %s\n", tag->tag, oid_to_hex(&tag->object.oid)); } } diff --git a/builtin/gc.c b/builtin/gc.c index eeeb21b1c4..c583aad6ec 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -46,6 +46,22 @@ static struct argv_array rerere = ARGV_ARRAY_INIT; static struct tempfile pidfile; static struct lock_file log_lock; +static struct string_list pack_garbage = STRING_LIST_INIT_DUP; + +static void clean_pack_garbage(void) +{ + int i; + for (i = 0; i < pack_garbage.nr; i++) + unlink_or_warn(pack_garbage.items[i].string); + string_list_clear(&pack_garbage, 0); +} + +static void report_pack_garbage(unsigned seen_bits, const char *path) +{ + if (seen_bits == PACKDIR_FILE_IDX) + string_list_append(&pack_garbage, path); +} + static void git_config_date_string(const char *key, const char **output) { if (git_config_get_string_const(key, output)) @@ -240,7 +256,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) * running. */ time(NULL) - st.st_mtime <= 12 * 3600 && - fscanf(fp, "%"PRIuMAX" %127c", &pid, locking_host) == 2 && + fscanf(fp, "%"SCNuMAX" %127c", &pid, locking_host) == 2 && /* be gentle to concurrent "gc" on remote hosts */ (strcmp(locking_host, my_host) || !kill(pid, 0) || errno == EPERM); if (fp != NULL) @@ -394,15 +410,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (gc_before_repack()) return -1; - if (run_command_v_opt(repack.argv, RUN_GIT_CMD)) - return error(FAILED_RUN, repack.argv[0]); + if (!repository_format_precious_objects) { + if (run_command_v_opt(repack.argv, RUN_GIT_CMD)) + return error(FAILED_RUN, repack.argv[0]); - if (prune_expire) { - argv_array_push(&prune, prune_expire); - if (quiet) - argv_array_push(&prune, "--no-progress"); - if (run_command_v_opt(prune.argv, RUN_GIT_CMD)) - return error(FAILED_RUN, prune.argv[0]); + if (prune_expire) { + argv_array_push(&prune, prune_expire); + if (quiet) + argv_array_push(&prune, "--no-progress"); + if (run_command_v_opt(prune.argv, RUN_GIT_CMD)) + return error(FAILED_RUN, prune.argv[0]); + } } if (prune_worktrees_expire) { @@ -414,6 +432,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (run_command_v_opt(rerere.argv, RUN_GIT_CMD)) return error(FAILED_RUN, rerere.argv[0]); + report_garbage = report_pack_garbage; + reprepare_packed_git(); + if (pack_garbage.nr > 0) + clean_pack_garbage(); + if (auto_gc && too_many_loose_objects()) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index 6f4147ad02..e21c5416cd 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -8,7 +8,7 @@ #include "quote.h" static const char builtin_get_tar_commit_id_usage[] = -"git get-tar-commit-id < <tarfile>"; +"git get-tar-commit-id"; /* ustar header + extended global header content */ #define RECORDSIZE (512) diff --git a/builtin/grep.c b/builtin/grep.c index d04f4400d9..4229cae390 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -459,7 +459,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, struct object *obj, const char *name, const char *path) { if (obj->type == OBJ_BLOB) - return grep_sha1(opt, obj->sha1, name, 0, path); + return grep_sha1(opt, obj->oid.hash, name, 0, path); if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) { struct tree_desc tree; void *data; @@ -468,12 +468,12 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, int hit, len; grep_read_lock(); - data = read_object_with_reference(obj->sha1, tree_type, + data = read_object_with_reference(obj->oid.hash, tree_type, &size, NULL); grep_read_unlock(); if (!data) - die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1)); + die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); len = name ? strlen(name) : 0; strbuf_init(&base, PATH_MAX + len + 1); @@ -612,11 +612,6 @@ static int pattern_callback(const struct option *opt, const char *arg, return 0; } -static int help_callback(const struct option *opt, const char *arg, int unset) -{ - return -1; -} - int cmd_grep(int argc, const char **argv, const char *prefix) { int hit = 0; @@ -738,18 +733,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix) PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager }, OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored, N_("allow calling of grep(1) (ignored by this build)")), - { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"), - PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback }, OPT_END() }; - /* - * 'git grep -h', unlike 'git grep -h <pattern>', is a request - * to show usage information and exit. - */ - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(grep_usage, options); - init_grep_defaults(); git_config(grep_cmd_config, NULL); grep_init(&opt, prefix); @@ -766,8 +752,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) */ argc = parse_options(argc, argv, prefix, options, grep_usage, PARSE_OPT_KEEP_DASHDASH | - PARSE_OPT_STOP_AT_NON_OPTION | - PARSE_OPT_NO_INTERNAL_HELP); + PARSE_OPT_STOP_AT_NON_OPTION); grep_commit_pattern_type(pattern_type_arg, &opt); if (use_index && !startup_info->have_repository) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 07fef3cc6b..43b098b76c 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -78,7 +78,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) { static const char * const hash_object_usage[] = { N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."), - N_("git hash-object --stdin-paths < <list-of-paths>"), + N_("git hash-object --stdin-paths"), NULL }; const char *type = blob_type; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 1ad1bde696..6a01509587 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -199,7 +199,7 @@ static int mark_link(struct object *obj, int type, void *data, struct fsck_optio return -1; if (type != OBJ_ANY && obj->type != type) - die(_("object type mismatch at %s"), sha1_to_hex(obj->sha1)); + die(_("object type mismatch at %s"), oid_to_hex(&obj->oid)); obj->flags |= FLAG_LINK; return 0; @@ -217,13 +217,13 @@ static unsigned check_object(struct object *obj) if (!(obj->flags & FLAG_CHECKED)) { unsigned long size; - int type = sha1_object_info(obj->sha1, &size); + int type = sha1_object_info(obj->oid.hash, &size); if (type <= 0) die(_("did not receive expected object %s"), - sha1_to_hex(obj->sha1)); + oid_to_hex(&obj->oid)); if (type != obj->type) die(_("object %s: expected type %s, found %s"), - sha1_to_hex(obj->sha1), + oid_to_hex(&obj->oid), typename(obj->type), typename(type)); obj->flags |= FLAG_CHECKED; return 1; @@ -842,7 +842,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, fsck_object(obj, buf, size, &fsck_options)) die(_("Error in object")); if (fsck_walk(obj, NULL, &fsck_options)) - die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1)); + die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid)); if (obj->type == OBJ_TREE) { struct tree *item = (struct tree *) obj; diff --git a/builtin/init-db.c b/builtin/init-db.c index f59f40768e..07229d60f1 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -24,18 +24,6 @@ static int init_shared_repository = -1; static const char *init_db_template_dir; static const char *git_link; -static void safe_create_dir(const char *dir, int share) -{ - if (mkdir(dir, 0777) < 0) { - if (errno != EEXIST) { - perror(dir); - exit(1); - } - } - else if (share && adjust_shared_perm(dir)) - die(_("Could not make %s writable by group"), dir); -} - static void copy_templates_1(struct strbuf *path, struct strbuf *template, DIR *dir) { diff --git a/builtin/log.c b/builtin/log.c index dda671d975..e00cea75cc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -552,7 +552,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) const char *name = objects[i].name; switch (o->type) { case OBJ_BLOB: - ret = show_blob_object(o->sha1, &rev, name); + ret = show_blob_object(o->oid.hash, &rev, name); break; case OBJ_TAG: { struct tag *t = (struct tag *)o; @@ -563,14 +563,14 @@ int cmd_show(int argc, const char **argv, const char *prefix) diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, diff_get_color_opt(&rev.diffopt, DIFF_RESET)); - ret = show_tag_object(o->sha1, &rev); + ret = show_tag_object(o->oid.hash, &rev); rev.shown_one = 1; if (ret) break; - o = parse_object(t->tagged->sha1); + o = parse_object(t->tagged->oid.hash); if (!o) ret = error(_("Could not read object %s"), - sha1_to_hex(t->tagged->sha1)); + oid_to_hex(&t->tagged->oid)); objects[i].item = o; i--; break; @@ -830,8 +830,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids) o2 = rev->pending.objects[1].item; flags1 = o1->flags; flags2 = o2->flags; - c1 = lookup_commit_reference(o1->sha1); - c2 = lookup_commit_reference(o2->sha1); + c1 = lookup_commit_reference(o1->oid.hash); + c2 = lookup_commit_reference(o2->oid.hash); if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die(_("Not a range.")); @@ -896,8 +896,8 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name) static char *find_branch_name(struct rev_info *rev) { int i, positive = -1; - unsigned char branch_sha1[20]; - const unsigned char *tip_sha1; + struct object_id branch_oid; + const struct object_id *tip_oid; const char *ref, *v; char *full_ref, *branch = NULL; @@ -912,10 +912,10 @@ static char *find_branch_name(struct rev_info *rev) if (positive < 0) return NULL; ref = rev->cmdline.rev[positive].name; - tip_sha1 = rev->cmdline.rev[positive].item->sha1; - if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) && + tip_oid = &rev->cmdline.rev[positive].item->oid; + if (dwim_ref(ref, strlen(ref), branch_oid.hash, &full_ref) && skip_prefix(full_ref, "refs/heads/", &v) && - !hashcmp(tip_sha1, branch_sha1)) + !oidcmp(tip_oid, &branch_oid)) branch = xstrdup(v); free(full_ref); return branch; @@ -993,8 +993,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, diff_setup_done(&opts); - diff_tree_sha1(origin->tree->object.sha1, - head->tree->object.sha1, + diff_tree_sha1(origin->tree->object.oid.hash, + head->tree->object.oid.hash, "", &opts); diffcore_std(&opts); diff_flush(&opts); @@ -1196,6 +1196,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int cover_letter = -1; int boundary_count = 0; int no_binary_diff = 0; + int zero_commit = 0; struct commit *origin = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -1236,6 +1237,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback }, OPT_BOOL(0, "no-binary", &no_binary_diff, N_("don't output binary diffs")), + OPT_BOOL(0, "zero-commit", &zero_commit, + N_("output all-zero hash in From header")), OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream, N_("don't include a patch matching a commit upstream")), { OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL, @@ -1380,6 +1383,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Always generate a patch */ rev.diffopt.output_format |= DIFF_FORMAT_PATCH; + rev.zero_commit = zero_commit; + if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff) DIFF_OPT_SET(&rev.diffopt, BINARY); @@ -1443,7 +1448,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* Don't say anything if head and upstream are the same. */ if (rev.pending.nr == 2) { struct object_array_entry *o = rev.pending.objects; - if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0) + if (oidcmp(&o[0].item->oid, &o[1].item->oid) == 0) return 0; } get_patch_ids(&rev, &ids); @@ -1550,7 +1555,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) string_list_append(rev.ref_message_ids, rev.message_id); } - gen_message_id(&rev, sha1_to_hex(commit->object.sha1)); + gen_message_id(&rev, oid_to_hex(&commit->object.oid)); } if (!use_stdout && @@ -1612,12 +1617,12 @@ static void print_commit(char sign, struct commit *commit, int verbose, { if (!verbose) { printf("%c %s\n", sign, - find_unique_abbrev(commit->object.sha1, abbrev)); + find_unique_abbrev(commit->object.oid.hash, abbrev)); } else { struct strbuf buf = STRBUF_INIT; pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf); printf("%c %s %s\n", sign, - find_unique_abbrev(commit->object.sha1, abbrev), + find_unique_abbrev(commit->object.oid.hash, abbrev), buf.buf); strbuf_release(&buf); } @@ -1675,7 +1680,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) /* Don't say anything if head and upstream are the same. */ if (revs.pending.nr == 2) { struct object_array_entry *o = revs.pending.objects; - if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0) + if (oidcmp(&o[0].item->oid, &o[1].item->oid) == 0) return 0; } diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index a31024900b..fa65a8448a 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -125,7 +125,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) continue; if (!tail_match(pattern, ref->name)) continue; - printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); + printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); status = 0; /* we found something */ } return status; diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 999a5250fb..f6df274111 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -6,1029 +6,7 @@ #include "builtin.h" #include "utf8.h" #include "strbuf.h" - -static FILE *cmitmsg, *patchfile, *fin, *fout; - -static int keep_subject; -static int keep_non_patch_brackets_in_subject; -static const char *metainfo_charset; -static struct strbuf line = STRBUF_INIT; -static struct strbuf name = STRBUF_INIT; -static struct strbuf email = STRBUF_INIT; -static char *message_id; - -static enum { - TE_DONTCARE, TE_QP, TE_BASE64 -} transfer_encoding; - -static struct strbuf charset = STRBUF_INIT; -static int patch_lines; -static struct strbuf **p_hdr_data, **s_hdr_data; -static int use_scissors; -static int add_message_id; -static int use_inbody_headers = 1; - -#define MAX_HDR_PARSED 10 -#define MAX_BOUNDARIES 5 - -static void cleanup_space(struct strbuf *sb); - - -static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email) -{ - struct strbuf *src = name; - if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') || - strchr(name->buf, '<') || strchr(name->buf, '>')) - src = email; - else if (name == out) - return; - strbuf_reset(out); - strbuf_addbuf(out, src); -} - -static void parse_bogus_from(const struct strbuf *line) -{ - /* John Doe <johndoe> */ - - char *bra, *ket; - /* This is fallback, so do not bother if we already have an - * e-mail address. - */ - if (email.len) - return; - - bra = strchr(line->buf, '<'); - if (!bra) - return; - ket = strchr(bra, '>'); - if (!ket) - return; - - strbuf_reset(&email); - strbuf_add(&email, bra + 1, ket - bra - 1); - - strbuf_reset(&name); - strbuf_add(&name, line->buf, bra - line->buf); - strbuf_trim(&name); - get_sane_name(&name, &name, &email); -} - -static void handle_from(const struct strbuf *from) -{ - char *at; - size_t el; - struct strbuf f; - - strbuf_init(&f, from->len); - strbuf_addbuf(&f, from); - - at = strchr(f.buf, '@'); - if (!at) { - parse_bogus_from(from); - return; - } - - /* - * If we already have one email, don't take any confusing lines - */ - if (email.len && strchr(at + 1, '@')) { - strbuf_release(&f); - return; - } - - /* Pick up the string around '@', possibly delimited with <> - * pair; that is the email part. - */ - while (at > f.buf) { - char c = at[-1]; - if (isspace(c)) - break; - if (c == '<') { - at[-1] = ' '; - break; - } - at--; - } - el = strcspn(at, " \n\t\r\v\f>"); - strbuf_reset(&email); - strbuf_add(&email, at, el); - strbuf_remove(&f, at - f.buf, el + (at[el] ? 1 : 0)); - - /* The remainder is name. It could be - * - * - "John Doe <john.doe@xz>" (a), or - * - "john.doe@xz (John Doe)" (b), or - * - "John (zzz) Doe <john.doe@xz> (Comment)" (c) - * - * but we have removed the email part, so - * - * - remove extra spaces which could stay after email (case 'c'), and - * - trim from both ends, possibly removing the () pair at the end - * (cases 'a' and 'b'). - */ - cleanup_space(&f); - strbuf_trim(&f); - if (f.buf[0] == '(' && f.len && f.buf[f.len - 1] == ')') { - strbuf_remove(&f, 0, 1); - strbuf_setlen(&f, f.len - 1); - } - - get_sane_name(&name, &f, &email); - strbuf_release(&f); -} - -static void handle_header(struct strbuf **out, const struct strbuf *line) -{ - if (!*out) { - *out = xmalloc(sizeof(struct strbuf)); - strbuf_init(*out, line->len); - } else - strbuf_reset(*out); - - strbuf_addbuf(*out, line); -} - -/* NOTE NOTE NOTE. We do not claim we do full MIME. We just attempt - * to have enough heuristics to grok MIME encoded patches often found - * on our mailing lists. For example, we do not even treat header lines - * case insensitively. - */ - -static int slurp_attr(const char *line, const char *name, struct strbuf *attr) -{ - const char *ends, *ap = strcasestr(line, name); - size_t sz; - - strbuf_setlen(attr, 0); - if (!ap) - return 0; - ap += strlen(name); - if (*ap == '"') { - ap++; - ends = "\""; - } - else - ends = "; \t"; - sz = strcspn(ap, ends); - strbuf_add(attr, ap, sz); - return 1; -} - -static struct strbuf *content[MAX_BOUNDARIES]; - -static struct strbuf **content_top = content; - -static void handle_content_type(struct strbuf *line) -{ - struct strbuf *boundary = xmalloc(sizeof(struct strbuf)); - strbuf_init(boundary, line->len); - - if (slurp_attr(line->buf, "boundary=", boundary)) { - strbuf_insert(boundary, 0, "--", 2); - if (++content_top > &content[MAX_BOUNDARIES]) { - fprintf(stderr, "Too many boundaries to handle\n"); - exit(1); - } - *content_top = boundary; - boundary = NULL; - } - slurp_attr(line->buf, "charset=", &charset); - - if (boundary) { - strbuf_release(boundary); - free(boundary); - } -} - -static void handle_message_id(const struct strbuf *line) -{ - if (add_message_id) - message_id = strdup(line->buf); -} - -static void handle_content_transfer_encoding(const struct strbuf *line) -{ - if (strcasestr(line->buf, "base64")) - transfer_encoding = TE_BASE64; - else if (strcasestr(line->buf, "quoted-printable")) - transfer_encoding = TE_QP; - else - transfer_encoding = TE_DONTCARE; -} - -static int is_multipart_boundary(const struct strbuf *line) -{ - return (((*content_top)->len <= line->len) && - !memcmp(line->buf, (*content_top)->buf, (*content_top)->len)); -} - -static void cleanup_subject(struct strbuf *subject) -{ - size_t at = 0; - - while (at < subject->len) { - char *pos; - size_t remove; - - switch (subject->buf[at]) { - case 'r': case 'R': - if (subject->len <= at + 3) - break; - if ((subject->buf[at + 1] == 'e' || - subject->buf[at + 1] == 'E') && - subject->buf[at + 2] == ':') { - strbuf_remove(subject, at, 3); - continue; - } - at++; - break; - case ' ': case '\t': case ':': - strbuf_remove(subject, at, 1); - continue; - case '[': - pos = strchr(subject->buf + at, ']'); - if (!pos) - break; - remove = pos - subject->buf + at + 1; - if (!keep_non_patch_brackets_in_subject || - (7 <= remove && - memmem(subject->buf + at, remove, "PATCH", 5))) - strbuf_remove(subject, at, remove); - else { - at += remove; - /* - * If the input had a space after the ], keep - * it. We don't bother with finding the end of - * the space, since we later normalize it - * anyway. - */ - if (isspace(subject->buf[at])) - at += 1; - } - continue; - } - break; - } - strbuf_trim(subject); -} - -static void cleanup_space(struct strbuf *sb) -{ - size_t pos, cnt; - for (pos = 0; pos < sb->len; pos++) { - if (isspace(sb->buf[pos])) { - sb->buf[pos] = ' '; - for (cnt = 0; isspace(sb->buf[pos + cnt + 1]); cnt++); - strbuf_remove(sb, pos + 1, cnt); - } - } -} - -static void decode_header(struct strbuf *line); -static const char *header[MAX_HDR_PARSED] = { - "From","Subject","Date", -}; - -static inline int cmp_header(const struct strbuf *line, const char *hdr) -{ - int len = strlen(hdr); - return !strncasecmp(line->buf, hdr, len) && line->len > len && - line->buf[len] == ':' && isspace(line->buf[len + 1]); -} - -static int is_format_patch_separator(const char *line, int len) -{ - static const char SAMPLE[] = - "From e6807f3efca28b30decfecb1732a56c7db1137ee Mon Sep 17 00:00:00 2001\n"; - const char *cp; - - if (len != strlen(SAMPLE)) - return 0; - if (!skip_prefix(line, "From ", &cp)) - return 0; - if (strspn(cp, "0123456789abcdef") != 40) - return 0; - cp += 40; - return !memcmp(SAMPLE + (cp - line), cp, strlen(SAMPLE) - (cp - line)); -} - -static int check_header(const struct strbuf *line, - struct strbuf *hdr_data[], int overwrite) -{ - int i, ret = 0, len; - struct strbuf sb = STRBUF_INIT; - /* search for the interesting parts */ - for (i = 0; header[i]; i++) { - int len = strlen(header[i]); - if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) { - /* Unwrap inline B and Q encoding, and optionally - * normalize the meta information to utf8. - */ - strbuf_add(&sb, line->buf + len + 2, line->len - len - 2); - decode_header(&sb); - handle_header(&hdr_data[i], &sb); - ret = 1; - goto check_header_out; - } - } - - /* Content stuff */ - if (cmp_header(line, "Content-Type")) { - len = strlen("Content-Type: "); - strbuf_add(&sb, line->buf + len, line->len - len); - decode_header(&sb); - strbuf_insert(&sb, 0, "Content-Type: ", len); - handle_content_type(&sb); - ret = 1; - goto check_header_out; - } - if (cmp_header(line, "Content-Transfer-Encoding")) { - len = strlen("Content-Transfer-Encoding: "); - strbuf_add(&sb, line->buf + len, line->len - len); - decode_header(&sb); - handle_content_transfer_encoding(&sb); - ret = 1; - goto check_header_out; - } - if (cmp_header(line, "Message-Id")) { - len = strlen("Message-Id: "); - strbuf_add(&sb, line->buf + len, line->len - len); - decode_header(&sb); - handle_message_id(&sb); - ret = 1; - goto check_header_out; - } - - /* for inbody stuff */ - if (starts_with(line->buf, ">From") && isspace(line->buf[5])) { - ret = is_format_patch_separator(line->buf + 1, line->len - 1); - goto check_header_out; - } - if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { - for (i = 0; header[i]; i++) { - if (!strcmp("Subject", header[i])) { - handle_header(&hdr_data[i], line); - ret = 1; - goto check_header_out; - } - } - } - -check_header_out: - strbuf_release(&sb); - return ret; -} - -static int is_rfc2822_header(const struct strbuf *line) -{ - /* - * The section that defines the loosest possible - * field name is "3.6.8 Optional fields". - * - * optional-field = field-name ":" unstructured CRLF - * field-name = 1*ftext - * ftext = %d33-57 / %59-126 - */ - int ch; - char *cp = line->buf; - - /* Count mbox From headers as headers */ - if (starts_with(cp, "From ") || starts_with(cp, ">From ")) - return 1; - - while ((ch = *cp++)) { - if (ch == ':') - return 1; - if ((33 <= ch && ch <= 57) || - (59 <= ch && ch <= 126)) - continue; - break; - } - return 0; -} - -static int read_one_header_line(struct strbuf *line, FILE *in) -{ - /* Get the first part of the line. */ - if (strbuf_getline(line, in, '\n')) - return 0; - - /* - * Is it an empty line or not a valid rfc2822 header? - * If so, stop here, and return false ("not a header") - */ - strbuf_rtrim(line); - if (!line->len || !is_rfc2822_header(line)) { - /* Re-add the newline */ - strbuf_addch(line, '\n'); - return 0; - } - - /* - * Now we need to eat all the continuation lines.. - * Yuck, 2822 header "folding" - */ - for (;;) { - int peek; - struct strbuf continuation = STRBUF_INIT; - - peek = fgetc(in); ungetc(peek, in); - if (peek != ' ' && peek != '\t') - break; - if (strbuf_getline(&continuation, in, '\n')) - break; - continuation.buf[0] = ' '; - strbuf_rtrim(&continuation); - strbuf_addbuf(line, &continuation); - } - - return 1; -} - -static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) -{ - const char *in = q_seg->buf; - int c; - struct strbuf *out = xmalloc(sizeof(struct strbuf)); - strbuf_init(out, q_seg->len); - - while ((c = *in++) != 0) { - if (c == '=') { - int d = *in++; - if (d == '\n' || !d) - break; /* drop trailing newline */ - strbuf_addch(out, (hexval(d) << 4) | hexval(*in++)); - continue; - } - if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */ - c = 0x20; - strbuf_addch(out, c); - } - return out; -} - -static struct strbuf *decode_b_segment(const struct strbuf *b_seg) -{ - /* Decode in..ep, possibly in-place to ot */ - int c, pos = 0, acc = 0; - const char *in = b_seg->buf; - struct strbuf *out = xmalloc(sizeof(struct strbuf)); - strbuf_init(out, b_seg->len); - - while ((c = *in++) != 0) { - if (c == '+') - c = 62; - else if (c == '/') - c = 63; - else if ('A' <= c && c <= 'Z') - c -= 'A'; - else if ('a' <= c && c <= 'z') - c -= 'a' - 26; - else if ('0' <= c && c <= '9') - c -= '0' - 52; - else - continue; /* garbage */ - switch (pos++) { - case 0: - acc = (c << 2); - break; - case 1: - strbuf_addch(out, (acc | (c >> 4))); - acc = (c & 15) << 4; - break; - case 2: - strbuf_addch(out, (acc | (c >> 2))); - acc = (c & 3) << 6; - break; - case 3: - strbuf_addch(out, (acc | c)); - acc = pos = 0; - break; - } - } - return out; -} - -static void convert_to_utf8(struct strbuf *line, const char *charset) -{ - char *out; - - if (!charset || !*charset) - return; - - if (same_encoding(metainfo_charset, charset)) - return; - out = reencode_string(line->buf, metainfo_charset, charset); - if (!out) - die("cannot convert from %s to %s", - charset, metainfo_charset); - strbuf_attach(line, out, strlen(out), strlen(out)); -} - -static int decode_header_bq(struct strbuf *it) -{ - char *in, *ep, *cp; - struct strbuf outbuf = STRBUF_INIT, *dec; - struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT; - int rfc2047 = 0; - - in = it->buf; - while (in - it->buf <= it->len && (ep = strstr(in, "=?")) != NULL) { - int encoding; - strbuf_reset(&charset_q); - strbuf_reset(&piecebuf); - rfc2047 = 1; - - if (in != ep) { - /* - * We are about to process an encoded-word - * that begins at ep, but there is something - * before the encoded word. - */ - char *scan; - for (scan = in; scan < ep; scan++) - if (!isspace(*scan)) - break; - - if (scan != ep || in == it->buf) { - /* - * We should not lose that "something", - * unless we have just processed an - * encoded-word, and there is only LWS - * before the one we are about to process. - */ - strbuf_add(&outbuf, in, ep - in); - } - } - /* E.g. - * ep : "=?iso-2022-jp?B?GyR...?= foo" - * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz" - */ - ep += 2; - - if (ep - it->buf >= it->len || !(cp = strchr(ep, '?'))) - goto decode_header_bq_out; - - if (cp + 3 - it->buf > it->len) - goto decode_header_bq_out; - strbuf_add(&charset_q, ep, cp - ep); - - encoding = cp[1]; - if (!encoding || cp[2] != '?') - goto decode_header_bq_out; - ep = strstr(cp + 3, "?="); - if (!ep) - goto decode_header_bq_out; - strbuf_add(&piecebuf, cp + 3, ep - cp - 3); - switch (tolower(encoding)) { - default: - goto decode_header_bq_out; - case 'b': - dec = decode_b_segment(&piecebuf); - break; - case 'q': - dec = decode_q_segment(&piecebuf, 1); - break; - } - if (metainfo_charset) - convert_to_utf8(dec, charset_q.buf); - - strbuf_addbuf(&outbuf, dec); - strbuf_release(dec); - free(dec); - in = ep + 2; - } - strbuf_addstr(&outbuf, in); - strbuf_reset(it); - strbuf_addbuf(it, &outbuf); -decode_header_bq_out: - strbuf_release(&outbuf); - strbuf_release(&charset_q); - strbuf_release(&piecebuf); - return rfc2047; -} - -static void decode_header(struct strbuf *it) -{ - if (decode_header_bq(it)) - return; - /* otherwise "it" is a straight copy of the input. - * This can be binary guck but there is no charset specified. - */ - if (metainfo_charset) - convert_to_utf8(it, ""); -} - -static void decode_transfer_encoding(struct strbuf *line) -{ - struct strbuf *ret; - - switch (transfer_encoding) { - case TE_QP: - ret = decode_q_segment(line, 0); - break; - case TE_BASE64: - ret = decode_b_segment(line); - break; - case TE_DONTCARE: - default: - return; - } - strbuf_reset(line); - strbuf_addbuf(line, ret); - strbuf_release(ret); - free(ret); -} - -static void handle_filter(struct strbuf *line); - -static int find_boundary(void) -{ - while (!strbuf_getline(&line, fin, '\n')) { - if (*content_top && is_multipart_boundary(&line)) - return 1; - } - return 0; -} - -static int handle_boundary(void) -{ - struct strbuf newline = STRBUF_INIT; - - strbuf_addch(&newline, '\n'); -again: - if (line.len >= (*content_top)->len + 2 && - !memcmp(line.buf + (*content_top)->len, "--", 2)) { - /* we hit an end boundary */ - /* pop the current boundary off the stack */ - strbuf_release(*content_top); - free(*content_top); - *content_top = NULL; - - /* technically won't happen as is_multipart_boundary() - will fail first. But just in case.. - */ - if (--content_top < content) { - fprintf(stderr, "Detected mismatched boundaries, " - "can't recover\n"); - exit(1); - } - handle_filter(&newline); - strbuf_release(&newline); - - /* skip to the next boundary */ - if (!find_boundary()) - return 0; - goto again; - } - - /* set some defaults */ - transfer_encoding = TE_DONTCARE; - strbuf_reset(&charset); - - /* slurp in this section's info */ - while (read_one_header_line(&line, fin)) - check_header(&line, p_hdr_data, 0); - - strbuf_release(&newline); - /* replenish line */ - if (strbuf_getline(&line, fin, '\n')) - return 0; - strbuf_addch(&line, '\n'); - return 1; -} - -static inline int patchbreak(const struct strbuf *line) -{ - size_t i; - - /* Beginning of a "diff -" header? */ - if (starts_with(line->buf, "diff -")) - return 1; - - /* CVS "Index: " line? */ - if (starts_with(line->buf, "Index: ")) - return 1; - - /* - * "--- <filename>" starts patches without headers - * "---<sp>*" is a manual separator - */ - if (line->len < 4) - return 0; - - if (starts_with(line->buf, "---")) { - /* space followed by a filename? */ - if (line->buf[3] == ' ' && !isspace(line->buf[4])) - return 1; - /* Just whitespace? */ - for (i = 3; i < line->len; i++) { - unsigned char c = line->buf[i]; - if (c == '\n') - return 1; - if (!isspace(c)) - break; - } - return 0; - } - return 0; -} - -static int is_scissors_line(const struct strbuf *line) -{ - size_t i, len = line->len; - int scissors = 0, gap = 0; - int first_nonblank = -1; - int last_nonblank = 0, visible, perforation = 0, in_perforation = 0; - const char *buf = line->buf; - - for (i = 0; i < len; i++) { - if (isspace(buf[i])) { - if (in_perforation) { - perforation++; - gap++; - } - continue; - } - last_nonblank = i; - if (first_nonblank < 0) - first_nonblank = i; - if (buf[i] == '-') { - in_perforation = 1; - perforation++; - continue; - } - if (i + 1 < len && - (!memcmp(buf + i, ">8", 2) || !memcmp(buf + i, "8<", 2) || - !memcmp(buf + i, ">%", 2) || !memcmp(buf + i, "%<", 2))) { - in_perforation = 1; - perforation += 2; - scissors += 2; - i++; - continue; - } - in_perforation = 0; - } - - /* - * The mark must be at least 8 bytes long (e.g. "-- >8 --"). - * Even though there can be arbitrary cruft on the same line - * (e.g. "cut here"), in order to avoid misidentification, the - * perforation must occupy more than a third of the visible - * width of the line, and dashes and scissors must occupy more - * than half of the perforation. - */ - - visible = last_nonblank - first_nonblank + 1; - return (scissors && 8 <= visible && - visible < perforation * 3 && - gap * 2 < perforation); -} - -static int handle_commit_msg(struct strbuf *line) -{ - static int still_looking = 1; - - if (!cmitmsg) - return 0; - - if (still_looking) { - if (!line->len || (line->len == 1 && line->buf[0] == '\n')) - return 0; - } - - if (use_inbody_headers && still_looking) { - still_looking = check_header(line, s_hdr_data, 0); - if (still_looking) - return 0; - } else - /* Only trim the first (blank) line of the commit message - * when ignoring in-body headers. - */ - still_looking = 0; - - /* normalize the log message to UTF-8. */ - if (metainfo_charset) - convert_to_utf8(line, charset.buf); - - if (use_scissors && is_scissors_line(line)) { - int i; - if (fseek(cmitmsg, 0L, SEEK_SET)) - die_errno("Could not rewind output message file"); - if (ftruncate(fileno(cmitmsg), 0)) - die_errno("Could not truncate output message file at scissors"); - still_looking = 1; - - /* - * We may have already read "secondary headers"; purge - * them to give ourselves a clean restart. - */ - for (i = 0; header[i]; i++) { - if (s_hdr_data[i]) - strbuf_release(s_hdr_data[i]); - s_hdr_data[i] = NULL; - } - return 0; - } - - if (patchbreak(line)) { - if (message_id) - fprintf(cmitmsg, "Message-Id: %s\n", message_id); - fclose(cmitmsg); - cmitmsg = NULL; - return 1; - } - - fputs(line->buf, cmitmsg); - return 0; -} - -static void handle_patch(const struct strbuf *line) -{ - fwrite(line->buf, 1, line->len, patchfile); - patch_lines++; -} - -static void handle_filter(struct strbuf *line) -{ - static int filter = 0; - - /* filter tells us which part we left off on */ - switch (filter) { - case 0: - if (!handle_commit_msg(line)) - break; - filter++; - case 1: - handle_patch(line); - break; - } -} - -static void handle_body(void) -{ - struct strbuf prev = STRBUF_INIT; - - /* Skip up to the first boundary */ - if (*content_top) { - if (!find_boundary()) - goto handle_body_out; - } - - do { - /* process any boundary lines */ - if (*content_top && is_multipart_boundary(&line)) { - /* flush any leftover */ - if (prev.len) { - handle_filter(&prev); - strbuf_reset(&prev); - } - if (!handle_boundary()) - goto handle_body_out; - } - - /* Unwrap transfer encoding */ - decode_transfer_encoding(&line); - - switch (transfer_encoding) { - case TE_BASE64: - case TE_QP: - { - struct strbuf **lines, **it, *sb; - - /* Prepend any previous partial lines */ - strbuf_insert(&line, 0, prev.buf, prev.len); - strbuf_reset(&prev); - - /* - * This is a decoded line that may contain - * multiple new lines. Pass only one chunk - * at a time to handle_filter() - */ - lines = strbuf_split(&line, '\n'); - for (it = lines; (sb = *it); it++) { - if (*(it + 1) == NULL) /* The last line */ - if (sb->buf[sb->len - 1] != '\n') { - /* Partial line, save it for later. */ - strbuf_addbuf(&prev, sb); - break; - } - handle_filter(sb); - } - /* - * The partial chunk is saved in "prev" and will be - * appended by the next iteration of read_line_with_nul(). - */ - strbuf_list_free(lines); - break; - } - default: - handle_filter(&line); - } - - } while (!strbuf_getwholeline(&line, fin, '\n')); - -handle_body_out: - strbuf_release(&prev); -} - -static void output_header_lines(FILE *fout, const char *hdr, const struct strbuf *data) -{ - const char *sp = data->buf; - while (1) { - char *ep = strchr(sp, '\n'); - int len; - if (!ep) - len = strlen(sp); - else - len = ep - sp; - fprintf(fout, "%s: %.*s\n", hdr, len, sp); - if (!ep) - break; - sp = ep + 1; - } -} - -static void handle_info(void) -{ - struct strbuf *hdr; - int i; - - for (i = 0; header[i]; i++) { - /* only print inbody headers if we output a patch file */ - if (patch_lines && s_hdr_data[i]) - hdr = s_hdr_data[i]; - else if (p_hdr_data[i]) - hdr = p_hdr_data[i]; - else - continue; - - if (!strcmp(header[i], "Subject")) { - if (!keep_subject) { - cleanup_subject(hdr); - cleanup_space(hdr); - } - output_header_lines(fout, "Subject", hdr); - } else if (!strcmp(header[i], "From")) { - cleanup_space(hdr); - handle_from(hdr); - fprintf(fout, "Author: %s\n", name.buf); - fprintf(fout, "Email: %s\n", email.buf); - } else { - cleanup_space(hdr); - fprintf(fout, "%s: %s\n", header[i], hdr->buf); - } - } - fprintf(fout, "\n"); -} - -static int mailinfo(FILE *in, FILE *out, const char *msg, const char *patch) -{ - int peek; - fin = in; - fout = out; - - cmitmsg = fopen(msg, "w"); - if (!cmitmsg) { - perror(msg); - return -1; - } - patchfile = fopen(patch, "w"); - if (!patchfile) { - perror(patch); - fclose(cmitmsg); - return -1; - } - - p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*p_hdr_data)); - s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*s_hdr_data)); - - do { - peek = fgetc(in); - } while (isspace(peek)); - ungetc(peek, in); - - /* process the email header */ - while (read_one_header_line(&line, fin)) - check_header(&line, p_hdr_data, 1); - - handle_body(); - handle_info(); - - return 0; -} - -static int git_mailinfo_config(const char *var, const char *value, void *unused) -{ - if (!starts_with(var, "mailinfo.")) - return git_default_config(var, value, unused); - if (!strcmp(var, "mailinfo.scissors")) { - use_scissors = git_config_bool(var, value); - return 0; - } - /* perhaps others here */ - return 0; -} +#include "mailinfo.h" static const char mailinfo_usage[] = "git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info"; @@ -1036,34 +14,36 @@ static const char mailinfo_usage[] = int cmd_mailinfo(int argc, const char **argv, const char *prefix) { const char *def_charset; + struct mailinfo mi; + int status; /* NEEDSWORK: might want to do the optional .git/ directory * discovery */ - git_config(git_mailinfo_config, NULL); + setup_mailinfo(&mi); def_charset = get_commit_output_encoding(); - metainfo_charset = def_charset; + mi.metainfo_charset = def_charset; while (1 < argc && argv[1][0] == '-') { if (!strcmp(argv[1], "-k")) - keep_subject = 1; + mi.keep_subject = 1; else if (!strcmp(argv[1], "-b")) - keep_non_patch_brackets_in_subject = 1; + mi.keep_non_patch_brackets_in_subject = 1; else if (!strcmp(argv[1], "-m") || !strcmp(argv[1], "--message-id")) - add_message_id = 1; + mi.add_message_id = 1; else if (!strcmp(argv[1], "-u")) - metainfo_charset = def_charset; + mi.metainfo_charset = def_charset; else if (!strcmp(argv[1], "-n")) - metainfo_charset = NULL; + mi.metainfo_charset = NULL; else if (starts_with(argv[1], "--encoding=")) - metainfo_charset = argv[1] + 11; + mi.metainfo_charset = argv[1] + 11; else if (!strcmp(argv[1], "--scissors")) - use_scissors = 1; + mi.use_scissors = 1; else if (!strcmp(argv[1], "--no-scissors")) - use_scissors = 0; + mi.use_scissors = 0; else if (!strcmp(argv[1], "--no-inbody-headers")) - use_inbody_headers = 0; + mi.use_inbody_headers = 0; else usage(mailinfo_usage); argc--; argv++; @@ -1072,5 +52,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) if (argc != 3) usage(mailinfo_usage); - return !!mailinfo(stdin, stdout, argv[1], argv[2]); + mi.input = stdin; + mi.output = stdout; + status = !!mailinfo(&mi, argv[1], argv[2]); + clear_mailinfo(&mi); + + return status; } diff --git a/builtin/merge-base.c b/builtin/merge-base.c index 08a8217890..a8911626c2 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -16,7 +16,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all) return 1; while (result) { - printf("%s\n", sha1_to_hex(result->item->object.sha1)); + printf("%s\n", oid_to_hex(&result->item->object.oid)); if (!show_all) return 0; result = result->next; @@ -62,7 +62,7 @@ static int handle_independent(int count, const char **args) return 1; while (result) { - printf("%s\n", sha1_to_hex(result->item->object.sha1)); + printf("%s\n", oid_to_hex(&result->item->object.oid)); result = result->next; } return 0; @@ -83,7 +83,7 @@ static int handle_octopus(int count, const char **args, int show_all) return 1; while (result) { - printf("%s\n", sha1_to_hex(result->item->object.sha1)); + printf("%s\n", oid_to_hex(&result->item->object.oid)); if (!show_all) return 0; result = result->next; @@ -196,7 +196,7 @@ static int handle_fork_point(int argc, const char **argv) goto cleanup_return; } - printf("%s\n", sha1_to_hex(bases->item->object.sha1)); + printf("%s\n", oid_to_hex(&bases->item->object.oid)); cleanup_return: free_commit_list(bases); diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 50d0bc873b..55447053f2 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -104,5 +104,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) free(result.ptr); } + if (ret > 127) + ret = 127; + return ret; } diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 2a4aafec6a..d4f0cbd451 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -60,7 +60,7 @@ static void *result(struct merge_list *entry, unsigned long *size) const char *path = entry->path; if (!entry->stage) - return read_sha1_file(entry->blob->object.sha1, &type, size); + return read_sha1_file(entry->blob->object.oid.hash, &type, size); base = NULL; if (entry->stage == 1) { base = entry->blob; @@ -82,7 +82,7 @@ static void *origin(struct merge_list *entry, unsigned long *size) enum object_type type; while (entry) { if (entry->stage == 2) - return read_sha1_file(entry->blob->object.sha1, &type, size); + return read_sha1_file(entry->blob->object.oid.hash, &type, size); entry = entry->link; } return NULL; @@ -130,7 +130,7 @@ static void show_result_list(struct merge_list *entry) do { struct merge_list *link = entry->link; static const char *desc[4] = { "result", "base", "our", "their" }; - printf(" %-6s %o %s %s\n", desc[entry->stage], entry->mode, sha1_to_hex(entry->blob->object.sha1), entry->path); + printf(" %-6s %o %s %s\n", desc[entry->stage], entry->mode, oid_to_hex(&entry->blob->object.oid), entry->path); entry = link; } while (entry); } diff --git a/builtin/merge.c b/builtin/merge.c index a0a9328292..b98a3489bf 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -365,7 +365,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", - sha1_to_hex(commit->object.sha1)); + oid_to_hex(&commit->object.oid)); pretty_print_commit(&ctx, commit, &out); } if (write_in_full(fd, out.buf, out.len) != out.len) @@ -380,7 +380,7 @@ static void finish(struct commit *head_commit, const unsigned char *new_head, const char *msg) { struct strbuf reflog_message = STRBUF_INIT; - const unsigned char *head = head_commit->object.sha1; + const unsigned char *head = head_commit->object.oid.hash; if (!msg) strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION")); @@ -404,6 +404,7 @@ static void finish(struct commit *head_commit, * We ignore errors in 'gc --auto', since the * user should see them. */ + close_all_packs(); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); } } @@ -497,7 +498,7 @@ static void merge_name(const char *remote, struct strbuf *msg) if (ref_exists(truname.buf)) { strbuf_addf(msg, "%s\t\tbranch '%s'%s of .\n", - sha1_to_hex(remote_head->object.sha1), + sha1_to_hex(remote_head->object.oid.hash), truname.buf + 11, (early ? " (early part)" : "")); strbuf_release(&truname); @@ -511,7 +512,7 @@ static void merge_name(const char *remote, struct strbuf *msg) desc = merge_remote_util(remote_head); if (desc && desc->obj && desc->obj->type == OBJ_TAG) { strbuf_addf(msg, "%s\t\t%s '%s'\n", - sha1_to_hex(desc->obj->sha1), + sha1_to_hex(desc->obj->oid.hash), typename(desc->obj->type), remote); goto cleanup; @@ -519,7 +520,7 @@ static void merge_name(const char *remote, struct strbuf *msg) } strbuf_addf(msg, "%s\t\tcommit '%s'\n", - sha1_to_hex(remote_head->object.sha1), remote); + sha1_to_hex(remote_head->object.oid.hash), remote); cleanup: strbuf_release(&buf); strbuf_release(&bname); @@ -806,7 +807,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) abort_commit(remoteheads, NULL); } read_merge_msg(&msg); - stripspace(&msg, 0 < option_edit); + strbuf_stripspace(&msg, 0 < option_edit); if (!msg.len) abort_commit(remoteheads, _("Empty commit message.")); strbuf_release(&merge_msg); @@ -892,7 +893,7 @@ static struct commit *is_old_style_invocation(int argc, const char **argv, second_token = lookup_commit_reference_gently(second_sha1, 0); if (!second_token) die(_("'%s' is not a commit"), argv[1]); - if (hashcmp(second_token->object.sha1, head)) + if (hashcmp(second_token->object.oid.hash, head)) return NULL; } return second_token; @@ -958,14 +959,14 @@ static void write_merge_state(struct commit_list *remoteheads) struct strbuf buf = STRBUF_INIT; for (j = remoteheads; j; j = j->next) { - unsigned const char *sha1; + struct object_id *oid; struct commit *c = j->item; if (c->util && merge_remote_util(c)->obj) { - sha1 = merge_remote_util(c)->obj->sha1; + oid = &merge_remote_util(c)->obj->oid; } else { - sha1 = c->object.sha1; + oid = &c->object.oid; } - strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1)); + strbuf_addf(&buf, "%s\n", oid_to_hex(oid)); } filename = git_path_merge_head(); fd = open(filename, O_WRONLY | O_CREAT, 0666); @@ -1019,7 +1020,7 @@ static struct commit_list *reduce_parents(struct commit *head_commit, int *head_subsumed, struct commit_list *remoteheads) { - struct commit_list *parents, *next, **remotes = &remoteheads; + struct commit_list *parents, **remotes; /* * Is the current HEAD reachable from another commit being @@ -1033,16 +1034,14 @@ static struct commit_list *reduce_parents(struct commit *head_commit, /* Find what parents to record by checking independent ones. */ parents = reduce_heads(remoteheads); - for (remoteheads = NULL, remotes = &remoteheads; - parents; - parents = next) { - struct commit *commit = parents->item; - next = parents->next; + remoteheads = NULL; + remotes = &remoteheads; + while (parents) { + struct commit *commit = pop_commit(&parents); if (commit == head_commit) *head_subsumed = 0; else remotes = &commit_list_insert(commit, remotes)->next; - free(parents); } return remoteheads; } @@ -1276,8 +1275,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix) die(_("%s - not something we can merge"), argv[0]); if (remoteheads->next) die(_("Can merge only exactly one commit into empty head")); - read_empty(remote_head->object.sha1, 0); - update_ref("initial pull", "HEAD", remote_head->object.sha1, + read_empty(remote_head->object.oid.hash, 0); + update_ref("initial pull", "HEAD", remote_head->object.oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); goto done; } @@ -1291,7 +1290,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * additional safety measure to check for it. */ if (!have_message && - is_old_style_invocation(argc, argv, head_commit->object.sha1)) { + is_old_style_invocation(argc, argv, head_commit->object.oid.hash)) { warning("old-style 'git merge <msg> HEAD <commit>' is deprecated."); strbuf_addstr(&merge_msg, argv[0]); head_arg = argv[1]; @@ -1325,7 +1324,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) check_commit_signature(commit, &signature_check); - find_unique_abbrev_r(hex, commit->object.sha1, DEFAULT_ABBREV); + find_unique_abbrev_r(hex, commit->object.oid.hash, DEFAULT_ABBREV); switch (signature_check.result) { case 'G': break; @@ -1355,7 +1354,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) for (p = remoteheads; p; p = p->next) { struct commit *commit = p->item; strbuf_addf(&buf, "GITHEAD_%s", - sha1_to_hex(commit->object.sha1)); + sha1_to_hex(commit->object.oid.hash)); setenv(buf.buf, merge_remote_util(commit)->name, 1); strbuf_reset(&buf); if (fast_forward != FF_ONLY && @@ -1395,7 +1394,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) free(list); } - update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1, + update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); if (remoteheads && !common) @@ -1411,16 +1410,16 @@ int cmd_merge(int argc, const char **argv, const char *prefix) goto done; } else if (fast_forward != FF_NO && !remoteheads->next && !common->next && - !hashcmp(common->item->object.sha1, head_commit->object.sha1)) { + !hashcmp(common->item->object.oid.hash, head_commit->object.oid.hash)) { /* Again the most common case of merging one remote. */ struct strbuf msg = STRBUF_INIT; struct commit *commit; if (verbosity >= 0) { char from[GIT_SHA1_HEXSZ + 1], to[GIT_SHA1_HEXSZ + 1]; - find_unique_abbrev_r(from, head_commit->object.sha1, + find_unique_abbrev_r(from, head_commit->object.oid.hash, DEFAULT_ABBREV); - find_unique_abbrev_r(to, remoteheads->item->object.sha1, + find_unique_abbrev_r(to, remoteheads->item->object.oid.hash, DEFAULT_ABBREV); printf(_("Updating %s..%s\n"), from, to); } @@ -1434,14 +1433,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix) goto done; } - if (checkout_fast_forward(head_commit->object.sha1, - commit->object.sha1, + if (checkout_fast_forward(head_commit->object.oid.hash, + commit->object.oid.hash, overwrite_ignore)) { ret = 1; goto done; } - finish(head_commit, remoteheads, commit->object.sha1, msg.buf); + finish(head_commit, remoteheads, commit->object.oid.hash, msg.buf); drop_save(); goto done; } else if (!remoteheads->next && common->next) @@ -1460,9 +1459,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) /* See if it is really trivial. */ git_committer_info(IDENT_STRICT); printf(_("Trying really trivial in-index merge...\n")); - if (!read_tree_trivial(common->item->object.sha1, - head_commit->object.sha1, - remoteheads->item->object.sha1)) { + if (!read_tree_trivial(common->item->object.oid.hash, + head_commit->object.oid.hash, + remoteheads->item->object.oid.hash)) { ret = merge_trivial(head_commit, remoteheads); goto done; } @@ -1485,8 +1484,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * HEAD^^" would be missed. */ common_one = get_merge_bases(head_commit, j->item); - if (hashcmp(common_one->item->object.sha1, - j->item->object.sha1)) { + if (hashcmp(common_one->item->object.oid.hash, + j->item->object.oid.hash)) { up_to_date = 0; break; } @@ -1522,7 +1521,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) int ret; if (i) { printf(_("Rewinding the tree to pristine...\n")); - restore_state(head_commit->object.sha1, stash); + restore_state(head_commit->object.oid.hash, stash); } if (use_strategies_nr != 1) printf(_("Trying merge strategy %s...\n"), @@ -1588,7 +1587,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * it up. */ if (!best_strategy) { - restore_state(head_commit->object.sha1, stash); + restore_state(head_commit->object.oid.hash, stash); if (use_strategies_nr > 1) fprintf(stderr, _("No merge strategy handled the merge.\n")); @@ -1601,7 +1600,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) ; /* We already have its result in the working tree. */ else { printf(_("Rewinding the tree to pristine...\n")); - restore_state(head_commit->object.sha1, stash); + restore_state(head_commit->object.oid.hash, stash); printf(_("Using the %s to prepare resolving by hand.\n"), best_strategy); try_merge_strategy(best_strategy, common, remoteheads, diff --git a/builtin/mktag.c b/builtin/mktag.c index 640ab64f41..031b750f06 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -154,7 +154,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix) unsigned char result_sha1[20]; if (argc != 1) - usage("git mktag < signaturefile"); + usage("git mktag"); if (strbuf_read(&buf, 0, 4096) < 0) { die_errno("could not read from stdin"); diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 0377fc1142..092e03c3cc 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -162,7 +162,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo struct tag *t = (struct tag *) o; if (!t->tagged) break; /* broken repository */ - o = parse_object(t->tagged->sha1); + o = parse_object(t->tagged->oid.hash); deref = 1; } if (o && o->type == OBJ_COMMIT) { @@ -193,7 +193,7 @@ static const char *get_exact_ref_match(const struct object *o) tip_table.sorted = 1; } - found = sha1_pos(o->sha1, tip_table.table, tip_table.nr, + found = sha1_pos(o->oid.hash, tip_table.table, tip_table.nr, nth_tip_table_ent); if (0 <= found) return tip_table.table[found].refname; @@ -232,19 +232,19 @@ static void show_name(const struct object *obj, int always, int allow_undefined, int name_only) { const char *name; - const unsigned char *sha1 = obj->sha1; + const struct object_id *oid = &obj->oid; if (!name_only) - printf("%s ", caller_name ? caller_name : sha1_to_hex(sha1)); + printf("%s ", caller_name ? caller_name : oid_to_hex(oid)); name = get_rev_name(obj); if (name) printf("%s\n", name); else if (allow_undefined) printf("undefined\n"); else if (always) - printf("%s\n", find_unique_abbrev(sha1, DEFAULT_ABBREV)); + printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV)); else - die("cannot describe '%s'", sha1_to_hex(sha1)); + die("cannot describe '%s'", oid_to_hex(oid)); } static char const * const name_rev_usage[] = { diff --git a/builtin/notes.c b/builtin/notes.c index 13c0af9155..52aa9af74b 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -192,7 +192,7 @@ static void prepare_note_data(const unsigned char *object, struct note_data *d, if (launch_editor(d->edit_path, &d->buf, NULL)) { die(_("Please supply the note contents using either -m or -F option")); } - stripspace(&d->buf, 1); + strbuf_stripspace(&d->buf, 1); } } @@ -215,7 +215,7 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) if (d->buf.len) strbuf_addch(&d->buf, '\n'); strbuf_addstr(&d->buf, arg); - stripspace(&d->buf, 0); + strbuf_stripspace(&d->buf, 0); d->given = 1; return 0; @@ -232,7 +232,7 @@ static int parse_file_arg(const struct option *opt, const char *arg, int unset) die_errno(_("cannot read '%s'"), arg); } else if (strbuf_read_file(&d->buf, arg, 1024) < 0) die_errno(_("could not open or read '%s'"), arg); - stripspace(&d->buf, 0); + strbuf_stripspace(&d->buf, 0); d->given = 1; return 0; @@ -707,7 +707,7 @@ static int merge_commit(struct notes_merge_options *o) die("Could not parse commit from NOTES_MERGE_PARTIAL."); if (partial->parents) - hashcpy(parent_sha1, partial->parents->item->object.sha1); + hashcpy(parent_sha1, partial->parents->item->object.oid.hash); else hashclr(parent_sha1); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 1c63f8f28c..4dae5b11c2 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2277,7 +2277,7 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, void *data) { - add_object_entry(commit->object.sha1, OBJ_COMMIT, NULL, 0); + add_object_entry(commit->object.oid.hash, OBJ_COMMIT, NULL, 0); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) @@ -2291,7 +2291,7 @@ static void show_object(struct object *obj, char *name = path_name(path, last); add_preferred_base_object(name); - add_object_entry(obj->sha1, obj->type, name, 0); + add_object_entry(obj->oid.hash, obj->type, name, 0); obj->flags |= OBJECT_ADDED; /* @@ -2303,7 +2303,7 @@ static void show_object(struct object *obj, static void show_edge(struct commit *commit) { - add_preferred_base(commit->object.sha1); + add_preferred_base(commit->object.oid.hash); } struct in_pack_object { @@ -2319,7 +2319,7 @@ struct in_pack { static void mark_in_pack_object(struct object *object, struct packed_git *p, struct in_pack *in_pack) { - in_pack->array[in_pack->nr].offset = find_pack_entry_one(object->sha1, p); + in_pack->array[in_pack->nr].offset = find_pack_entry_one(object->oid.hash, p); in_pack->array[in_pack->nr].object = object; in_pack->nr++; } @@ -2338,7 +2338,7 @@ static int ofscmp(const void *a_, const void *b_) else if (a->offset > b->offset) return 1; else - return hashcmp(a->object->sha1, b->object->sha1); + return oidcmp(&a->object->oid, &b->object->oid); } static void add_objects_in_unpacked_packs(struct rev_info *revs) @@ -2376,7 +2376,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs) ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; - add_object_entry(o->sha1, o->type, "", 0); + add_object_entry(o->oid.hash, o->type, "", 0); } } free(in_pack.array); @@ -2484,12 +2484,12 @@ static void record_recent_object(struct object *obj, const char *last, void *data) { - sha1_array_append(&recent_objects, obj->sha1); + sha1_array_append(&recent_objects, obj->oid.hash); } static void record_recent_commit(struct commit *commit, void *data) { - sha1_array_append(&recent_objects, commit->object.sha1); + sha1_array_append(&recent_objects, commit->object.oid.hash); } static void get_object_list(int ac, const char **av) diff --git a/builtin/patch-id.c b/builtin/patch-id.c index ba34dac4d2..366ce5a5d4 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -165,7 +165,7 @@ static void generate_id_list(int stable) strbuf_release(&line_buf); } -static const char patch_id_usage[] = "git patch-id [--stable | --unstable] < patch"; +static const char patch_id_usage[] = "git patch-id [--stable | --unstable]"; static int git_patch_id_config(const char *var, const char *value, void *cb) { diff --git a/builtin/prune.c b/builtin/prune.c index 10b03d3e4c..8f4f052285 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -119,6 +119,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, prune_usage, 0); + if (repository_format_precious_objects) + die(_("cannot prune in a precious-objects repo")); + while (argc--) { unsigned char sha1[20]; const char *name = *argv++; diff --git a/builtin/pull.c b/builtin/pull.c index bf3fd3f9c8..5145fc60a0 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -743,7 +743,7 @@ static int get_octopus_merge_base(unsigned char *merge_base, if (!result) return 1; - hashcpy(merge_base, result->item->object.sha1); + hashcpy(merge_base, result->item->object.oid.hash); return 0; } diff --git a/builtin/push.c b/builtin/push.c index 3bda430b6b..8963dbdf3d 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -9,6 +9,7 @@ #include "transport.h" #include "parse-options.h" #include "submodule.h" +#include "submodule-config.h" #include "send-pack.h" static const char * const push_usage[] = { @@ -21,6 +22,7 @@ static int deleterefs; static const char *receivepack; static int verbosity; static int progress = -1; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static struct push_cas_option cas; @@ -452,22 +454,14 @@ static int do_push(const char *repo, int flags) static int option_parse_recurse_submodules(const struct option *opt, const char *arg, int unset) { - int *flags = opt->value; + int *recurse_submodules = opt->value; - if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK | - TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND)) - die("%s can only be used once.", opt->long_name); - - if (arg) { - if (!strcmp(arg, "check")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; - else if (!strcmp(arg, "on-demand")) - *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; - else - die("bad %s argument: %s", opt->long_name, arg); - } else - die("option %s needs an argument (check|on-demand)", - opt->long_name); + if (unset) + *recurse_submodules = RECURSE_SUBMODULES_OFF; + else if (arg) + *recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg); + else + die("%s missing parameter", opt->long_name); return 0; } @@ -522,6 +516,10 @@ static int git_push_config(const char *k, const char *v, void *cb) return error("Invalid value for '%s'", k); } } + } else if (!strcmp(k, "push.recursesubmodules")) { + const char *value; + if (!git_config_get_value("push.recursesubmodules", &value)) + recurse_submodules = parse_push_recurse_submodules_arg(k, value); } return git_default_config(k, v, NULL); @@ -549,7 +547,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) 0, CAS_OPT_NAME, &cas, N_("refname>:<expect"), N_("require old value of ref to be at this value"), PARSE_OPT_OPTARG, parseopt_push_cas_option }, - { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check|on-demand", + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no", N_("control recursive pushing of submodules"), PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")), @@ -580,6 +578,11 @@ int cmd_push(int argc, const char **argv, const char *prefix) if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); + if (recurse_submodules == RECURSE_SUBMODULES_CHECK) + flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; + else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) + flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND; + if (tags) add_refspec("refs/tags/*"); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index bcb624bc05..f2d6761af6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -195,9 +195,6 @@ static int receive_pack_config(const char *var, const char *value, void *cb) static void show_ref(const char *path, const unsigned char *sha1) { - if (ref_is_hidden(path)) - return; - if (sent_capabilities) { packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); } else { @@ -219,9 +216,14 @@ static void show_ref(const char *path, const unsigned char *sha1) } } -static int show_ref_cb(const char *path, const struct object_id *oid, int flag, void *unused) +static int show_ref_cb(const char *path_full, const struct object_id *oid, + int flag, void *unused) { - path = strip_namespace(path); + const char *path = strip_namespace(path_full); + + if (ref_is_hidden(path, path_full)) + return 0; + /* * Advertise refs outside our current namespace as ".have" * refs, so that the client can use them to minimize data @@ -244,7 +246,7 @@ static void show_one_alternate_sha1(const unsigned char sha1[20], void *unused) static void collect_one_alternate_ref(const struct ref *ref, void *data) { struct sha1_array *sa = data; - sha1_array_append(sa, ref->old_sha1); + sha1_array_append(sa, ref->old_oid.hash); } static void write_head_info(void) @@ -1195,16 +1197,29 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20]) static void reject_updates_to_hidden(struct command *commands) { + struct strbuf refname_full = STRBUF_INIT; + size_t prefix_len; struct command *cmd; + strbuf_addstr(&refname_full, get_git_namespace()); + prefix_len = refname_full.len; + for (cmd = commands; cmd; cmd = cmd->next) { - if (cmd->error_string || !ref_is_hidden(cmd->ref_name)) + if (cmd->error_string) + continue; + + strbuf_setlen(&refname_full, prefix_len); + strbuf_addstr(&refname_full, cmd->ref_name); + + if (!ref_is_hidden(cmd->ref_name, refname_full.buf)) continue; if (is_null_sha1(cmd->new_sha1)) cmd->error_string = "deny deleting a hidden ref"; else cmd->error_string = "deny updating a hidden ref"; } + + strbuf_release(&refname_full); } static int should_process_cmd(struct command *cmd) @@ -1603,7 +1618,7 @@ static void prepare_shallow_update(struct command *commands, continue; si->need_reachability_test[i]++; for (k = 0; k < 32; k++) - if (si->used_shallow[i][j] & (1 << k)) + if (si->used_shallow[i][j] & (1U << k)) si->shallow_ref[j * 32 + k]++; } @@ -1781,6 +1796,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) "gc", "--auto", "--quiet", NULL, }; int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + close_all_packs(); run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) diff --git a/builtin/reflog.c b/builtin/reflog.c index f96ca2a27d..f39960e5e4 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -126,7 +126,7 @@ static int commit_is_complete(struct commit *commit) struct commit_list *parent; c = (struct commit *)study.objects[--study.nr].item; - if (!c->object.parsed && !parse_object(c->object.sha1)) + if (!c->object.parsed && !parse_object(c->object.oid.hash)) c->object.flags |= INCOMPLETE; if (c->object.flags & INCOMPLETE) { @@ -152,7 +152,7 @@ static int commit_is_complete(struct commit *commit) for (i = 0; i < found.nr; i++) { struct commit *c = (struct commit *)found.objects[i].item; - if (!tree_is_complete(c->tree->object.sha1)) { + if (!tree_is_complete(c->tree->object.oid.hash)) { is_incomplete = 1; c->object.flags |= INCOMPLETE; } @@ -218,7 +218,6 @@ static int keep_entry(struct commit **it, unsigned char *sha1) */ static void mark_reachable(struct expire_reflog_policy_cb *cb) { - struct commit *commit; struct commit_list *pending; unsigned long expire_limit = cb->mark_limit; struct commit_list *leftover = NULL; @@ -228,11 +227,8 @@ static void mark_reachable(struct expire_reflog_policy_cb *cb) pending = cb->mark_list; while (pending) { - struct commit_list *entry = pending; struct commit_list *parent; - pending = entry->next; - commit = entry->item; - free(entry); + struct commit *commit = pop_commit(&pending); if (commit->object.flags & REACHABLE) continue; if (parse_commit(commit)) diff --git a/builtin/remote.c b/builtin/remote.c index e4c3ea130c..6694cf20ef 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -401,7 +401,7 @@ static int get_push_ref_states(const struct ref *remote_refs, if (!ref->peer_ref) continue; - hashcpy(ref->new_sha1, ref->peer_ref->new_sha1); + oidcpy(&ref->new_oid, &ref->peer_ref->new_oid); item = string_list_append(&states->push, abbrev_branch(ref->peer_ref->name)); @@ -410,14 +410,14 @@ static int get_push_ref_states(const struct ref *remote_refs, info->forced = ref->force; info->dest = xstrdup(abbrev_branch(ref->name)); - if (is_null_sha1(ref->new_sha1)) { + if (is_null_oid(&ref->new_oid)) { info->status = PUSH_STATUS_DELETE; - } else if (!hashcmp(ref->old_sha1, ref->new_sha1)) + } else if (!oidcmp(&ref->old_oid, &ref->new_oid)) info->status = PUSH_STATUS_UPTODATE; - else if (is_null_sha1(ref->old_sha1)) + else if (is_null_oid(&ref->old_oid)) info->status = PUSH_STATUS_CREATE; - else if (has_sha1_file(ref->old_sha1) && - ref_newer(ref->new_sha1, ref->old_sha1)) + else if (has_object_file(&ref->old_oid) && + ref_newer(&ref->new_oid, &ref->old_oid)) info->status = PUSH_STATUS_FASTFORWARD; else info->status = PUSH_STATUS_OUTOFDATE; diff --git a/builtin/repack.c b/builtin/repack.c index 70b9b1eaf1..945611006a 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -193,6 +193,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_repack_options, git_repack_usage, 0); + if (delete_redundant && repository_format_precious_objects) + die(_("cannot delete packs in a precious-objects repo")); + if (pack_kept_objects < 0) pack_kept_objects = write_bitmaps; diff --git a/builtin/replace.c b/builtin/replace.c index 6b3c469a33..748c6ca954 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -358,10 +358,10 @@ static void check_one_mergetag(struct commit *commit, /* iterate over new parents */ for (i = 1; i < mergetag_data->argc; i++) { - unsigned char sha1[20]; - if (get_sha1(mergetag_data->argv[i], sha1) < 0) + struct object_id oid; + if (get_sha1(mergetag_data->argv[i], oid.hash) < 0) die(_("Not a valid object name: '%s'"), mergetag_data->argv[i]); - if (!hashcmp(tag->tagged->sha1, sha1)) + if (!oidcmp(&tag->tagged->oid, &oid)) return; /* found */ } diff --git a/builtin/reset.c b/builtin/reset.c index c503e75a59..092c3a5399 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -96,7 +96,7 @@ static void print_new_head_line(struct commit *commit) const char *hex, *body; const char *msg; - hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV); + hex = find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV); printf(_("HEAD is now at %s"), hex); msg = logmsg_reencode(commit, NULL, get_log_output_encoding()); body = strstr(msg, "\n\n"); @@ -269,7 +269,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) int reset_type = NONE, update_ref_status = 0, quiet = 0; int patch_mode = 0, unborn; const char *rev; - unsigned char sha1[20]; + struct object_id oid; struct pathspec pathspec; int intent_to_add = 0; const struct option options[] = { @@ -295,26 +295,26 @@ int cmd_reset(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH); parse_args(&pathspec, argv, prefix, patch_mode, &rev); - unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", sha1); + unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ - hashcpy(sha1, EMPTY_TREE_SHA1_BIN); + hashcpy(oid.hash, EMPTY_TREE_SHA1_BIN); } else if (!pathspec.nr) { struct commit *commit; - if (get_sha1_committish(rev, sha1)) + if (get_sha1_committish(rev, oid.hash)) die(_("Failed to resolve '%s' as a valid revision."), rev); - commit = lookup_commit_reference(sha1); + commit = lookup_commit_reference(oid.hash); if (!commit) die(_("Could not parse object '%s'."), rev); - hashcpy(sha1, commit->object.sha1); + oidcpy(&oid, &commit->object.oid); } else { struct tree *tree; - if (get_sha1_treeish(rev, sha1)) + if (get_sha1_treeish(rev, oid.hash)) die(_("Failed to resolve '%s' as a valid tree."), rev); - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(oid.hash); if (!tree) die(_("Could not parse object '%s'."), rev); - hashcpy(sha1, tree->object.sha1); + oidcpy(&oid, &tree->object.oid); } if (patch_mode) { @@ -357,15 +357,15 @@ int cmd_reset(int argc, const char **argv, const char *prefix) hold_locked_index(lock, 1); if (reset_type == MIXED) { int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN; - if (read_from_tree(&pathspec, sha1, intent_to_add)) + if (read_from_tree(&pathspec, oid.hash, intent_to_add)) return 1; if (get_git_work_tree()) refresh_index(&the_index, flags, NULL, NULL, _("Unstaged changes after reset:")); } else { - int err = reset_index(sha1, reset_type, quiet); + int err = reset_index(oid.hash, reset_type, quiet); if (reset_type == KEEP && !err) - err = reset_index(sha1, MIXED, quiet); + err = reset_index(oid.hash, MIXED, quiet); if (err) die(_("Could not reset index file to revision '%s'."), rev); } @@ -377,10 +377,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (!pathspec.nr && !unborn) { /* Any resets without paths update HEAD to the head being * switched to, saving the previous head in ORIG_HEAD before. */ - update_ref_status = reset_refs(rev, sha1); + update_ref_status = reset_refs(rev, oid.hash); if (reset_type == HARD && !update_ref_status && !quiet) - print_new_head_line(lookup_commit_reference(sha1)); + print_new_head_line(lookup_commit_reference(oid.hash)); } if (!pathspec.nr) remove_branch_state(); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 491d298fa2..3aa89a1a3c 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -81,14 +81,14 @@ static void show_commit(struct commit *commit, void *data) if (!revs->graph) fputs(get_revision_mark(revs, commit), stdout); if (revs->abbrev_commit && revs->abbrev) - fputs(find_unique_abbrev(commit->object.sha1, revs->abbrev), + fputs(find_unique_abbrev(commit->object.oid.hash, revs->abbrev), stdout); else - fputs(sha1_to_hex(commit->object.sha1), stdout); + fputs(oid_to_hex(&commit->object.oid), stdout); if (revs->print_parents) { struct commit_list *parents = commit->parents; while (parents) { - printf(" %s", sha1_to_hex(parents->item->object.sha1)); + printf(" %s", oid_to_hex(&parents->item->object.oid)); parents = parents->next; } } @@ -97,7 +97,7 @@ static void show_commit(struct commit *commit, void *data) children = lookup_decoration(&revs->children, &commit->object); while (children) { - printf(" %s", sha1_to_hex(children->item->object.sha1)); + printf(" %s", oid_to_hex(&children->item->object.oid)); children = children->next; } } @@ -182,10 +182,10 @@ static void finish_object(struct object *obj, void *cb_data) { struct rev_list_info *info = cb_data; - if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1)) - die("missing blob object '%s'", sha1_to_hex(obj->sha1)); + if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid)) + die("missing blob object '%s'", oid_to_hex(&obj->oid)); if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT) - parse_object(obj->sha1); + parse_object(obj->oid.hash); } static void show_object(struct object *obj, @@ -201,7 +201,7 @@ static void show_object(struct object *obj, static void show_edge(struct commit *commit) { - printf("-%s\n", sha1_to_hex(commit->object.sha1)); + printf("-%s\n", oid_to_hex(&commit->object.oid)); } static void print_var_str(const char *var, const char *val) @@ -242,7 +242,7 @@ static int show_bisect_vars(struct rev_list_info *info, int reaches, int all) cnt = reaches; if (revs->commits) - sha1_to_hex_r(hex, revs->commits->item->object.sha1); + sha1_to_hex_r(hex, revs->commits->item->object.oid.hash); if (flags & BISECT_SHOW_ALL) { traverse_commit_list(revs, show_commit, show_object, info); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 02d747dcb1..7e074aad40 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -281,11 +281,8 @@ static int try_difference(const char *arg) b = lookup_commit_reference(end); exclude = get_merge_bases(a, b); while (exclude) { - struct commit_list *n = exclude->next; - show_rev(REVERSED, - exclude->item->object.sha1,NULL); - free(exclude); - exclude = n; + struct commit *commit = pop_commit(&exclude); + show_rev(REVERSED, commit->object.oid.hash, NULL); } } *dotdot = '.'; @@ -322,7 +319,7 @@ static int try_parent_shorthands(const char *arg) commit = lookup_commit_reference(sha1); for (parents = commit->parents; parents; parents = parents->next) show_rev(parents_only ? NORMAL : REVERSED, - parents->item->object.sha1, arg); + parents->item->object.oid.hash, arg); *dotdot = '^'; return 1; diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 007cc66a03..35ebd17f80 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -129,7 +129,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) } if (!author) { warning(_("Missing author: %s"), - sha1_to_hex(commit->object.sha1)); + oid_to_hex(&commit->object.oid)); return; } if (log->user_format) { diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 092b59b0b3..25669357e9 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -3,6 +3,7 @@ #include "refs.h" #include "builtin.h" #include "color.h" +#include "argv-array.h" #include "parse-options.h" static const char* show_branch_usage[] = { @@ -16,9 +17,7 @@ static const char* show_branch_usage[] = { static int showbranch_use_color = -1; -static int default_num; -static int default_alloc; -static const char **default_arg; +static struct argv_array default_args = ARGV_ARRAY_INIT; #define UNINTERESTING 01 @@ -53,17 +52,6 @@ static struct commit *interesting(struct commit_list *list) return NULL; } -static struct commit *pop_one_commit(struct commit_list **list_p) -{ - struct commit *commit; - struct commit_list *list; - list = *list_p; - commit = list->item; - *list_p = list->next; - free(list); - return commit; -} - struct commit_name { const char *head_name; /* which head's ancestor? */ int generation; /* how many parents away from head_name */ @@ -213,7 +201,7 @@ static void join_revs(struct commit_list **list_p, while (*list_p) { struct commit_list *parents; int still_interesting = !!interesting(*list_p); - struct commit *commit = pop_one_commit(list_p); + struct commit *commit = pop_commit(list_p); int flags = commit->object.flags & all_mask; if (!still_interesting && extra <= 0) @@ -303,7 +291,7 @@ static void show_one_commit(struct commit *commit, int no_name) } else printf("[%s] ", - find_unique_abbrev(commit->object.sha1, + find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV)); } puts(pretty_str); @@ -504,11 +492,11 @@ static int show_merge_base(struct commit_list *seen, int num_rev) int exit_status = 1; while (seen) { - struct commit *commit = pop_one_commit(&seen); + struct commit *commit = pop_commit(&seen); int flags = commit->object.flags & all_mask; if (!(flags & UNINTERESTING) && ((flags & all_revs) == all_revs)) { - puts(sha1_to_hex(commit->object.sha1)); + puts(oid_to_hex(&commit->object.oid)); exit_status = 0; commit->object.flags |= UNINTERESTING; } @@ -528,7 +516,7 @@ static int show_independent(struct commit **rev, unsigned int flag = rev_mask[i]; if (commit->object.flags == flag) - puts(sha1_to_hex(commit->object.sha1)); + puts(oid_to_hex(&commit->object.oid)); commit->object.flags |= UNINTERESTING; } return 0; @@ -567,16 +555,9 @@ static int git_show_branch_config(const char *var, const char *value, void *cb) * default_arg is now passed to parse_options(), so we need to * mimic the real argv a bit better. */ - if (!default_num) { - default_alloc = 20; - default_arg = xcalloc(default_alloc, sizeof(*default_arg)); - default_arg[default_num++] = "show-branch"; - } else if (default_alloc <= default_num + 1) { - default_alloc = default_alloc * 3 / 2 + 20; - REALLOC_ARRAY(default_arg, default_alloc); - } - default_arg[default_num++] = xstrdup(value); - default_arg[default_num] = NULL; + if (!default_args.argc) + argv_array_push(&default_args, "show-branch"); + argv_array_push(&default_args, value); return 0; } @@ -696,9 +677,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) git_config(git_show_branch_config, NULL); /* If nothing is specified, try the default first */ - if (ac == 1 && default_num) { - ac = default_num; - av = default_arg; + if (ac == 1 && default_args.argc) { + ac = default_args.argc; + av = default_args.argv; } ac = parse_options(ac, av, prefix, builtin_show_branch_options, @@ -886,7 +867,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) head_len, ref_name[i], head_oid.hash, - rev[i]->object.sha1); + rev[i]->object.oid.hash); if (extra < 0) printf("%c [%s] ", is_head ? '*' : ' ', ref_name[i]); @@ -929,7 +910,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) all_revs = all_mask & ~((1u << REV_SHIFT) - 1); while (seen) { - struct commit *commit = pop_one_commit(&seen); + struct commit *commit = pop_commit(&seen); int this_flag = commit->object.flags; int is_merge_point = ((this_flag & all_revs) == all_revs); diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 131ef28e5c..6d4e669002 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -8,7 +8,7 @@ static const char * const show_ref_usage[] = { N_("git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"), - N_("git show-ref --exclude-existing[=<pattern>] < <ref-list>"), + N_("git show-ref --exclude-existing[=<pattern>]"), NULL }; @@ -161,11 +161,6 @@ static int exclude_existing_callback(const struct option *opt, const char *arg, return 0; } -static int help_callback(const struct option *opt, const char *arg, int unset) -{ - return -1; -} - static const struct option show_ref_options[] = { OPT_BOOL(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")), OPT_BOOL(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")), @@ -186,18 +181,13 @@ static const struct option show_ref_options[] = { { OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg, N_("pattern"), N_("show refs from stdin that aren't in local repository"), PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback }, - { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"), - PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback }, OPT_END() }; int cmd_show_ref(int argc, const char **argv, const char *prefix) { - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(show_ref_usage, show_ref_options); - argc = parse_options(argc, argv, prefix, show_ref_options, - show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP); + show_ref_usage, 0); if (exclude_arg) return exclude_existing(exclude_existing_arg); diff --git a/builtin/stripspace.c b/builtin/stripspace.c index 1259ed708b..7ff8434f7c 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -1,71 +1,7 @@ #include "builtin.h" #include "cache.h" - -/* - * Returns the length of a line, without trailing spaces. - * - * If the line ends with newline, it will be removed too. - */ -static size_t cleanup(char *line, size_t len) -{ - while (len) { - unsigned char c = line[len - 1]; - if (!isspace(c)) - break; - len--; - } - - return len; -} - -/* - * Remove empty lines from the beginning and end - * and also trailing spaces from every line. - * - * Turn multiple consecutive empty lines between paragraphs - * into just one empty line. - * - * If the input has only empty lines and spaces, - * no output will be produced. - * - * If last line does not have a newline at the end, one is added. - * - * Enable skip_comments to skip every line starting with comment - * character. - */ -void stripspace(struct strbuf *sb, int skip_comments) -{ - int empties = 0; - size_t i, j, len, newlen; - char *eol; - - /* We may have to add a newline. */ - strbuf_grow(sb, 1); - - for (i = j = 0; i < sb->len; i += len, j += newlen) { - eol = memchr(sb->buf + i, '\n', sb->len - i); - len = eol ? eol - (sb->buf + i) + 1 : sb->len - i; - - if (skip_comments && len && sb->buf[i] == comment_line_char) { - newlen = 0; - continue; - } - newlen = cleanup(sb->buf + i, len); - - /* Not just an empty line? */ - if (newlen) { - if (empties > 0 && j > 0) - sb->buf[j++] = '\n'; - empties = 0; - memmove(sb->buf + j, sb->buf + i, newlen); - sb->buf[newlen + j++] = '\n'; - } else { - empties++; - } - } - - strbuf_setlen(sb, j); -} +#include "parse-options.h" +#include "strbuf.h" static void comment_lines(struct strbuf *buf) { @@ -77,41 +13,45 @@ static void comment_lines(struct strbuf *buf) free(msg); } -static const char *usage_msg = "\n" -" git stripspace [-s | --strip-comments] < input\n" -" git stripspace [-c | --comment-lines] < input"; +static const char * const stripspace_usage[] = { + N_("git stripspace [-s | --strip-comments]"), + N_("git stripspace [-c | --comment-lines]"), + NULL +}; + +enum stripspace_mode { + STRIP_DEFAULT = 0, + STRIP_COMMENTS, + COMMENT_LINES +}; int cmd_stripspace(int argc, const char **argv, const char *prefix) { struct strbuf buf = STRBUF_INIT; - int strip_comments = 0; - enum { INVAL = 0, STRIP_SPACE = 1, COMMENT_LINES = 2 } mode = STRIP_SPACE; - - if (argc == 2) { - if (!strcmp(argv[1], "-s") || - !strcmp(argv[1], "--strip-comments")) { - strip_comments = 1; - } else if (!strcmp(argv[1], "-c") || - !strcmp(argv[1], "--comment-lines")) { - mode = COMMENT_LINES; - } else { - mode = INVAL; - } - } else if (argc > 1) { - mode = INVAL; - } - - if (mode == INVAL) - usage(usage_msg); - - if (strip_comments || mode == COMMENT_LINES) + enum stripspace_mode mode = STRIP_DEFAULT; + + const struct option options[] = { + OPT_CMDMODE('s', "strip-comments", &mode, + N_("skip and remove all lines starting with comment character"), + STRIP_COMMENTS), + OPT_CMDMODE('c', "comment-lines", &mode, + N_("prepend comment character and blank to each line"), + COMMENT_LINES), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, stripspace_usage, 0); + if (argc) + usage_with_options(stripspace_usage, options); + + if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) git_config(git_default_config, NULL); if (strbuf_read(&buf, 0, 1024) < 0) die_errno("could not read the input"); - if (mode == STRIP_SPACE) - stripspace(&buf, strip_comments); + if (mode == STRIP_DEFAULT || mode == STRIP_COMMENTS) + strbuf_stripspace(&buf, mode == STRIP_COMMENTS); else comment_lines(&buf); diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index ce0fde705c..9c29a64e43 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -67,7 +67,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) if (!strcmp(argv[0], "HEAD") && !starts_with(argv[1], "refs/")) die("Refusing to point HEAD outside of refs/"); - create_symref(argv[0], argv[1], msg); + ret = !!create_symref(argv[0], argv[1], msg); break; default: usage_with_options(git_symbolic_ref_usage, options); diff --git a/builtin/tag.c b/builtin/tag.c index 9e17dca7ca..1705c94665 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -44,14 +44,15 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con if (!format) { if (filter->lines) { to_free = xstrfmt("%s %%(contents:lines=%d)", - "%(align:15)%(refname:short)%(end)", + "%(align:15)%(refname:strip=2)%(end)", filter->lines); format = to_free; } else - format = "%(refname:short)"; + format = "%(refname:strip=2)"; } verify_ref_format(format); + filter->with_commit_tag_algo = 1; filter_refs(&array, filter, FILTER_REFS_TAGS); ref_array_sort(sorting, &array); @@ -268,7 +269,7 @@ static void create_tag(const unsigned char *object, const char *tag, } if (opt->cleanup_mode != CLEANUP_NONE) - stripspace(buf, opt->cleanup_mode == CLEANUP_ALL); + strbuf_stripspace(buf, opt->cleanup_mode == CLEANUP_ALL); if (!opt->message_given && !buf->len) die(_("no tag message?")); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 7cc086f5f2..875e7ed998 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -13,7 +13,7 @@ #include "fsck.h" static int dry_run, quiet, recover, has_errors, strict; -static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] < pack-file"; +static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]"; /* We always read in 4kB chunks. */ static unsigned char buffer[4096]; @@ -46,7 +46,7 @@ static void add_object_buffer(struct object *object, char *buffer, unsigned long obj->buffer = buffer; obj->size = size; if (add_decoration(&obj_decorate, object, obj)) - die("object %s tried to add buffer twice!", sha1_to_hex(object->sha1)); + die("object %s tried to add buffer twice!", oid_to_hex(&object->oid)); } /* @@ -170,7 +170,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) unsigned char sha1[20]; if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), sha1) < 0) - die("failed to write object %s", sha1_to_hex(obj->sha1)); + die("failed to write object %s", oid_to_hex(&obj->oid)); obj->flags |= FLAG_WRITTEN; } @@ -194,7 +194,7 @@ static int check_object(struct object *obj, int type, void *data, struct fsck_op if (!(obj->flags & FLAG_OPEN)) { unsigned long size; - int type = sha1_object_info(obj->sha1, &size); + int type = sha1_object_info(obj->oid.hash, &size); if (type != obj->type || type <= 0) die("object of unexpected type"); obj->flags |= FLAG_WRITTEN; @@ -203,12 +203,12 @@ static int check_object(struct object *obj, int type, void *data, struct fsck_op obj_buf = lookup_object_buffer(obj); if (!obj_buf) - die("Whoops! Cannot find object '%s'", sha1_to_hex(obj->sha1)); + die("Whoops! Cannot find object '%s'", oid_to_hex(&obj->oid)); if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options)) die("Error in object"); fsck_options.walk = check_object; if (fsck_walk(obj, NULL, &fsck_options)) - die("Error on reachable objects of %s", sha1_to_hex(obj->sha1)); + die("Error on reachable objects of %s", oid_to_hex(&obj->oid)); write_cached_object(obj, obj_buf); return 0; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 78d26902a6..475b9581a5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -12,7 +12,7 @@ #include "worktree.h" static const char * const worktree_usage[] = { - N_("git worktree add [<options>] <path> <branch>"), + N_("git worktree add [<options>] <path> [<branch>]"), N_("git worktree prune [<options>]"), N_("git worktree list [<options>]"), NULL @@ -277,7 +277,7 @@ static int add_worktree(const char *path, const char *refname, if (commit) argv_array_pushl(&cp.args, "update-ref", "HEAD", - sha1_to_hex(commit->object.sha1), NULL); + oid_to_hex(&commit->object.oid), NULL); else argv_array_pushl(&cp.args, "symbolic-ref", "HEAD", symref.buf, NULL); |