diff options
Diffstat (limited to 'builtin')
60 files changed, 1279 insertions, 934 deletions
diff --git a/builtin/add.c b/builtin/add.c index 9f53f020d0..36cad00ae6 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -400,7 +400,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) } /* This picks up the paths that are not tracked */ - baselen = fill_directory(&dir, &pathspec); + baselen = fill_directory(&dir, &the_index, &pathspec); if (pathspec.nr) seen = prune_directory(&dir, &pathspec, baselen); } @@ -436,8 +436,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) !file_exists(path))) { if (ignore_missing) { int dtype = DT_UNKNOWN; - if (is_excluded(&dir, path, &dtype)) - dir_add_ignored(&dir, path, pathspec.items[i].len); + if (is_excluded(&dir, &the_index, path, &dtype)) + dir_add_ignored(&dir, &the_index, + path, pathspec.items[i].len); } else die(_("pathspec '%s' did not match any files"), pathspec.items[i].original); diff --git a/builtin/am.c b/builtin/am.c index f7a7a971fb..0f63dcab16 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -134,17 +134,15 @@ struct am_state { }; /** - * Initializes am_state with the default values. The state directory is set to - * dir. + * Initializes am_state with the default values. */ -static void am_state_init(struct am_state *state, const char *dir) +static void am_state_init(struct am_state *state) { int gpgsign; memset(state, 0, sizeof(*state)); - assert(dir); - state->dir = xstrdup(dir); + state->dir = git_pathdup("rebase-apply"); state->prec = 4; @@ -762,14 +760,18 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state, mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1); out = fopen(mail, "w"); - if (!out) + if (!out) { + if (in != stdin) + fclose(in); return error_errno(_("could not open '%s' for writing"), mail); + } ret = fn(out, in, keep_cr); fclose(out); - fclose(in); + if (in != stdin) + fclose(in); if (ret) return error(_("could not parse patch '%s'"), *paths); @@ -877,12 +879,12 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr) if (skip_prefix(sb.buf, "# User ", &str)) fprintf(out, "From: %s\n", str); else if (skip_prefix(sb.buf, "# Date ", &str)) { - unsigned long timestamp; + timestamp_t timestamp; long tz, tz2; char *end; errno = 0; - timestamp = strtoul(str, &end, 10); + timestamp = parse_timestamp(str, &end, 10); if (errno) return error(_("invalid timestamp")); @@ -1143,7 +1145,7 @@ static int index_has_changes(struct strbuf *sb) DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); if (!sb) DIFF_OPT_SET(&opt, QUICK); - do_diff_cache(head.hash, &opt); + do_diff_cache(&head, &opt); diffcore_std(&opt); for (i = 0; sb && i < diff_queued_diff.nr; i++) { if (i) @@ -1181,42 +1183,39 @@ static void NORETURN die_user_resolve(const struct am_state *state) exit(128); } -static void am_signoff(struct strbuf *sb) +/** + * Appends signoff to the "msg" field of the am_state. + */ +static void am_append_signoff(struct am_state *state) { char *cp; struct strbuf mine = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; + + strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); - /* Does it end with our own sign-off? */ + /* our sign-off */ strbuf_addf(&mine, "\n%s%s\n", sign_off_header, fmt_name(getenv("GIT_COMMITTER_NAME"), getenv("GIT_COMMITTER_EMAIL"))); - if (mine.len < sb->len && - !strcmp(mine.buf, sb->buf + sb->len - mine.len)) + + /* Does sb end with it already? */ + if (mine.len < sb.len && + !strcmp(mine.buf, sb.buf + sb.len - mine.len)) goto exit; /* no need to duplicate */ /* Does it have any Signed-off-by: in the text */ - for (cp = sb->buf; + for (cp = sb.buf; cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL; cp = strchr(cp, '\n')) { - if (sb->buf == cp || cp[-1] == '\n') + if (sb.buf == cp || cp[-1] == '\n') break; } - strbuf_addstr(sb, mine.buf + !!cp); + strbuf_addstr(&sb, mine.buf + !!cp); exit: strbuf_release(&mine); -} - -/** - * Appends signoff to the "msg" field of the am_state. - */ -static void am_append_signoff(struct am_state *state) -{ - struct strbuf sb = STRBUF_INIT; - - strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len); - am_signoff(&sb); state->msg = strbuf_detach(&sb, &state->msg_len); } @@ -1313,7 +1312,7 @@ static int parse_mail(struct am_state *state, const char *mail) } if (is_empty_file(am_path(state, "patch"))) { - printf_ln(_("Patch is empty. Was it split wrong?")); + printf_ln(_("Patch is empty.")); die_user_resolve(state); } @@ -1321,9 +1320,6 @@ static int parse_mail(struct am_state *state, const char *mail) strbuf_addbuf(&msg, &mi.log_message); strbuf_stripspace(&msg, 0); - if (state->signoff) - am_signoff(&msg); - assert(!state->author_name); state->author_name = strbuf_detach(&author_name, NULL); @@ -1355,19 +1351,16 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail) struct strbuf sb = STRBUF_INIT; FILE *fp = xfopen(mail, "r"); const char *x; + int ret = 0; - if (strbuf_getline_lf(&sb, fp)) - return -1; - - if (!skip_prefix(sb.buf, "From ", &x)) - return -1; - - if (get_oid_hex(x, commit_id) < 0) - return -1; + if (strbuf_getline_lf(&sb, fp) || + !skip_prefix(sb.buf, "From ", &x) || + get_oid_hex(x, commit_id) < 0) + ret = -1; strbuf_release(&sb); fclose(fp); - return 0; + return ret; } /** @@ -1376,40 +1369,33 @@ static int get_mail_commit_oid(struct object_id *commit_id, const char *mail) */ static void get_commit_info(struct am_state *state, struct commit *commit) { - const char *buffer, *ident_line, *author_date, *msg; + const char *buffer, *ident_line, *msg; size_t ident_len; - struct ident_split ident_split; - struct strbuf sb = STRBUF_INIT; + struct ident_split id; buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding()); ident_line = find_commit_header(buffer, "author", &ident_len); - if (split_ident_line(&ident_split, ident_line, ident_len) < 0) { - strbuf_add(&sb, ident_line, ident_len); - die(_("invalid ident line: %s"), sb.buf); - } + if (split_ident_line(&id, ident_line, ident_len) < 0) + die(_("invalid ident line: %.*s"), (int)ident_len, ident_line); assert(!state->author_name); - if (ident_split.name_begin) { - strbuf_add(&sb, ident_split.name_begin, - ident_split.name_end - ident_split.name_begin); - state->author_name = strbuf_detach(&sb, NULL); - } else + if (id.name_begin) + state->author_name = + xmemdupz(id.name_begin, id.name_end - id.name_begin); + else state->author_name = xstrdup(""); assert(!state->author_email); - if (ident_split.mail_begin) { - strbuf_add(&sb, ident_split.mail_begin, - ident_split.mail_end - ident_split.mail_begin); - state->author_email = strbuf_detach(&sb, NULL); - } else + if (id.mail_begin) + state->author_email = + xmemdupz(id.mail_begin, id.mail_end - id.mail_begin); + else state->author_email = xstrdup(""); - author_date = show_ident_date(&ident_split, DATE_MODE(NORMAL)); - strbuf_addstr(&sb, author_date); assert(!state->author_date); - state->author_date = strbuf_detach(&sb, NULL); + state->author_date = xstrdup(show_ident_date(&id, DATE_MODE(NORMAL))); assert(!state->msg); msg = strstr(buffer, "\n\n"); @@ -1417,6 +1403,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit) die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid)); state->msg = xstrdup(msg + 2); state->msg_len = strlen(state->msg); + unuse_commit_buffer(commit, buffer); } /** @@ -1457,9 +1444,9 @@ static void write_index_patch(const struct am_state *state) FILE *fp; if (!get_sha1_tree("HEAD", head.hash)) - tree = lookup_tree(head.hash); + tree = lookup_tree(&head); else - tree = lookup_tree(EMPTY_TREE_SHA1_BIN); + tree = lookup_tree(&empty_tree_oid); fp = xfopen(am_path(state, "patch"), "w"); init_revisions(&rev_info, NULL); @@ -1492,7 +1479,7 @@ static int parse_mail_rebase(struct am_state *state, const char *mail) if (get_mail_commit_oid(&commit_oid, mail) < 0) die(_("could not parse %s"), mail); - commit = lookup_commit_or_die(commit_oid.hash, mail); + commit = lookup_commit_or_die(&commit_oid, mail); get_commit_info(state, commit); @@ -1622,7 +1609,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, rev_info.prefix); - add_pending_sha1(&rev_info, "HEAD", our_tree.hash, 0); + add_pending_oid(&rev_info, "HEAD", &our_tree, 0); diff_setup_done(&rev_info.diffopt); run_diff_index(&rev_info, 1); } @@ -1687,7 +1674,7 @@ static void do_commit(const struct am_state *state) if (!get_sha1_commit("HEAD", parent.hash)) { old_oid = &parent; - commit_list_insert(lookup_commit(parent.hash), &parents); + commit_list_insert(lookup_commit(&parent), &parents); } else { old_oid = NULL; say(state, stderr, _("applying to an empty history")); @@ -1848,6 +1835,9 @@ static void am_run(struct am_state *state, int resume) if (skip) goto next; /* mail should be skipped */ + if (state->signoff) + am_append_signoff(state); + write_author_script(state); write_commit_msg(state); } @@ -1941,7 +1931,8 @@ static void am_resolve(struct am_state *state) if (unmerged_cache()) { printf_ln(_("You still have unmerged paths in your index.\n" - "Did you forget to use 'git add'?")); + "You should 'git add' each file with resolved conflicts to mark them as such.\n" + "You might run `git rm` on a file to accept \"deleted by them\" for it.")); die_user_resolve(state); } @@ -2046,11 +2037,11 @@ static int clean_index(const struct object_id *head, const struct object_id *rem struct tree *head_tree, *remote_tree, *index_tree; struct object_id index; - head_tree = parse_tree_indirect(head->hash); + head_tree = parse_tree_indirect(head); if (!head_tree) return error(_("Could not parse object '%s'."), oid_to_hex(head)); - remote_tree = parse_tree_indirect(remote->hash); + remote_tree = parse_tree_indirect(remote); if (!remote_tree) return error(_("Could not parse object '%s'."), oid_to_hex(remote)); @@ -2062,7 +2053,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem if (write_cache_as_tree(index.hash, 0, NULL)) return -1; - index_tree = parse_tree_indirect(index.hash); + index_tree = parse_tree_indirect(&index); if (!index_tree) return error(_("Could not parse object '%s'."), oid_to_hex(&index)); @@ -2157,7 +2148,7 @@ static void am_abort(struct am_state *state) am_rerere_clear(); curr_branch = resolve_refdup("HEAD", 0, curr_head.hash, NULL); - has_curr_head = !is_null_oid(&curr_head); + has_curr_head = curr_branch && !is_null_oid(&curr_head); if (!has_curr_head) hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN); @@ -2322,7 +2313,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) git_config(git_am_config, NULL); - am_state_init(&state, git_path("rebase-apply")); + am_state_init(&state); in_progress = am_in_progress(&state); if (in_progress) diff --git a/builtin/blame.c b/builtin/blame.c index f7aa95f4ba..1043e5376f 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -563,7 +563,7 @@ static struct origin *find_origin(struct scoreboard *sb, diff_setup_done(&diff_opts); if (is_null_oid(&origin->commit->object.oid)) - do_diff_cache(parent->tree->object.oid.hash, &diff_opts); + do_diff_cache(&parent->tree->object.oid, &diff_opts); else diff_tree_sha1(parent->tree->object.oid.hash, origin->commit->tree->object.oid.hash, @@ -633,7 +633,7 @@ static struct origin *find_rename(struct scoreboard *sb, diff_setup_done(&diff_opts); if (is_null_oid(&origin->commit->object.oid)) - do_diff_cache(parent->tree->object.oid.hash, &diff_opts); + do_diff_cache(&parent->tree->object.oid, &diff_opts); else diff_tree_sha1(parent->tree->object.oid.hash, origin->commit->tree->object.oid.hash, @@ -1272,7 +1272,7 @@ static void find_copy_in_parent(struct scoreboard *sb, DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER); if (is_null_oid(&target->commit->object.oid)) - do_diff_cache(parent->tree->object.oid.hash, &diff_opts); + do_diff_cache(&parent->tree->object.oid, &diff_opts); else diff_tree_sha1(parent->tree->object.oid.hash, target->commit->tree->object.oid.hash, @@ -1561,13 +1561,13 @@ finish: struct commit_info { struct strbuf author; struct strbuf author_mail; - unsigned long author_time; + timestamp_t author_time; struct strbuf author_tz; /* filled only when asked for details */ struct strbuf committer; struct strbuf committer_mail; - unsigned long committer_time; + timestamp_t committer_time; struct strbuf committer_tz; struct strbuf summary; @@ -1578,7 +1578,7 @@ struct commit_info { */ static void get_ac_line(const char *inbuf, const char *what, struct strbuf *name, struct strbuf *mail, - unsigned long *time, struct strbuf *tz) + timestamp_t *time, struct strbuf *tz) { struct ident_split ident; size_t len, maillen, namelen; @@ -1727,11 +1727,11 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) get_commit_info(suspect->commit, &ci, 1); printf("author %s\n", ci.author.buf); printf("author-mail %s\n", ci.author_mail.buf); - printf("author-time %lu\n", ci.author_time); + printf("author-time %"PRItime"\n", ci.author_time); printf("author-tz %s\n", ci.author_tz.buf); printf("committer %s\n", ci.committer.buf); printf("committer-mail %s\n", ci.committer_mail.buf); - printf("committer-time %lu\n", ci.committer_time); + printf("committer-time %"PRItime"\n", ci.committer_time); printf("committer-tz %s\n", ci.committer_tz.buf); printf("summary %s\n", ci.summary.buf); if (suspect->commit->object.flags & UNINTERESTING) @@ -1837,14 +1837,14 @@ static void assign_blame(struct scoreboard *sb, int opt) stop_progress(&pi.progress); } -static const char *format_time(unsigned long time, const char *tz_str, +static const char *format_time(timestamp_t time, const char *tz_str, int show_raw_time) { static struct strbuf time_buf = STRBUF_INIT; strbuf_reset(&time_buf); if (show_raw_time) { - strbuf_addf(&time_buf, "%lu %s", time, tz_str); + strbuf_addf(&time_buf, "%"PRItime" %s", time, tz_str); } else { const char *time_str; @@ -1890,7 +1890,7 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent, int cnt; const char *cp; struct origin *suspect = ent->suspect; - char hex[GIT_SHA1_HEXSZ + 1]; + char hex[GIT_MAX_HEXSZ + 1]; oid_to_hex_r(hex, &suspect->commit->object.oid); printf("%s %d %d %d\n", @@ -1928,7 +1928,7 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) const char *cp; struct origin *suspect = ent->suspect; struct commit_info ci; - char hex[GIT_SHA1_HEXSZ + 1]; + char hex[GIT_MAX_HEXSZ + 1]; int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP); get_commit_info(suspect->commit, &ci, 1); @@ -2253,7 +2253,7 @@ static struct commit_list **append_parent(struct commit_list **tail, const struc { struct commit *parent; - parent = lookup_commit_reference(oid->hash); + parent = lookup_commit_reference(oid); if (!parent) die("no such commit %s", oid_to_hex(oid)); return &commit_list_insert(parent, tail)->next; @@ -2461,7 +2461,7 @@ static const char *dwim_reverse_initial(struct scoreboard *sb) */ struct object *obj; struct commit *head_commit; - unsigned char head_sha1[20]; + struct object_id head_oid; if (sb->revs->pending.nr != 1) return NULL; @@ -2473,9 +2473,9 @@ static const char *dwim_reverse_initial(struct scoreboard *sb) return NULL; /* Do we have HEAD? */ - if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL)) + if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL)) return NULL; - head_commit = lookup_commit_reference_gently(head_sha1, 1); + head_commit = lookup_commit_reference_gently(&head_oid, 1); if (!head_commit) return NULL; diff --git a/builtin/branch.c b/builtin/branch.c index 52688f2e1b..83fcda43dc 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -124,7 +124,7 @@ static int branch_merged(int kind, const char *name, (reference_name = reference_name_to_free = resolve_refdup(upstream, RESOLVE_REF_READING, oid.hash, NULL)) != NULL) - reference_rev = lookup_commit_reference(oid.hash); + reference_rev = lookup_commit_reference(&oid); } if (!reference_rev) reference_rev = head_rev; @@ -157,7 +157,7 @@ static int check_branch_commit(const char *branchname, const char *refname, const struct object_id *oid, struct commit *head_rev, int kinds, int force) { - struct commit *rev = lookup_commit_reference(oid->hash); + struct commit *rev = lookup_commit_reference(oid); if (!rev) { error(_("Couldn't look up commit object for '%s'"), refname); return -1; @@ -211,7 +211,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, } if (!force) { - head_rev = lookup_commit_reference(head_oid.hash); + head_rev = lookup_commit_reference(&head_oid); if (!head_rev) die(_("Couldn't look up commit object for HEAD")); } @@ -504,7 +504,7 @@ static void rename_branch(const char *oldname, const char *newname, int force) strbuf_release(&newsection); } -static const char edit_description[] = "BRANCH_DESCRIPTION"; +static GIT_PATH_FUNC(edit_description, "EDIT_DESCRIPTION") static int edit_branch_description(const char *branch_name) { @@ -519,9 +519,9 @@ static int edit_branch_description(const char *branch_name) " %s\n" "Lines starting with '%c' will be stripped.\n"), branch_name, comment_line_char); - write_file_buf(git_path(edit_description), buf.buf, buf.len); + write_file_buf(edit_description(), buf.buf, buf.len); strbuf_reset(&buf); - if (launch_editor(git_path(edit_description), &buf, NULL)) { + if (launch_editor(edit_description(), &buf, NULL)) { strbuf_release(&buf); return -1; } @@ -562,7 +562,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"), FILTER_REFS_REMOTES), OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")), + OPT_NO_CONTAINS(&filter.no_commit, N_("print only branches that don't contain the commit")), OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")), + OPT_WITHOUT(&filter.no_commit, N_("print only branches that don't contain the commit")), OPT__ABBREV(&filter.abbrev), OPT_GROUP(N_("Specific git-branch actions:")), @@ -618,7 +620,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0) list = 1; - if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr) + if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr || + filter.no_commit) list = 1; if (!!delete + !!rename + !!new_upstream + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 8b85cb8cf0..9af863e791 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -165,6 +165,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, die("git cat-file %s: bad file", obj_name); write_or_die(1, buf, size); + free(buf); return 0; } @@ -401,10 +402,10 @@ struct object_cb_data { struct expand_data *expand; }; -static int batch_object_cb(const unsigned char sha1[20], void *vdata) +static int batch_object_cb(const struct object_id *oid, void *vdata) { struct object_cb_data *data = vdata; - hashcpy(data->expand->oid.hash, sha1); + oidcpy(&data->expand->oid, oid); batch_object_write(NULL, data->opt, data->expand); return 0; } @@ -413,7 +414,7 @@ static int batch_loose_object(const struct object_id *oid, const char *path, void *data) { - sha1_array_append(data, oid->hash); + oid_array_append(data, oid); return 0; } @@ -422,7 +423,7 @@ static int batch_packed_object(const struct object_id *oid, uint32_t pos, void *data) { - sha1_array_append(data, oid->hash); + oid_array_append(data, oid); return 0; } @@ -462,7 +463,7 @@ static int batch_objects(struct batch_options *opt) data.info.typep = &data.type; if (opt->all_objects) { - struct sha1_array sa = SHA1_ARRAY_INIT; + struct oid_array sa = OID_ARRAY_INIT; struct object_cb_data cb; for_each_loose_object(batch_loose_object, &sa, 0); @@ -470,9 +471,9 @@ static int batch_objects(struct batch_options *opt) cb.opt = opt; cb.expand = &data; - sha1_array_for_each_unique(&sa, batch_object_cb, &cb); + oid_array_for_each_unique(&sa, batch_object_cb, &cb); - sha1_array_clear(&sa); + oid_array_clear(&sa); return 0; } diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 1d73d3ca3d..d2293b22e1 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -101,7 +101,8 @@ static int check_ignore(struct dir_struct *dir, full_path = pathspec.items[i].match; exclude = NULL; if (!seen[i]) { - exclude = last_exclude_matching(dir, full_path, &dtype); + exclude = last_exclude_matching(dir, &the_index, + full_path, &dtype); } if (!quiet && (exclude || show_non_matching)) output_exclude(pathspec.items[i].original, exclude); diff --git a/builtin/checkout.c b/builtin/checkout.c index 81f07c3ef2..a6b2af39d3 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -21,12 +21,31 @@ #include "submodule-config.h" #include "submodule.h" +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; + static const char * const checkout_usage[] = { N_("git checkout [<options>] <branch>"), N_("git checkout [<options>] [<branch>] -- <file>..."), NULL, }; +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} + struct checkout_opts { int patch_mode; int quiet; @@ -216,22 +235,24 @@ static int checkout_merged(int pos, const struct checkout *state) /* * NEEDSWORK: * There is absolutely no reason to write this as a blob object - * and create a phony cache entry just to leak. This hack is - * primarily to get to the write_entry() machinery that massages - * the contents to work-tree format and writes out which only - * allows it for a cache entry. The code in write_entry() needs - * to be refactored to allow us to feed a <buffer, size, mode> - * instead of a cache entry. Such a refactoring would help - * merge_recursive as well (it also writes the merge result to the - * object database even when it may contain conflicts). + * and create a phony cache entry. This hack is primarily to get + * to the write_entry() machinery that massages the contents to + * work-tree format and writes out which only allows it for a + * cache entry. The code in write_entry() needs to be refactored + * to allow us to feed a <buffer, size, mode> instead of a cache + * entry. Such a refactoring would help merge_recursive as well + * (it also writes the merge result to the object database even + * when it may contain conflicts). */ if (write_sha1_file(result_buf.ptr, result_buf.size, blob_type, oid.hash)) die(_("Unable to add merge result for '%s'"), path); + free(result_buf.ptr); ce = make_cache_entry(mode, oid.hash, path, 2, 0); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); status = checkout_entry(ce, state, NULL); + free(ce); return status; } @@ -374,7 +395,7 @@ static int checkout_paths(const struct checkout_opts *opts, die(_("unable to write new index file")); read_ref_full("HEAD", 0, rev.hash, NULL); - head = lookup_commit_reference_gently(rev.hash, 1); + head = lookup_commit_reference_gently(&rev, 1); errs |= post_checkout_hook(head, head, 0); return errs; @@ -508,10 +529,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.oid.hash : - EMPTY_TREE_SHA1_BIN); + &old->commit->object.oid : + &empty_tree_oid); init_tree_desc(&trees[0], tree->buffer, tree->size); - tree = parse_tree_indirect(new->commit->object.oid.hash); + tree = parse_tree_indirect(&new->commit->object.oid); init_tree_desc(&trees[1], tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); @@ -702,7 +723,7 @@ static int add_pending_uninteresting_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data) { - add_pending_sha1(cb_data, refname, oid->hash, UNINTERESTING); + add_pending_oid(cb_data, refname, oid, UNINTERESTING); return 0; } @@ -788,7 +809,7 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new) 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.oid.hash, UNINTERESTING); + add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING); refs = revs.pending; revs.leak_pending = 1; @@ -814,7 +835,8 @@ static int switch_branches(const struct checkout_opts *opts, int flag, writeout_error = 0; memset(&old, 0, sizeof(old)); old.path = path_to_free = resolve_refdup("HEAD", 0, rev.hash, &flag); - old.commit = lookup_commit_reference_gently(rev.hash, 1); + if (old.path) + old.commit = lookup_commit_reference_gently(&rev, 1); if (!(flag & REF_ISSYMREF)) old.path = NULL; @@ -889,11 +911,10 @@ static int check_tracking_name(struct remote *remote, void *cb_data) static const char *unique_tracking_name(const char *name, struct object_id *oid) { struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 }; - char src_ref[PATH_MAX]; - snprintf(src_ref, PATH_MAX, "refs/heads/%s", name); - cb_data.src_ref = src_ref; + cb_data.src_ref = xstrfmt("refs/heads/%s", name); cb_data.dst_oid = oid; for_each_remote(check_tracking_name, &cb_data); + free(cb_data.src_ref); if (cb_data.unique) return cb_data.dst_ref; free(cb_data.dst_ref); @@ -1029,10 +1050,10 @@ static int parse_branchname_arg(int argc, const char **argv, else new->path = NULL; /* not an existing branch */ - new->commit = lookup_commit_reference_gently(rev->hash, 1); + new->commit = lookup_commit_reference_gently(rev, 1); if (!new->commit) { /* not a commit */ - *source_tree = parse_tree_indirect(rev->hash); + *source_tree = parse_tree_indirect(rev); } else { parse_commit_or_die(new->commit); *source_tree = new->commit->tree; @@ -1163,6 +1184,9 @@ 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")), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, + "checkout", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")), OPT_END(), }; @@ -1193,6 +1217,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) git_xmerge_config("merge.conflictstyle", conflict_style, NULL); } + if (recurse_submodules != RECURSE_SUBMODULES_OFF) { + git_config(submodule_config, NULL); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) + set_config_update_recurse_submodules(recurse_submodules); + } + if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1) die(_("-b, -B and --orphan are mutually exclusive")); @@ -1259,9 +1289,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) * new_branch && argc > 1 will be caught later. */ if (opts.new_branch && argc == 1) - die(_("Cannot update paths and switch to branch '%s' at the same time.\n" - "Did you intend to checkout '%s' which can not be resolved as commit?"), - opts.new_branch, argv[0]); + die(_("'%s' is not a commit and a branch '%s' cannot be created from it"), + argv[0], opts.new_branch); if (opts.force_detach) die(_("git checkout: --detach does not take a path argument '%s'"), diff --git a/builtin/clean.c b/builtin/clean.c index d861f836a2..329b68c40b 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -683,7 +683,7 @@ static int filter_by_patterns_cmd(void) for_each_string_list_item(item, &del_list) { int dtype = DT_UNKNOWN; - if (is_excluded(&dir, item->string, &dtype)) { + if (is_excluded(&dir, &the_index, item->string, &dtype)) { *item->string = '\0'; changed++; } @@ -930,7 +930,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) PATHSPEC_PREFER_CWD, prefix, argv); - fill_directory(&dir, &pathspec); + fill_directory(&dir, &the_index, &pathspec); for (i = 0; i < dir.nr; i++) { struct dir_entry *ent = dir.entries[i]; diff --git a/builtin/clone.c b/builtin/clone.c index b4c929bb8a..743f16ae2a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -39,7 +39,8 @@ static const char * const builtin_clone_usage[] = { }; static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1; -static int option_local = -1, option_no_hardlinks, option_shared, option_recursive; +static int option_local = -1, option_no_hardlinks, option_shared; +static int option_no_tags; static int option_shallow_submodules; static int deepen; static char *option_template, *option_depth, *option_since; @@ -56,6 +57,21 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP; static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP; static int option_dissociate; static int max_jobs = -1; +static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP; + +static int recurse_submodules_cb(const struct option *opt, + const char *arg, int unset) +{ + if (unset) + string_list_clear((struct string_list *)opt->value, 0); + else if (arg) + string_list_append((struct string_list *)opt->value, arg); + else + string_list_append((struct string_list *)opt->value, + (const char *)opt->defval); + + return 0; +} static struct option builtin_clone_options[] = { OPT__VERBOSITY(&option_verbosity), @@ -74,10 +90,13 @@ static struct option builtin_clone_options[] = { N_("don't use local hardlinks, always copy")), OPT_BOOL('s', "shared", &option_shared, N_("setup as shared repository")), - OPT_BOOL(0, "recursive", &option_recursive, - N_("initialize submodules in the clone")), - OPT_BOOL(0, "recurse-submodules", &option_recursive, - N_("initialize submodules in the clone")), + { OPTION_CALLBACK, 0, "recursive", &option_recurse_submodules, + N_("pathspec"), N_("initialize submodules in the clone"), + PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb, + (intptr_t)"." }, + { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules, + N_("pathspec"), N_("initialize submodules in the clone"), + PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." }, OPT_INTEGER('j', "jobs", &max_jobs, N_("number of submodules cloned in parallel")), OPT_STRING(0, "template", &option_template, N_("template-directory"), @@ -102,6 +121,8 @@ static struct option builtin_clone_options[] = { N_("deepen history of shallow clone, excluding rev")), OPT_BOOL(0, "single-branch", &option_single_branch, N_("clone only one branch, HEAD or --branch")), + OPT_BOOL(0, "no-tags", &option_no_tags, + N_("don't clone any tags, and make later fetches not to follow them")), OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, N_("any cloned submodules will be shallow")), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), @@ -545,7 +566,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs, } else get_fetch_map(refs, refspec, &tail, 0); - if (!option_mirror && !option_single_branch) + if (!option_mirror && !option_single_branch && !option_no_tags) get_fetch_map(refs, tag_refspec, &tail, 0); return local_refs; @@ -634,7 +655,7 @@ static void update_remote_refs(const struct ref *refs, if (refs) { write_remote_refs(mapped_refs); - if (option_single_branch) + if (option_single_branch && !option_no_tags) write_followtags(refs, msg); } @@ -664,7 +685,7 @@ static void update_head(const struct ref *our, const struct ref *remote, install_branch_config(0, head, option_origin, our->name); } } else if (our) { - struct commit *c = lookup_commit_reference(our->old_oid.hash); + struct commit *c = lookup_commit_reference(&our->old_oid); /* --branch specifies a non-branch (i.e. tags), detach HEAD */ update_ref(msg, "HEAD", c->object.oid.hash, NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); @@ -721,7 +742,7 @@ static int checkout(int submodule_progress) opts.src_index = &the_index; opts.dst_index = &the_index; - tree = parse_tree_indirect(oid.hash); + tree = parse_tree_indirect(&oid); parse_tree(tree); init_tree_desc(&t, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts) < 0) @@ -733,7 +754,7 @@ static int checkout(int submodule_progress) err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1), oid_to_hex(&oid), "1", NULL); - if (!err && option_recursive) { + if (!err && (option_recurse_submodules.nr > 0)) { struct argv_array args = ARGV_ARRAY_INIT; argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); @@ -755,7 +776,9 @@ static int checkout(int submodule_progress) static int write_one_config(const char *key, const char *value, void *data) { - return git_config_set_multivar_gently(key, value ? value : "true", "^$", 0); + return git_config_set_multivar_gently(key, + value ? value : "true", + CONFIG_REGEX_NONE, 0); } static void write_config(struct string_list *config) @@ -957,7 +980,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix) fprintf(stderr, _("Cloning into '%s'...\n"), dir); } - if (option_recursive) { + if (option_recurse_submodules.nr > 0) { + struct string_list_item *item; + struct strbuf sb = STRBUF_INIT; + + /* remove duplicates */ + string_list_sort(&option_recurse_submodules); + string_list_remove_duplicates(&option_recurse_submodules, 0); + + /* + * NEEDSWORK: In a multi-working-tree world, this needs to be + * set in the per-worktree config. + */ + for_each_string_list_item(item, &option_recurse_submodules) { + strbuf_addf(&sb, "submodule.active=%s", + item->string); + string_list_append(&option_config, + strbuf_detach(&sb, NULL)); + } + if (option_required_reference.nr && option_optional_reference.nr) die(_("clone --recursive is not compatible with " @@ -999,6 +1040,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set(key.buf, repo); strbuf_reset(&key); + if (option_no_tags) { + strbuf_addf(&key, "remote.%s.tagOpt", option_origin); + git_config_set(key.buf, "--no-tags"); + strbuf_reset(&key); + } + if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 605017261c..f39c2b2737 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -58,7 +58,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) if (get_sha1_commit(argv[i], oid.hash)) die("Not a valid object name %s", argv[i]); assert_sha1_type(oid.hash, OBJ_COMMIT); - new_parent(lookup_commit(oid.hash), &parents); + new_parent(lookup_commit(&oid), &parents); continue; } diff --git a/builtin/commit.c b/builtin/commit.c index 4e288bc513..da1ba4c862 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -313,7 +313,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.oid.hash); + tree = parse_tree_indirect(¤t_head->object.oid); if (!tree) die(_("failed to unpack HEAD tree object")); parse_tree(tree); @@ -821,9 +821,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix, "If this is not correct, please remove the file\n" " %s\n" "and try again.\n"), - git_path(whence == FROM_MERGE - ? "MERGE_HEAD" - : "CHERRY_PICK_HEAD")); + whence == FROM_MERGE ? + git_path_merge_head() : + git_path_cherry_pick_head()); } fprintf(s->fp, "\n"); @@ -1263,6 +1263,10 @@ static int parse_status_slot(const char *slot) return WT_STATUS_NOBRANCH; if (!strcasecmp(slot, "unmerged")) return WT_STATUS_UNMERGED; + if (!strcasecmp(slot, "localBranch")) + return WT_STATUS_LOCAL_BRANCH; + if (!strcasecmp(slot, "remoteBranch")) + return WT_STATUS_REMOTE_BRANCH; return -1; } @@ -1404,7 +1408,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) static const char *implicit_ident_advice(void) { - char *user_config = expand_user_path("~/.gitconfig"); + char *user_config = expand_user_path("~/.gitconfig", 0); char *xdg_config = xdg_config_home("config"); int config_exists = file_exists(user_config) || file_exists(xdg_config); @@ -1430,7 +1434,7 @@ static void print_summary(const char *prefix, const struct object_id *oid, struct strbuf author_ident = STRBUF_INIT; struct strbuf committer_ident = STRBUF_INIT; - commit = lookup_commit(oid->hash); + commit = lookup_commit(oid); if (!commit) die(_("couldn't look up newly created commit")); if (parse_commit(commit)) @@ -1654,7 +1658,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (get_sha1("HEAD", oid.hash)) current_head = NULL; else { - current_head = lookup_commit_or_die(oid.hash, "HEAD"); + current_head = lookup_commit_or_die(&oid, "HEAD"); if (parse_commit(current_head)) die(_("could not parse HEAD commit")); } @@ -1735,7 +1739,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (verbose || /* Truncate the message just before the diff, if any. */ cleanup_mode == CLEANUP_SCISSORS) - wt_status_truncate_message_at_cut_line(&sb); + strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len)); if (cleanup_mode != CLEANUP_NONE) strbuf_stripspace(&sb, cleanup_mode == CLEANUP_ALL); @@ -1758,7 +1762,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) append_merge_tag_headers(parents, &tail); } - if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1, + if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->oid.hash, parents, oid.hash, author_ident.buf, sign_commit, extra)) { rollback_index_files(); die(_("failed to write commit object")); diff --git a/builtin/config.c b/builtin/config.c index 4f49a0edb9..7f6c25d4d9 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -26,7 +26,8 @@ static int use_global_config, use_system_config, use_local_config; static struct git_config_source given_config_source; static int actions, types; static int end_null; -static int respect_includes = -1; +static int respect_includes_opt = -1; +static struct config_options config_options; static int show_origin; #define ACTION_GET (1<<0) @@ -81,7 +82,7 @@ static struct option builtin_config_options[] = { OPT_GROUP(N_("Other")), OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), - OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")), + OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")), OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")), OPT_END(), }; @@ -242,7 +243,7 @@ static int get_value(const char *key_, const char *regex_) } git_config_with_options(collect_config, &values, - &given_config_source, respect_includes); + &given_config_source, &config_options); ret = !values.nr; @@ -320,7 +321,7 @@ static void get_color(const char *var, const char *def_color) get_color_found = 0; parsed_color[0] = '\0'; git_config_with_options(git_get_color_config, NULL, - &given_config_source, respect_includes); + &given_config_source, &config_options); if (!get_color_found && def_color) { if (color_parse(def_color, parsed_color) < 0) @@ -352,7 +353,7 @@ static int get_colorbool(const char *var, int print) get_diff_color_found = -1; get_color_ui_found = -1; git_config_with_options(git_get_colorbool_config, NULL, - &given_config_source, respect_includes); + &given_config_source, &config_options); if (get_colorbool_found < 0) { if (!strcmp(get_colorbool_slot, "color.diff")) @@ -441,7 +442,7 @@ static int get_urlmatch(const char *var, const char *url) } git_config_with_options(urlmatch_config_entry, &config, - &given_config_source, respect_includes); + &given_config_source, &config_options); ret = !values.nr; @@ -495,6 +496,9 @@ int cmd_config(int argc, const char **argv, const char *prefix) usage_with_options(builtin_config_usage, builtin_config_options); } + if (use_local_config && nongit) + die(_("--local can only be used inside a git repository")); + if (given_config_source.file && !strcmp(given_config_source.file, "-")) { given_config_source.file = NULL; @@ -502,7 +506,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) } if (use_global_config) { - char *user_config = expand_user_path("~/.gitconfig"); + char *user_config = expand_user_path("~/.gitconfig", 0); char *xdg_config = xdg_config_home("config"); if (!user_config) @@ -530,8 +534,10 @@ int cmd_config(int argc, const char **argv, const char *prefix) prefix_filename(prefix, given_config_source.file); } - if (respect_includes == -1) - respect_includes = !given_config_source.file; + if (respect_includes_opt == -1) + config_options.respect_includes = !given_config_source.file; + else + config_options.respect_includes = respect_includes_opt; if (end_null) { term = '\0'; @@ -578,7 +584,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_argc(argc, 0, 0); if (git_config_with_options(show_all_config, NULL, &given_config_source, - respect_includes) < 0) { + &config_options) < 0) { if (given_config_source.file) die_errno("unable to read config file '%s'", given_config_source.file); @@ -597,8 +603,9 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (given_config_source.blob) die("editing blobs is not supported"); git_config(git_default_config, NULL); - config_file = xstrdup(given_config_source.file ? - given_config_source.file : git_path("config")); + config_file = given_config_source.file ? + xstrdup(given_config_source.file) : + git_pathdup("config"); if (use_global_config) { int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd >= 0) { diff --git a/builtin/describe.c b/builtin/describe.c index a5cd8c513f..893c8789f4 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -79,13 +79,13 @@ static int replace_name(struct commit_name *e, struct tag *t; if (!e->tag) { - t = lookup_tag(e->oid.hash); + t = lookup_tag(&e->oid); if (!t || parse_tag(t)) return 1; e->tag = t; } - t = lookup_tag(oid->hash); + t = lookup_tag(oid); if (!t || parse_tag(t)) return 0; *tag = t; @@ -245,7 +245,7 @@ static unsigned long finish_depth_computation( static void display_name(struct commit_name *n) { if (n->prio == 2 && !n->tag) { - n->tag = lookup_tag(n->oid.hash); + n->tag = lookup_tag(&n->oid); if (!n->tag || parse_tag(n->tag)) die(_("annotated tag %s not available"), n->path); } @@ -281,7 +281,7 @@ static void describe(const char *arg, int last_one) if (get_oid(arg, &oid)) die(_("Not a valid object name %s"), arg); - cmit = lookup_commit_reference(oid.hash); + cmit = lookup_commit_reference(&oid); if (!cmit) die(_("%s is not a valid '%s' object"), arg, commit_type); @@ -309,7 +309,7 @@ static void describe(const char *arg, int last_one) struct commit *c; struct commit_name *n = hashmap_iter_first(&names, &iter); for (; n; n = hashmap_iter_next(&iter)) { - c = lookup_commit_reference_gently(n->peeled.hash, 1); + c = lookup_commit_reference_gently(&n->peeled, 1); if (c) c->util = n; } diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 326f88b657..5ea1c14317 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -9,7 +9,7 @@ static struct rev_info log_tree_opt; static int diff_tree_commit_sha1(const struct object_id *oid) { - struct commit *commit = lookup_commit_reference(oid->hash); + struct commit *commit = lookup_commit_reference(oid); if (!commit) return -1; return log_tree_commit(&log_tree_opt, commit); @@ -23,7 +23,7 @@ static int stdin_diff_commit(struct commit *commit, const char *p) /* Graft the fake parents locally to the commit */ while (isspace(*p++) && !parse_oid_hex(p, &oid, &p)) { - struct commit *parent = lookup_commit(oid.hash); + struct commit *parent = lookup_commit(&oid); if (!pptr) { /* Free the real parent list */ free_commit_list(commit->parents); @@ -44,7 +44,7 @@ static int stdin_diff_trees(struct tree *tree1, const char *p) struct tree *tree2; if (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p) return error("Need exactly two trees, separated by a space"); - tree2 = lookup_tree(oid.hash); + tree2 = lookup_tree(&oid); if (!tree2 || parse_tree(tree2)) return -1; printf("%s %s\n", oid_to_hex(&tree1->object.oid), @@ -67,7 +67,7 @@ static int diff_tree_stdin(char *line) line[len-1] = 0; if (parse_oid_hex(line, &oid, &p)) return -1; - obj = parse_object(oid.hash); + obj = parse_object(&oid); if (!obj) return -1; if (obj->type == OBJ_COMMIT) diff --git a/builtin/diff.c b/builtin/diff.c index 3d64b85337..8c03ddaf58 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -21,7 +21,7 @@ #define DIFF_NO_INDEX_IMPLICIT 2 struct blobinfo { - unsigned char sha1[20]; + struct object_id oid; const char *name; unsigned mode; }; @@ -31,22 +31,22 @@ static const char builtin_diff_usage[] = static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, - const unsigned char *old_sha1, - const unsigned char *new_sha1, - int old_sha1_valid, - int new_sha1_valid, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, + int new_oid_valid, const char *old_name, const char *new_name) { struct diff_filespec *one, *two; - if (!is_null_sha1(old_sha1) && !is_null_sha1(new_sha1) && - !hashcmp(old_sha1, new_sha1) && (old_mode == new_mode)) + if (!is_null_oid(old_oid) && !is_null_oid(new_oid) && + !oidcmp(old_oid, new_oid) && (old_mode == new_mode)) return; if (DIFF_OPT_TST(opt, REVERSE_DIFF)) { SWAP(old_mode, new_mode); - SWAP(old_sha1, new_sha1); + SWAP(old_oid, new_oid); SWAP(old_name, new_name); } @@ -57,8 +57,8 @@ static void stuff_change(struct diff_options *opt, one = alloc_filespec(old_name); two = alloc_filespec(new_name); - fill_filespec(one, old_sha1, old_sha1_valid, old_mode); - fill_filespec(two, new_sha1, new_sha1_valid, new_mode); + fill_filespec(one, old_oid->hash, old_oid_valid, old_mode); + fill_filespec(two, new_oid->hash, new_oid_valid, new_mode); diff_queue(&diff_queued_diff, one, two); } @@ -89,7 +89,7 @@ static int builtin_diff_b_f(struct rev_info *revs, stuff_change(&revs->diffopt, blob[0].mode, canon_mode(st.st_mode), - blob[0].sha1, null_sha1, + &blob[0].oid, &null_oid, 1, 0, path, path); diffcore_std(&revs->diffopt); @@ -114,7 +114,7 @@ static int builtin_diff_blobs(struct rev_info *revs, stuff_change(&revs->diffopt, blob[0].mode, blob[1].mode, - blob[0].sha1, blob[1].sha1, + &blob[0].oid, &blob[1].oid, 1, 1, blob[0].name, blob[1].name); diffcore_std(&revs->diffopt); @@ -160,7 +160,7 @@ static int builtin_diff_tree(struct rev_info *revs, struct object_array_entry *ent0, struct object_array_entry *ent1) { - const unsigned char *(sha1[2]); + const struct object_id *(oid[2]); int swap = 0; if (argc > 1) @@ -172,9 +172,9 @@ static int builtin_diff_tree(struct rev_info *revs, */ if (ent1->item->flags & UNINTERESTING) swap = 1; - sha1[swap] = ent0->item->oid.hash; - sha1[1 - swap] = ent1->item->oid.hash; - diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt); + oid[swap] = &ent0->item->oid; + oid[1 - swap] = &ent1->item->oid; + diff_tree_sha1(oid[0]->hash, oid[1]->hash, "", &revs->diffopt); log_tree_diff_flush(revs); return 0; } @@ -184,7 +184,7 @@ static int builtin_diff_combined(struct rev_info *revs, struct object_array_entry *ent, int ents) { - struct sha1_array parents = SHA1_ARRAY_INIT; + struct oid_array parents = OID_ARRAY_INIT; int i; if (argc > 1) @@ -193,10 +193,10 @@ 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->oid.hash); + oid_array_append(&parents, &ent[i].item->oid); diff_tree_combined(ent[0].item->oid.hash, &parents, revs->dense_combined_merges, revs); - sha1_array_clear(&parents); + oid_array_clear(&parents); return 0; } @@ -381,7 +381,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) add_head_to_pending(&rev); if (!rev.pending.nr) { struct tree *tree; - tree = lookup_tree(EMPTY_TREE_SHA1_BIN); + tree = lookup_tree(&empty_tree_oid); add_pending_object(&rev, &tree->object, "HEAD"); } break; @@ -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->oid.hash); + obj = parse_object(&obj->oid); 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->oid.hash); + oidcpy(&blob[blobs].oid, &obj->oid); blob[blobs].name = name; blob[blobs].mode = entry->mode; blobs++; diff --git a/builtin/difftool.c b/builtin/difftool.c index 25e54ad3ed..b9a892f269 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -226,6 +226,7 @@ static void changed_files(struct hashmap *result, const char *index_path, hashmap_entry_init(entry, strhash(buf.buf)); hashmap_add(result, entry); } + fclose(fp); if (finish_command(&diff_files)) die("diff-files did not exit properly"); strbuf_release(&index_env); @@ -297,6 +298,19 @@ static char *get_symlink(const struct object_id *oid, const char *path) return data; } +static int checkout_path(unsigned mode, struct object_id *oid, + const char *path, const struct checkout *state) +{ + struct cache_entry *ce; + int ret; + + ce = make_cache_entry(mode, oid->hash, path, 0, 0); + ret = checkout_entry(ce, state, NULL); + + free(ce); + return ret; +} + static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, int argc, const char **argv) { @@ -305,8 +319,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT; struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT; struct strbuf wtdir = STRBUF_INIT; + char *lbase_dir, *rbase_dir; size_t ldir_len, rdir_len, wtdir_len; - struct cache_entry *ce = xcalloc(1, sizeof(ce) + PATH_MAX + 1); const char *workdir, *tmp; int ret = 0, i; FILE *fp; @@ -339,11 +353,11 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, memset(&wtindex, 0, sizeof(wtindex)); memset(&lstate, 0, sizeof(lstate)); - lstate.base_dir = ldir.buf; + lstate.base_dir = lbase_dir = xstrdup(ldir.buf); lstate.base_dir_len = ldir.len; lstate.force = 1; memset(&rstate, 0, sizeof(rstate)); - rstate.base_dir = rdir.buf; + rstate.base_dir = rbase_dir = xstrdup(rdir.buf); rstate.base_dir_len = rdir.len; rstate.force = 1; @@ -377,7 +391,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct object_id loid, roid; char status; const char *src_path, *dst_path; - size_t src_path_len, dst_path_len; if (starts_with(info.buf, "::")) die(N_("combined diff formats('-c' and '--cc') are " @@ -390,17 +403,14 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, if (strbuf_getline_nul(&lpath, fp)) break; src_path = lpath.buf; - src_path_len = lpath.len; i++; if (status != 'C' && status != 'R') { dst_path = src_path; - dst_path_len = src_path_len; } else { if (strbuf_getline_nul(&rpath, fp)) break; dst_path = rpath.buf; - dst_path_len = rpath.len; } if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) { @@ -430,12 +440,10 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } if (lmode && status != 'C') { - ce->ce_mode = lmode; - oidcpy(&ce->oid, &loid); - strcpy(ce->name, src_path); - ce->ce_namelen = src_path_len; - if (checkout_entry(ce, &lstate, NULL)) - return error("could not write '%s'", src_path); + if (checkout_path(lmode, &loid, src_path, &lstate)) { + ret = error("could not write '%s'", src_path); + goto finish; + } } if (rmode && !S_ISLNK(rmode)) { @@ -451,13 +459,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, hashmap_add(&working_tree_dups, entry); if (!use_wt_file(workdir, dst_path, &roid)) { - ce->ce_mode = rmode; - oidcpy(&ce->oid, &roid); - strcpy(ce->name, dst_path); - ce->ce_namelen = dst_path_len; - if (checkout_entry(ce, &rstate, NULL)) - return error("could not write '%s'", - dst_path); + if (checkout_path(rmode, &roid, dst_path, + &rstate)) { + ret = error("could not write '%s'", + dst_path); + goto finish; + } } else if (!is_null_oid(&roid)) { /* * Changes in the working tree need special @@ -472,10 +479,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, ADD_CACHE_JUST_APPEND); add_path(&rdir, rdir_len, dst_path); - if (ensure_leading_directories(rdir.buf)) - return error("could not create " - "directory for '%s'", - dst_path); + if (ensure_leading_directories(rdir.buf)) { + ret = error("could not create " + "directory for '%s'", + dst_path); + goto finish; + } add_path(&wtdir, wtdir_len, dst_path); if (symlinks) { if (symlink(wtdir.buf, rdir.buf)) { @@ -496,13 +505,15 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } } + fclose(fp); + fp = NULL; if (finish_command(&child)) { ret = error("error occurred running diff --raw"); goto finish; } if (!i) - return 0; + goto finish; /* * Changes to submodules require special treatment.This loop writes a @@ -625,7 +636,11 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, exit_cleanup(tmpdir, rc); finish: - free(ce); + if (fp) + fclose(fp); + + free(lbase_dir); + free(rbase_dir); strbuf_release(&ldir); strbuf_release(&rdir); strbuf_release(&wtdir); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index e0220630d0..24e29ad7ea 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -232,7 +232,7 @@ static void export_blob(const struct object_id *oid) if (anonymize) { buf = anonymize_blob(&size); - object = (struct object *)lookup_blob(oid->hash); + object = (struct object *)lookup_blob(oid); eaten = 0; } else { buf = read_sha1_file(oid->hash, &type, &size); @@ -240,7 +240,7 @@ static void export_blob(const struct object_id *oid) die ("Could not read blob %s", oid_to_hex(oid)); if (check_sha1_signature(oid->hash, buf, size, typename(type)) < 0) die("sha1 mismatch in blob %s", oid_to_hex(oid)); - object = parse_object_buffer(oid->hash, type, size, buf, &eaten); + object = parse_object_buffer(oid, type, size, buf, &eaten); } if (!object) @@ -734,6 +734,7 @@ static void handle_tag(const char *name, struct tag *tag) oid_to_hex(&tag->object.oid)); case DROP: /* Ignore this tag altogether */ + free(buf); return; case REWRITE: if (tagged->type != OBJ_COMMIT) { @@ -765,6 +766,7 @@ static void handle_tag(const char *name, struct tag *tag) (int)(tagger_end - tagger), tagger, tagger == tagger_end ? "" : "\n", (int)message_size, (int)message_size, message ? message : ""); + free(buf); } static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name) @@ -777,7 +779,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.oid.hash); + parse_object(&tag->object.oid); string_list_append(&extra_refs, full_name)->util = tag; tag = (struct tag *)tag->tagged; } @@ -938,7 +940,7 @@ static void import_marks(char *input_file) /* only commits */ continue; - commit = lookup_commit(oid.hash); + commit = lookup_commit(&oid); if (!commit) die("not a commit? can't happen: %s", oid_to_hex(&oid)); diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 2a1c1c213f..366b9d13f9 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -50,7 +50,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) char **pack_lockfile_ptr = NULL; struct child_process *conn; struct fetch_pack_args args; - struct sha1_array shallow = SHA1_ARRAY_INIT; + struct oid_array shallow = OID_ARRAY_INIT; struct string_list deepen_not = STRING_LIST_INIT_DUP; packet_trace_identity("fetch-pack"); diff --git a/builtin/fetch.c b/builtin/fetch.c index b5ad09d046..d4d573b985 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -421,7 +421,7 @@ static int s_update_ref(const char *action, struct ref *ref, int check_old) { - char msg[1024]; + char *msg; char *rla = getenv("GIT_REFLOG_ACTION"); struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; @@ -431,7 +431,7 @@ static int s_update_ref(const char *action, return 0; if (!rla) rla = default_rla.buf; - snprintf(msg, sizeof(msg), "%s: %s", rla, action); + msg = xstrfmt("%s: %s", rla, action); transaction = ref_transaction_begin(&err); if (!transaction || @@ -449,11 +449,13 @@ static int s_update_ref(const char *action, ref_transaction_free(transaction); strbuf_release(&err); + free(msg); return 0; fail: ref_transaction_free(transaction); error("%s", err.buf); strbuf_release(&err); + free(msg); return df_conflict ? STORE_REF_ERROR_DF_CONFLICT : STORE_REF_ERROR_OTHER; } @@ -634,8 +636,8 @@ static int update_local_ref(struct ref *ref, return r; } - current = lookup_commit_reference_gently(ref->old_oid.hash, 1); - updated = lookup_commit_reference_gently(ref->new_oid.hash, 1); + current = lookup_commit_reference_gently(&ref->old_oid, 1); + updated = lookup_commit_reference_gently(&ref->new_oid, 1); if (!current || !updated) { const char *msg; const char *what; @@ -659,7 +661,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_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref(msg, ref, 0); format_display(display, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, @@ -675,7 +677,7 @@ static int update_local_ref(struct ref *ref, 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_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("fast-forward", ref, 1); format_display(display, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, @@ -690,7 +692,7 @@ static int update_local_ref(struct ref *ref, 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_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("forced-update", ref, 1); format_display(display, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), @@ -768,7 +770,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, continue; } - commit = lookup_commit_reference_gently(rm->old_oid.hash, 1); + commit = lookup_commit_reference_gently(&rm->old_oid, + 1); if (!commit) rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE; diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 6faa3c0d24..70137b0b7e 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -341,7 +341,7 @@ static void shortlog(const char *name, const struct object_id *oid = &origin_data->oid; int limit = opts->shortlog_len; - branch = deref_tag(parse_object(oid->hash), oid_to_hex(oid), GIT_SHA1_HEXSZ); + branch = deref_tag(parse_object(oid), oid_to_hex(oid), GIT_SHA1_HEXSZ); if (!branch || branch->type != OBJ_COMMIT) return; @@ -559,14 +559,14 @@ static void find_merge_parents(struct merge_parents *result, * "name" here and we do not want to contaminate its * util field yet. */ - obj = parse_object(oid.hash); + obj = parse_object(&oid); parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT); if (!parent) continue; commit_list_insert(parent, &parents); add_merge_parent(result, &obj->oid, &parent->object.oid); } - head_commit = lookup_commit(head->hash); + head_commit = lookup_commit(head); if (head_commit) commit_list_insert(head_commit, &parents); parents = reduce_heads(parents); @@ -633,7 +633,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out, struct commit *head; struct rev_info rev; - head = lookup_commit_or_die(head_oid.hash, "HEAD"); + head = lookup_commit_or_die(&head_oid, "HEAD"); init_revisions(&rev, NULL); rev.commit_format = CMIT_FMT_ONELINE; rev.ignore_merges = 1; diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index df41fa0350..eca365bf89 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -8,8 +8,8 @@ static char const * const for_each_ref_usage[] = { N_("git for-each-ref [<options>] [<pattern>]"), N_("git for-each-ref [--points-at <object>]"), - N_("git for-each-ref [(--merged | --no-merged) [<object>]]"), - N_("git for-each-ref [--contains [<object>]]"), + N_("git for-each-ref [(--merged | --no-merged) [<commit>]]"), + N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"), NULL }; @@ -43,6 +43,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) OPT_MERGED(&filter, N_("print only refs that are merged")), OPT_NO_MERGED(&filter, N_("print only refs that are not merged")), OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")), + OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")), OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")), OPT_END(), }; diff --git a/builtin/fsck.c b/builtin/fsck.c index f76e4163ab..cb2ba6cd1b 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -377,7 +377,7 @@ static int fsck_obj(struct object *obj) return 0; } -static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type, +static int fsck_obj_buffer(const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten) { /* @@ -385,10 +385,10 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type, * verify_packfile(), data_valid variable for details. */ struct object *obj; - obj = parse_object_buffer(sha1, type, size, buffer, eaten); + obj = parse_object_buffer(oid, type, size, buffer, eaten); if (!obj) { errors_found |= ERROR_OBJECT; - return error("%s: object corrupt or missing", sha1_to_hex(sha1)); + return error("%s: object corrupt or missing", oid_to_hex(oid)); } obj->flags = HAS_OBJ; return fsck_obj(obj); @@ -397,7 +397,7 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type, static int default_refs; static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, - unsigned long timestamp) + timestamp_t timestamp) { struct object *obj; @@ -407,7 +407,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, if (timestamp && name_objects) add_decoration(fsck_walk_options.object_names, obj, - xstrfmt("%s@{%ld}", refname, timestamp)); + xstrfmt("%s@{%"PRItime"}", refname, timestamp)); obj->used = 1; mark_object_reachable(obj); } else { @@ -418,7 +418,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, } static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid, - const char *email, unsigned long timestamp, int tz, + const char *email, timestamp_t timestamp, int tz, const char *message, void *cb_data) { const char *refname = cb_data; @@ -444,7 +444,7 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, { struct object *obj; - obj = parse_object(oid->hash); + obj = parse_object(oid); if (!obj) { error("%s: invalid sha1 pointer %s", refname, oid_to_hex(oid)); errors_found |= ERROR_REACHABLE; @@ -506,7 +506,7 @@ static struct object *parse_loose_object(const struct object_id *oid, if (!contents && type != OBJ_BLOB) die("BUG: read_loose_object streamed a non-blob"); - obj = parse_object_buffer(oid->hash, type, size, contents, &eaten); + obj = parse_object_buffer(oid, type, size, contents, &eaten); if (!eaten) free(contents); @@ -599,10 +599,10 @@ static int fsck_cache_tree(struct cache_tree *it) fprintf(stderr, "Checking cache tree\n"); if (0 <= it->entry_count) { - struct object *obj = parse_object(it->sha1); + struct object *obj = parse_object(&it->oid); if (!obj) { error("%s: invalid sha1 pointer in cache-tree", - sha1_to_hex(it->sha1)); + oid_to_hex(&it->oid)); errors_found |= ERROR_REFS; return 1; } @@ -771,6 +771,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } if (keep_cache_objects) { + verify_index_checksum = 1; read_cache(); for (i = 0; i < active_nr; i++) { unsigned int mode; @@ -780,7 +781,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) mode = active_cache[i]->ce_mode; if (S_ISGITLINK(mode)) continue; - blob = lookup_blob(active_cache[i]->oid.hash); + blob = lookup_blob(&active_cache[i]->oid); if (!blob) continue; obj = &blob->object; diff --git a/builtin/gc.c b/builtin/gc.c index c2c61a57bb..f484eda43c 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -33,7 +33,7 @@ static int aggressive_window = 250; static int gc_auto_threshold = 6700; static int gc_auto_pack_limit = 50; static int detach_auto = 1; -static unsigned long gc_log_expire_time; +static timestamp_t gc_log_expire_time; static const char *gc_log_expire = "1.day.ago"; static const char *prune_expire = "2.weeks.ago"; static const char *prune_worktrees_expire = "3.months.ago"; @@ -135,8 +135,6 @@ static int too_many_loose_objects(void) * distributed, we can check only one and get a reasonable * estimate. */ - char path[PATH_MAX]; - const char *objdir = get_object_directory(); DIR *dir; struct dirent *ent; int auto_threshold; @@ -146,11 +144,7 @@ static int too_many_loose_objects(void) if (gc_auto_threshold <= 0) return 0; - if (sizeof(path) <= snprintf(path, sizeof(path), "%s/17", objdir)) { - warning(_("insanely long object directory %.*s"), 50, objdir); - return 0; - } - dir = opendir(path); + dir = opendir(git_path("objects/17")); if (!dir) return 0; @@ -238,7 +232,7 @@ static int need_to_gc(void) static const char *lock_repo_for_gc(int force, pid_t* ret_pid) { static struct lock_file lock; - char my_host[128]; + char my_host[HOST_NAME_MAX + 1]; struct strbuf sb = STRBUF_INIT; struct stat st; uintmax_t pid; @@ -250,15 +244,19 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) /* already locked */ return NULL; - if (gethostname(my_host, sizeof(my_host))) + if (xgethostname(my_host, sizeof(my_host))) xsnprintf(my_host, sizeof(my_host), "unknown"); pidfile_path = git_pathdup("gc.pid"); fd = hold_lock_file_for_update(&lock, pidfile_path, LOCK_DIE_ON_ERROR); if (!force) { - static char locking_host[128]; + static char locking_host[HOST_NAME_MAX + 1]; + static char *scan_fmt; int should_exit; + + if (!scan_fmt) + scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX); fp = fopen(pidfile_path, "r"); memset(locking_host, 0, sizeof(locking_host)); should_exit = @@ -274,7 +272,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) * running. */ time(NULL) - st.st_mtime <= 12 * 3600 && - fscanf(fp, "%"SCNuMAX" %127c", &pid, locking_host) == 2 && + fscanf(fp, scan_fmt, &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) diff --git a/builtin/grep.c b/builtin/grep.c index 837836fb3e..c6c26e9b9e 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -310,10 +310,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid, { struct strbuf pathbuf = STRBUF_INIT; - if (opt->relative && opt->prefix_length) { - quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf); - strbuf_insert(&pathbuf, 0, filename, tree_name_len); - } else if (super_prefix) { + if (super_prefix) { strbuf_add(&pathbuf, filename, tree_name_len); strbuf_addstr(&pathbuf, super_prefix); strbuf_addstr(&pathbuf, filename + tree_name_len); @@ -321,6 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid, strbuf_addstr(&pathbuf, filename); } + if (opt->relative && opt->prefix_length) { + char *name = strbuf_detach(&pathbuf, NULL); + quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf); + strbuf_insert(&pathbuf, 0, name, tree_name_len); + free(name); + } + #ifndef NO_PTHREADS if (num_threads) { add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, oid); @@ -345,12 +349,14 @@ static int grep_file(struct grep_opt *opt, const char *filename) { struct strbuf buf = STRBUF_INIT; + if (super_prefix) + strbuf_addstr(&buf, super_prefix); + strbuf_addstr(&buf, filename); + if (opt->relative && opt->prefix_length) { - quote_path_relative(filename, opt->prefix, &buf); - } else { - if (super_prefix) - strbuf_addstr(&buf, super_prefix); - strbuf_addstr(&buf, filename); + char *name = strbuf_detach(&buf, NULL); + quote_path_relative(name, opt->prefix, &buf); + free(name); } #ifndef NO_PTHREADS @@ -399,13 +405,12 @@ static void run_pager(struct grep_opt *opt, const char *prefix) } static void compile_submodule_options(const struct grep_opt *opt, - const struct pathspec *pathspec, + const char **argv, int cached, int untracked, int opt_exclude, int use_index, int pattern_type_arg) { struct grep_pat *pattern; - int i; if (recurse_submodules) argv_array_push(&submodule_options, "--recurse-submodules"); @@ -523,9 +528,8 @@ static void compile_submodule_options(const struct grep_opt *opt, /* Add Pathspecs */ argv_array_push(&submodule_options, "--"); - for (i = 0; i < pathspec->nr; i++) - argv_array_push(&submodule_options, - pathspec->items[i].original); + for (; *argv; argv++) + argv_array_push(&submodule_options, *argv); } /* @@ -538,7 +542,7 @@ static int grep_submodule_launch(struct grep_opt *opt, int status, i; const char *end_of_base; const char *name; - struct work_item *w = opt->output_priv; + struct strbuf child_output = STRBUF_INIT; end_of_base = strchr(gs->name, ':'); if (gs->identifier && end_of_base) @@ -549,6 +553,11 @@ static int grep_submodule_launch(struct grep_opt *opt, prepare_submodule_repo_env(&cp.env_array); argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT); + if (opt->relative && opt->prefix_length) + argv_array_pushf(&cp.env_array, "%s=%s", + GIT_TOPLEVEL_PREFIX_ENVIRONMENT, + opt->prefix); + /* Add super prefix */ argv_array_pushf(&cp.args, "--super-prefix=%s%s/", super_prefix ? super_prefix : "", @@ -593,14 +602,16 @@ static int grep_submodule_launch(struct grep_opt *opt, * child process. A '0' indicates a hit, a '1' indicates no hit and * anything else is an error. */ - status = capture_command(&cp, &w->out, 0); + status = capture_command(&cp, &child_output, 0); if (status && (status != 1)) { /* flush the buffer */ - write_or_die(1, w->out.buf, w->out.len); + write_or_die(1, child_output.buf, child_output.len); die("process for submodule '%s' failed with exit code: %d", gs->name, status); } + opt->output(opt, child_output.buf, child_output.len); + strbuf_release(&child_output); /* invert the return code to make a hit equal to 1 */ return !status; } @@ -616,7 +627,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1, { if (!is_submodule_initialized(path)) return 0; - if (!is_submodule_populated(path)) { + if (!is_submodule_populated_gently(path, NULL)) { /* * If searching history, check for the presense of the * submodule's gitdir before skipping the submodule. @@ -641,19 +652,14 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1, } else #endif { - struct work_item w; + struct grep_source gs; int hit; - grep_source_init(&w.source, GREP_SOURCE_SUBMODULE, + grep_source_init(&gs, GREP_SOURCE_SUBMODULE, filename, path, sha1); - strbuf_init(&w.out, 0); - opt->output_priv = &w; - hit = grep_submodule_launch(opt, &w.source); - - write_or_die(1, w.out.buf, w.out.len); + hit = grep_submodule_launch(opt, &gs); - grep_source_clear(&w.source); - strbuf_release(&w.out); + grep_source_clear(&gs); return hit; } } @@ -860,7 +866,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, if (exc_std) setup_standard_excludes(&dir); - fill_directory(&dir, pathspec); + fill_directory(&dir, &the_index, pathspec); for (i = 0; i < dir.nr; i++) { if (!dir_path_match(dir.entries[i], pathspec, 0, NULL)) continue; @@ -979,7 +985,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) OPT_SET_INT(0, "exclude-standard", &opt_exclude, N_("ignore files specified via '.gitignore'"), 1), OPT_BOOL(0, "recurse-submodules", &recurse_submodules, - N_("recursivley search in each submodule")), + N_("recursively search in each submodule")), OPT_STRING(0, "parent-basename", &parent_basename, N_("basename"), N_("prepend parent project's basename to output")), @@ -1190,7 +1196,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) break; } - object = parse_object_or_die(oid.hash, arg); + object = parse_object_or_die(&oid, arg); if (!seen_dashdash) verify_non_filename(prefix, arg); add_object_array_with_path(object, arg, &list, oc.mode, oc.path); @@ -1236,7 +1242,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (recurse_submodules) { gitmodules_config(); - compile_submodule_options(&opt, &pathspec, cached, untracked, + compile_submodule_options(&opt, argv + i, cached, untracked, opt_exclude, use_index, pattern_type_arg); } @@ -1293,6 +1299,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) hit |= wait_all(); if (hit && show_in_pager) run_pager(&opt, prefix); + clear_pathspec(&pathspec); free_grep_patterns(&opt); return !hit; } diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 88d205f858..04b9dcaf0f 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -307,14 +307,15 @@ static const char *open_pack_file(const char *pack_name) if (from_stdin) { input_fd = 0; if (!pack_name) { - static char tmp_file[PATH_MAX]; - output_fd = odb_mkstemp(tmp_file, sizeof(tmp_file), + struct strbuf tmp_file = STRBUF_INIT; + output_fd = odb_mkstemp(&tmp_file, "pack/tmp_pack_XXXXXX"); - pack_name = xstrdup(tmp_file); - } else + pack_name = strbuf_detach(&tmp_file, NULL); + } else { output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600); - if (output_fd < 0) - die_errno(_("unable to create '%s'"), pack_name); + if (output_fd < 0) + die_errno(_("unable to create '%s'"), pack_name); + } nothread_data.pack_fd = output_fd; } else { input_fd = open(pack_name, O_RDONLY); @@ -746,13 +747,13 @@ static int compare_objects(const unsigned char *buf, unsigned long size, ssize_t len = read_istream(data->st, data->buf, size); if (len == 0) die(_("SHA1 COLLISION FOUND WITH %s !"), - sha1_to_hex(data->entry->idx.sha1)); + oid_to_hex(&data->entry->idx.oid)); if (len < 0) die(_("unable to read %s"), - sha1_to_hex(data->entry->idx.sha1)); + oid_to_hex(&data->entry->idx.oid)); if (memcmp(buf, data->buf, len)) die(_("SHA1 COLLISION FOUND WITH %s !"), - sha1_to_hex(data->entry->idx.sha1)); + oid_to_hex(&data->entry->idx.oid)); size -= len; buf += len; } @@ -770,12 +771,12 @@ static int check_collison(struct object_entry *entry) memset(&data, 0, sizeof(data)); data.entry = entry; - data.st = open_istream(entry->idx.sha1, &type, &size, NULL); + data.st = open_istream(entry->idx.oid.hash, &type, &size, NULL); if (!data.st) return -1; if (size != entry->size || type != entry->type) die(_("SHA1 COLLISION FOUND WITH %s !"), - sha1_to_hex(entry->idx.sha1)); + oid_to_hex(&entry->idx.oid)); unpack_data(entry, compare_objects, &data); close_istream(data.st); free(data.buf); @@ -784,7 +785,7 @@ static int check_collison(struct object_entry *entry) static void sha1_object(const void *data, struct object_entry *obj_entry, unsigned long size, enum object_type type, - const unsigned char *sha1) + const struct object_id *oid) { void *new_data = NULL; int collision_test_needed = 0; @@ -793,7 +794,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (startup_info->have_repository) { read_lock(); - collision_test_needed = has_sha1_file_with_flags(sha1, HAS_SHA1_QUICK); + collision_test_needed = has_sha1_file_with_flags(oid->hash, HAS_SHA1_QUICK); read_unlock(); } @@ -808,29 +809,31 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, enum object_type has_type; unsigned long has_size; read_lock(); - has_type = sha1_object_info(sha1, &has_size); + has_type = sha1_object_info(oid->hash, &has_size); + if (has_type < 0) + die(_("cannot read existing object info %s"), oid_to_hex(oid)); if (has_type != type || has_size != size) - die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1)); - has_data = read_sha1_file(sha1, &has_type, &has_size); + die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid)); + has_data = read_sha1_file(oid->hash, &has_type, &has_size); read_unlock(); if (!data) data = new_data = get_data_from_pack(obj_entry); if (!has_data) - die(_("cannot read existing object %s"), sha1_to_hex(sha1)); + die(_("cannot read existing object %s"), oid_to_hex(oid)); if (size != has_size || type != has_type || memcmp(data, has_data, size) != 0) - die(_("SHA1 COLLISION FOUND WITH %s !"), sha1_to_hex(sha1)); + die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid)); free(has_data); } if (strict) { read_lock(); if (type == OBJ_BLOB) { - struct blob *blob = lookup_blob(sha1); + struct blob *blob = lookup_blob(oid); if (blob) blob->object.flags |= FLAG_CHECKED; else - die(_("invalid blob object %s"), sha1_to_hex(sha1)); + die(_("invalid blob object %s"), oid_to_hex(oid)); } else { struct object *obj; int eaten; @@ -842,7 +845,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, * we do not need to free the memory here, as the * buf is deleted by the caller. */ - obj = parse_object_buffer(sha1, type, size, buf, &eaten); + obj = parse_object_buffer(oid, type, size, buf, + &eaten); if (!obj) die(_("invalid %s"), typename(type)); if (do_fsck_object && @@ -954,9 +958,10 @@ static void resolve_delta(struct object_entry *delta_obj, if (!result->data) bad_object(delta_obj->idx.offset, _("failed to apply delta")); hash_sha1_file(result->data, result->size, - typename(delta_obj->real_type), delta_obj->idx.sha1); + typename(delta_obj->real_type), + delta_obj->idx.oid.hash); sha1_object(result->data, NULL, result->size, delta_obj->real_type, - delta_obj->idx.sha1); + &delta_obj->idx.oid); counter_lock(); nr_resolved_deltas++; counter_unlock(); @@ -986,7 +991,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base, struct base_data *prev_base) { if (base->ref_last == -1 && base->ofs_last == -1) { - find_ref_delta_children(base->obj->idx.sha1, + find_ref_delta_children(base->obj->idx.oid.hash, &base->ref_first, &base->ref_last, OBJ_REF_DELTA); @@ -1127,7 +1132,8 @@ static void parse_pack_objects(unsigned char *sha1) for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; void *data = unpack_raw_entry(obj, &ofs_delta->offset, - ref_delta_sha1, obj->idx.sha1); + ref_delta_sha1, + obj->idx.oid.hash); obj->real_type = obj->type; if (obj->type == OBJ_OFS_DELTA) { nr_ofs_deltas++; @@ -1143,7 +1149,8 @@ static void parse_pack_objects(unsigned char *sha1) obj->real_type = OBJ_BAD; nr_delays++; } else - sha1_object(data, NULL, obj->size, obj->type, obj->idx.sha1); + sha1_object(data, NULL, obj->size, obj->type, + &obj->idx.oid); free(data); display_progress(progress, i+1); } @@ -1169,7 +1176,8 @@ static void parse_pack_objects(unsigned char *sha1) if (obj->real_type != OBJ_BAD) continue; obj->real_type = obj->type; - sha1_object(NULL, obj, obj->size, obj->type, obj->idx.sha1); + sha1_object(NULL, obj, obj->size, obj->type, + &obj->idx.oid); nr_delays--; } if (nr_delays) @@ -1327,7 +1335,7 @@ static struct object_entry *append_obj_to_pack(struct sha1file *f, obj[1].idx.offset += write_compressed(f, buf, size); obj[0].idx.crc32 = crc32_end(f); sha1flush(f); - hashcpy(obj->idx.sha1, sha1); + hashcpy(obj->idx.oid.hash, sha1); return obj; } @@ -1442,10 +1450,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name, if (!from_stdin) { printf("%s\n", sha1_to_hex(sha1)); } else { - char buf[48]; - int len = snprintf(buf, sizeof(buf), "%s\t%s\n", - report, sha1_to_hex(sha1)); - write_or_die(1, buf, len); + struct strbuf buf = STRBUF_INIT; + + strbuf_addf(&buf, "%s\t%s\n", report, sha1_to_hex(sha1)); + write_or_die(1, buf.buf, buf.len); + strbuf_release(&buf); /* * Let's just mimic git-unpack-objects here and write @@ -1577,13 +1586,14 @@ static void show_pack_info(int stat_only) if (stat_only) continue; printf("%s %-6s %lu %lu %"PRIuMAX, - sha1_to_hex(obj->idx.sha1), + oid_to_hex(&obj->idx.oid), typename(obj->real_type), obj->size, (unsigned long)(obj[1].idx.offset - obj->idx.offset), (uintmax_t)obj->idx.offset); if (is_delta_type(obj->type)) { struct object_entry *bobj = &objects[obj_stat[i].base_object_no]; - printf(" %u %s", obj_stat[i].delta_depth, sha1_to_hex(bobj->idx.sha1)); + printf(" %u %s", obj_stat[i].delta_depth, + oid_to_hex(&bobj->idx.oid)); } putchar('\n'); } diff --git a/builtin/log.c b/builtin/log.c index 670229cbb4..a440601efe 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -52,6 +52,11 @@ struct line_opt_callback_data { struct string_list args; }; +static int auto_decoration_style(void) +{ + return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0; +} + static int parse_decoration_style(const char *var, const char *value) { switch (git_config_maybe_bool(var, value)) { @@ -67,7 +72,7 @@ static int parse_decoration_style(const char *var, const char *value) else if (!strcmp(value, "short")) return DECORATE_SHORT_REFS; else if (!strcmp(value, "auto")) - return (isatty(1) || pager_in_use()) ? DECORATE_SHORT_REFS : 0; + return auto_decoration_style(); return -1; } @@ -105,6 +110,8 @@ static void init_log_defaults(void) { init_grep_defaults(); init_diff_ui_defaults(); + + decoration_style = auto_decoration_style(); } static void cmd_log_init_defaults(struct rev_info *rev) @@ -589,7 +596,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.shown_one = 1; if (ret) break; - o = parse_object(t->tagged->oid.hash); + o = parse_object(&t->tagged->oid); if (!o) ret = error(_("Could not read object %s"), oid_to_hex(&t->tagged->oid)); @@ -871,8 +878,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->oid.hash); - c2 = lookup_commit_reference(o2->oid.hash); + c1 = lookup_commit_reference(&o1->oid); + c2 = lookup_commit_reference(&o2->oid); if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die(_("Not a range.")); @@ -903,8 +910,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids) static void gen_message_id(struct rev_info *info, char *base) { struct strbuf buf = STRBUF_INIT; - strbuf_addf(&buf, "%s.%lu.git.%s", base, - (unsigned long) time(NULL), + strbuf_addf(&buf, "%s.%"PRItime".git.%s", base, + (timestamp_t) time(NULL), git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT)); info->message_id = strbuf_detach(&buf, NULL); } @@ -1256,7 +1263,7 @@ static struct commit *get_base_commit(const char *base_commit, if (get_oid(upstream, &oid)) die(_("Failed to resolve '%s' as a valid ref."), upstream); - commit = lookup_commit_or_die(oid.hash, "upstream base"); + commit = lookup_commit_or_die(&oid, "upstream base"); base_list = get_merge_bases_many(commit, total, list); /* There should be one and only one merge base. */ if (!base_list || base_list->next) @@ -1812,7 +1819,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) { struct object_id oid; if (get_oid(arg, &oid) == 0) { - struct commit *commit = lookup_commit_reference(oid.hash); + struct commit *commit = lookup_commit_reference(&oid); if (commit) { commit->object.flags |= flags; add_pending_object(revs, &commit->object, arg); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 1c0f057d02..530e6ae7f7 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -15,6 +15,7 @@ #include "string-list.h" #include "pathspec.h" #include "run-command.h" +#include "submodule.h" static int abbrev; static int show_deleted; @@ -30,7 +31,7 @@ static int line_terminator = '\n'; static int debug_mode; static int show_eol; static int recurse_submodules; -static struct argv_array submodules_options = ARGV_ARRAY_INIT; +static struct argv_array submodule_options = ARGV_ARRAY_INIT; static const char *prefix; static const char *super_prefix; @@ -172,20 +173,27 @@ static void show_killed_files(struct dir_struct *dir) /* * Compile an argv_array with all of the options supported by --recurse_submodules */ -static void compile_submodule_options(const struct dir_struct *dir, int show_tag) +static void compile_submodule_options(const char **argv, + const struct dir_struct *dir, + int show_tag) { if (line_terminator == '\0') - argv_array_push(&submodules_options, "-z"); + argv_array_push(&submodule_options, "-z"); if (show_tag) - argv_array_push(&submodules_options, "-t"); + argv_array_push(&submodule_options, "-t"); if (show_valid_bit) - argv_array_push(&submodules_options, "-v"); + argv_array_push(&submodule_options, "-v"); if (show_cached) - argv_array_push(&submodules_options, "--cached"); + argv_array_push(&submodule_options, "--cached"); if (show_eol) - argv_array_push(&submodules_options, "--eol"); + argv_array_push(&submodule_options, "--eol"); if (debug_mode) - argv_array_push(&submodules_options, "--debug"); + argv_array_push(&submodule_options, "--debug"); + + /* Add Pathspecs */ + argv_array_push(&submodule_options, "--"); + for (; *argv; argv++) + argv_array_push(&submodule_options, *argv); } /** @@ -195,8 +203,15 @@ static void show_gitlink(const struct cache_entry *ce) { struct child_process cp = CHILD_PROCESS_INIT; int status; - int i; + char *dir; + + prepare_submodule_repo_env(&cp.env_array); + argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT); + if (prefix_len) + argv_array_pushf(&cp.env_array, "%s=%s", + GIT_TOPLEVEL_PREFIX_ENVIRONMENT, + prefix); argv_array_pushf(&cp.args, "--super-prefix=%s%s/", super_prefix ? super_prefix : "", ce->name); @@ -204,20 +219,13 @@ static void show_gitlink(const struct cache_entry *ce) argv_array_push(&cp.args, "--recurse-submodules"); /* add supported options */ - argv_array_pushv(&cp.args, submodules_options.argv); - - /* - * Pass in the original pathspec args. The submodule will be - * responsible for prepending the 'submodule_prefix' prior to comparing - * against the pathspec for matches. - */ - argv_array_push(&cp.args, "--"); - for (i = 0; i < pathspec.nr; i++) - argv_array_push(&cp.args, pathspec.items[i].original); + argv_array_pushv(&cp.args, submodule_options.argv); cp.git_cmd = 1; - cp.dir = ce->name; + dir = mkpathdup("%s/%s", get_git_work_tree(), ce->name); + cp.dir = dir; status = run_command(&cp); + free(dir); if (status) exit(status); } @@ -314,7 +322,7 @@ static void show_ru_info(void) static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce) { int dtype = ce_to_dtype(ce); - return is_excluded(dir, ce->name, &dtype); + return is_excluded(dir, &the_index, ce->name, &dtype); } static void show_files(struct dir_struct *dir) @@ -325,7 +333,7 @@ static void show_files(struct dir_struct *dir) if (show_others || show_killed) { if (!show_others) dir->flags |= DIR_COLLECT_KILLED_ONLY; - fill_directory(dir, &pathspec); + fill_directory(dir, &the_index, &pathspec); if (show_others) show_other_files(dir); if (show_killed) @@ -406,14 +414,14 @@ static void prune_cache(const char *prefix, size_t prefixlen) void overlay_tree_on_cache(const char *tree_name, const char *prefix) { struct tree *tree; - unsigned char sha1[20]; + struct object_id oid; struct pathspec pathspec; struct cache_entry *last_stage0 = NULL; int i; - if (get_sha1(tree_name, sha1)) + if (get_oid(tree_name, &oid)) die("tree-ish %s not found.", tree_name); - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(&oid); if (!tree) die("bad tree-ish %s", tree_name); @@ -604,7 +612,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) setup_work_tree(); if (recurse_submodules) - compile_submodule_options(&dir, show_tag); + compile_submodule_options(argv, &dir, show_tag); if (recurse_submodules && (show_stage || show_deleted || show_others || show_unmerged || diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 66cdd45cc1..b2d7d5ce68 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -17,17 +17,19 @@ static const char * const ls_remote_usage[] = { static int tail_match(const char **pattern, const char *path) { const char *p; - char pathbuf[PATH_MAX]; + char *pathbuf; if (!pattern) return 1; /* no restriction */ - if (snprintf(pathbuf, sizeof(pathbuf), "/%s", path) > sizeof(pathbuf)) - return error("insanely long ref %.*s...", 20, path); + pathbuf = xstrfmt("/%s", path); while ((p = *(pattern++)) != NULL) { - if (!wildmatch(p, pathbuf, 0, NULL)) + if (!wildmatch(p, pathbuf, 0, NULL)) { + free(pathbuf); return 1; + } } + free(pathbuf); return 0; } diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index d7ebeb4ce6..ee7b293b11 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -119,7 +119,7 @@ static int show_tree(const unsigned char *sha1, struct strbuf *base, int cmd_ls_tree(int argc, const char **argv, const char *prefix) { - unsigned char sha1[20]; + struct object_id oid; struct tree *tree; int i, full_tree = 0; const struct option ls_tree_options[] = { @@ -164,7 +164,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) if (argc < 1) usage_with_options(ls_tree_usage, ls_tree_options); - if (get_sha1(argv[0], sha1)) + if (get_oid(argv[0], &oid)) die("Not a valid object name %s", argv[0]); /* @@ -180,7 +180,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) for (i = 0; i < pathspec.nr; i++) pathspec.items[i].nowildcard_len = pathspec.items[i].len; pathspec.has_wildcard = 0; - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(&oid); if (!tree) die("not a tree object"); return !!read_tree_recursive(tree, "", 0, 0, &pathspec, show_tree, NULL); diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index 30681681c1..664400b816 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -232,6 +232,16 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, do { peek = fgetc(f); + if (peek == EOF) { + if (f == stdin) + /* empty stdin is OK */ + ret = skip; + else { + fclose(f); + error(_("empty mbox: '%s'"), file); + } + goto out; + } } while (isspace(peek)); ungetc(peek, f); diff --git a/builtin/merge-base.c b/builtin/merge-base.c index cfe2a796f8..0c36a70ad8 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -41,7 +41,7 @@ static struct commit *get_commit_reference(const char *arg) if (get_oid(arg, &revkey)) die("Not a valid object name %s", arg); - r = lookup_commit_reference(revkey.hash); + r = lookup_commit_reference(&revkey); if (!r) die("Not a valid commit name %s", arg); @@ -120,7 +120,7 @@ static void add_one_commit(struct object_id *oid, struct rev_collect *revs) if (is_null_oid(oid)) return; - commit = lookup_commit(oid->hash); + commit = lookup_commit(oid); if (!commit || (commit->object.flags & TMP_MARK) || parse_commit(commit)) @@ -132,7 +132,7 @@ static void add_one_commit(struct object_id *oid, struct rev_collect *revs) } static int collect_one_reflog_ent(struct object_id *ooid, struct object_id *noid, - const char *ident, unsigned long timestamp, + const char *ident, timestamp_t timestamp, int tz, const char *message, void *cbdata) { struct rev_collect *revs = cbdata; @@ -168,7 +168,7 @@ static int handle_fork_point(int argc, const char **argv) if (get_oid(commitname, &oid)) die("Not a valid object name: '%s'", commitname); - derived = lookup_commit_reference(oid.hash); + derived = lookup_commit_reference(&oid); memset(&revs, 0, sizeof(revs)); revs.initial = 1; for_each_reflog_ent(refname, collect_one_reflog_ent, &revs); diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 2d1b6db6bd..c99443b095 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -9,7 +9,7 @@ static int merge_entry(int pos, const char *path) { int found; const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL }; - char hexbuf[4][GIT_SHA1_HEXSZ + 1]; + char hexbuf[4][GIT_MAX_HEXSZ + 1]; char ownbuf[4][60]; if (pos >= active_nr) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 5b7ab9b967..bad6735c76 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -161,14 +161,14 @@ static int both_empty(struct name_entry *a, struct name_entry *b) return !(a->oid || b->oid); } -static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsigned char *sha1, const char *path) +static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path) { struct merge_list *res = xcalloc(1, sizeof(*res)); res->stage = stage; res->path = path; res->mode = mode; - res->blob = lookup_blob(sha1); + res->blob = lookup_blob(oid); return res; } @@ -188,8 +188,8 @@ static void resolve(const struct traverse_info *info, struct name_entry *ours, s return; path = traverse_path(info, result); - orig = create_entry(2, ours->mode, ours->oid->hash, path); - final = create_entry(0, result->mode, result->oid->hash, path); + orig = create_entry(2, ours->mode, ours->oid, path); + final = create_entry(0, result->mode, result->oid, path); final->link = orig; @@ -239,7 +239,7 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info path = entry->path; else path = traverse_path(info, n); - link = create_entry(stage, n->mode, n->oid->hash, path); + link = create_entry(stage, n->mode, n->oid, path); link->link = entry; return link; } diff --git a/builtin/merge.c b/builtin/merge.c index 7554b8d412..a4a098f40f 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -44,7 +44,6 @@ struct strategy { static const char * const builtin_merge_usage[] = { N_("git merge [<options>] [<commit>...]"), - N_("git merge [<options>] <msg> HEAD <commit>"), N_("git merge --abort"), N_("git merge --continue"), NULL @@ -606,13 +605,13 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head, opts.verbose_update = 1; opts.trivial_merges_only = 1; opts.merge = 1; - trees[nr_trees] = parse_tree_indirect(common->hash); + trees[nr_trees] = parse_tree_indirect(common); if (!trees[nr_trees++]) return -1; - trees[nr_trees] = parse_tree_indirect(head->hash); + trees[nr_trees] = parse_tree_indirect(head); if (!trees[nr_trees++]) return -1; - trees[nr_trees] = parse_tree_indirect(one->hash); + trees[nr_trees] = parse_tree_indirect(one); if (!trees[nr_trees++]) return -1; opts.fn = threeway_merge; @@ -634,9 +633,10 @@ static void write_tree_trivial(struct object_id *oid) static int try_merge_strategy(const char *strategy, struct commit_list *common, struct commit_list *remoteheads, - struct commit *head, const char *head_arg) + struct commit *head) { static struct lock_file lock; + const char *head_arg = "HEAD"; hold_locked_index(&lock, LOCK_DIE_ON_ERROR); refresh_cache(REFRESH_QUIET); @@ -853,24 +853,6 @@ static int suggest_conflicts(void) return 1; } -static struct commit *is_old_style_invocation(int argc, const char **argv, - const struct object_id *head) -{ - struct commit *second_token = NULL; - if (argc > 2) { - struct object_id second_oid; - - if (get_oid(argv[1], &second_oid)) - return NULL; - second_token = lookup_commit_reference_gently(second_oid.hash, 0); - if (!second_token) - die(_("'%s' is not a commit"), argv[1]); - if (oidcmp(&second_token->object.oid, head)) - return NULL; - } - return second_token; -} - static int evaluate_result(void) { int cnt = 0; @@ -1120,7 +1102,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) struct object_id result_tree, stash, head_oid; struct commit *head_commit; struct strbuf buf = STRBUF_INIT; - const char *head_arg; int i, ret = 0, head_subsumed; int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0; struct commit_list *common = NULL; @@ -1142,7 +1123,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) if (!branch || is_null_oid(&head_oid)) head_commit = NULL; else - head_commit = lookup_commit_or_die(head_oid.hash, "HEAD"); + head_commit = lookup_commit_or_die(&head_oid, "HEAD"); init_diff_ui_defaults(); git_config(git_merge_config, NULL); @@ -1260,34 +1241,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix) } /* - * This could be traditional "merge <msg> HEAD <commit>..." and - * the way we can tell it is to see if the second token is HEAD, - * but some people might have misused the interface and used a - * commit-ish that is the same as HEAD there instead. - * Traditional format never would have "-m" so it is an - * additional safety measure to check for it. + * All the rest are the commits being merged; prepare + * the standard merge summary message to be appended + * to the given message. */ - if (!have_message && - is_old_style_invocation(argc, argv, &head_commit->object.oid)) { - warning("old-style 'git merge <msg> HEAD <commit>' is deprecated."); - strbuf_addstr(&merge_msg, argv[0]); - head_arg = argv[1]; - argv += 2; - argc -= 2; - remoteheads = collect_parents(head_commit, &head_subsumed, - argc, argv, NULL); - } else { - /* We are invoked directly as the first-class UI. */ - head_arg = "HEAD"; - - /* - * All the rest are the commits being merged; prepare - * the standard merge summary message to be appended - * to the given message. - */ - remoteheads = collect_parents(head_commit, &head_subsumed, - argc, argv, &merge_msg); - } + remoteheads = collect_parents(head_commit, &head_subsumed, + argc, argv, &merge_msg); if (!head_commit || !argc) usage_with_options(builtin_merge_usage, @@ -1296,7 +1255,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) if (verify_signatures) { for (p = remoteheads; p; p = p->next) { struct commit *commit = p->item; - char hex[GIT_SHA1_HEXSZ + 1]; + char hex[GIT_MAX_HEXSZ + 1]; struct signature_check signature_check; memset(&signature_check, 0, sizeof(signature_check)); @@ -1413,8 +1372,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix) goto done; } - if (checkout_fast_forward(head_commit->object.oid.hash, - commit->object.oid.hash, + if (checkout_fast_forward(&head_commit->object.oid, + &commit->object.oid, overwrite_ignore)) { ret = 1; goto done; @@ -1513,7 +1472,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) ret = try_merge_strategy(use_strategies[i]->name, common, remoteheads, - head_commit, head_arg); + head_commit); if (!option_commit && !ret) { merge_was_ok = 1; /* @@ -1583,7 +1542,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) printf(_("Using the %s to prepare resolving by hand.\n"), best_strategy); try_merge_strategy(best_strategy, common, remoteheads, - head_commit, head_arg); + head_commit); } if (squash) diff --git a/builtin/mktree.c b/builtin/mktree.c index de9b40fc63..da0fd8cd70 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -72,7 +72,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss unsigned mode; enum object_type mode_type; /* object type derived from mode */ enum object_type obj_type; /* object type derived from sha */ - char *path; + char *path, *to_free = NULL; unsigned char sha1[20]; ptr = buf; @@ -102,7 +102,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss struct strbuf p_uq = STRBUF_INIT; if (unquote_c_style(&p_uq, path, NULL)) die("invalid quoting"); - path = strbuf_detach(&p_uq, NULL); + path = to_free = strbuf_detach(&p_uq, NULL); } /* @@ -136,6 +136,7 @@ static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_miss } append_to_tree(mode, sha1, path); + free(to_free); } int cmd_mktree(int ac, const char **av, const char *prefix) diff --git a/builtin/name-rev.c b/builtin/name-rev.c index bf7ed015ae..663e26ebbd 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -10,7 +10,7 @@ typedef struct rev_name { const char *tip_name; - unsigned long taggerdate; + timestamp_t taggerdate; int generation; int distance; int from_tag; @@ -23,7 +23,7 @@ static long cutoff = LONG_MAX; static int is_better_name(struct rev_name *name, const char *tip_name, - unsigned long taggerdate, + timestamp_t taggerdate, int generation, int distance, int from_tag) @@ -60,13 +60,14 @@ static int is_better_name(struct rev_name *name, } static void name_rev(struct commit *commit, - const char *tip_name, unsigned long taggerdate, + const char *tip_name, timestamp_t taggerdate, int generation, int distance, int from_tag, int deref) { struct rev_name *name = (struct rev_name *)commit->util; struct commit_list *parents; int parent_number = 1; + char *to_free = NULL; parse_commit(commit); @@ -74,7 +75,7 @@ static void name_rev(struct commit *commit, return; if (deref) { - tip_name = xstrfmt("%s^0", tip_name); + tip_name = to_free = xstrfmt("%s^0", tip_name); if (generation) die("generation: %d, but deref?", generation); @@ -92,8 +93,10 @@ copy_data: name->generation = generation; name->distance = distance; name->from_tag = from_tag; - } else + } else { + free(to_free); return; + } for (parents = commit->parents; parents; @@ -155,7 +158,7 @@ struct name_ref_data { static struct tip_table { struct tip_table_entry { - unsigned char sha1[20]; + struct object_id oid; const char *refname; } *table; int nr; @@ -163,13 +166,13 @@ static struct tip_table { int sorted; } tip_table; -static void add_to_tip_table(const unsigned char *sha1, const char *refname, +static void add_to_tip_table(const struct object_id *oid, const char *refname, int shorten_unambiguous) { refname = name_ref_abbrev(refname, shorten_unambiguous); ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc); - hashcpy(tip_table.table[tip_table.nr].sha1, sha1); + oidcpy(&tip_table.table[tip_table.nr].oid, oid); tip_table.table[tip_table.nr].refname = xstrdup(refname); tip_table.nr++; tip_table.sorted = 0; @@ -178,16 +181,16 @@ static void add_to_tip_table(const unsigned char *sha1, const char *refname, static int tipcmp(const void *a_, const void *b_) { const struct tip_table_entry *a = a_, *b = b_; - return hashcmp(a->sha1, b->sha1); + return oidcmp(&a->oid, &b->oid); } static int name_ref(const char *path, const struct object_id *oid, int flags, void *cb_data) { - struct object *o = parse_object(oid->hash); + struct object *o = parse_object(oid); struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; - unsigned long taggerdate = ULONG_MAX; + timestamp_t taggerdate = TIME_MAX; if (data->tags_only && !starts_with(path, "refs/tags/")) return 0; @@ -235,13 +238,13 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo return 0; } - add_to_tip_table(oid->hash, path, can_abbreviate_output); + add_to_tip_table(oid, path, can_abbreviate_output); while (o && o->type == OBJ_TAG) { struct tag *t = (struct tag *) o; if (!t->tagged) break; /* broken repository */ - o = parse_object(t->tagged->oid.hash); + o = parse_object(&t->tagged->oid); deref = 1; taggerdate = t->date; } @@ -261,7 +264,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo static const unsigned char *nth_tip_table_ent(size_t ix, void *table_) { struct tip_table_entry *table = table_; - return table[ix].sha1; + return table[ix].oid.hash; } static const char *get_exact_ref_match(const struct object *o) @@ -283,10 +286,9 @@ static const char *get_exact_ref_match(const struct object *o) return NULL; } -/* returns a static buffer */ -static const char *get_rev_name(const struct object *o) +/* may return a constant string or use "buf" as scratch space */ +static const char *get_rev_name(const struct object *o, struct strbuf *buf) { - static char buffer[1024]; struct rev_name *n; struct commit *c; @@ -303,10 +305,9 @@ static const char *get_rev_name(const struct object *o) int len = strlen(n->tip_name); if (len > 2 && !strcmp(n->tip_name + len - 2, "^0")) len -= 2; - snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name, - n->generation); - - return buffer; + strbuf_reset(buf); + strbuf_addf(buf, "%.*s~%d", len, n->tip_name, n->generation); + return buf->buf; } } @@ -316,10 +317,11 @@ static void show_name(const struct object *obj, { const char *name; const struct object_id *oid = &obj->oid; + struct strbuf buf = STRBUF_INIT; if (!name_only) printf("%s ", caller_name ? caller_name : oid_to_hex(oid)); - name = get_rev_name(obj); + name = get_rev_name(obj, &buf); if (name) printf("%s\n", name); else if (allow_undefined) @@ -328,6 +330,7 @@ static void show_name(const struct object *obj, printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV)); else die("cannot describe '%s'", oid_to_hex(oid)); + strbuf_release(&buf); } static char const * const name_rev_usage[] = { @@ -339,15 +342,16 @@ static char const * const name_rev_usage[] = { static void name_rev_line(char *p, struct name_ref_data *data) { + struct strbuf buf = STRBUF_INIT; int forty = 0; char *p_start; for (p_start = p; *p; p++) { #define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f')) if (!ishex(*p)) forty = 0; - else if (++forty == 40 && + else if (++forty == GIT_SHA1_HEXSZ && !ishex(*(p+1))) { - unsigned char sha1[40]; + struct object_id oid; const char *name = NULL; char c = *(p+1); int p_len = p - p_start + 1; @@ -355,11 +359,11 @@ static void name_rev_line(char *p, struct name_ref_data *data) forty = 0; *(p+1) = 0; - if (!get_sha1(p - 39, sha1)) { + if (!get_oid(p - (GIT_SHA1_HEXSZ - 1), &oid)) { struct object *o = - lookup_object(sha1); + lookup_object(oid.hash); if (o) - name = get_rev_name(o); + name = get_rev_name(o, &buf); } *(p+1) = c; @@ -367,7 +371,7 @@ static void name_rev_line(char *p, struct name_ref_data *data) continue; if (data->name_only) - printf("%.*s%s", p_len - 40, p_start, name); + printf("%.*s%s", p_len - GIT_SHA1_HEXSZ, p_start, name); else printf("%.*s (%s)", p_len, p_start, name); p_start = p + 1; @@ -377,6 +381,8 @@ static void name_rev_line(char *p, struct name_ref_data *data) /* flush */ if (p_start != p) fwrite(p_start, p - p_start, 1, stdout); + + strbuf_release(&buf); } int cmd_name_rev(int argc, const char **argv, const char *prefix) @@ -416,18 +422,18 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) cutoff = 0; for (; argc; argc--, argv++) { - unsigned char sha1[20]; + struct object_id oid; struct object *object; struct commit *commit; - if (get_sha1(*argv, sha1)) { + if (get_oid(*argv, &oid)) { fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", *argv); continue; } commit = NULL; - object = parse_object(sha1); + object = parse_object(&oid); if (object) { struct object *peeled = deref_tag(object, *argv, 0); if (peeled && peeled->type == OBJ_COMMIT) diff --git a/builtin/notes.c b/builtin/notes.c index 0513f7455d..f2847c41e0 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -554,7 +554,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) struct notes_tree *t; unsigned char object[20], new_note[20]; const unsigned char *note; - char logmsg[100]; + char *logmsg; const char * const *usage; struct note_data d = { 0, 0, NULL, STRBUF_INIT }; struct option options[] = { @@ -618,17 +618,16 @@ static int append_edit(int argc, const char **argv, const char *prefix) write_note_data(&d, new_note); if (add_note(t, object, new_note, combine_notes_overwrite)) die("BUG: combine_notes_overwrite failed"); - snprintf(logmsg, sizeof(logmsg), "Notes added by 'git notes %s'", - argv[0]); + logmsg = xstrfmt("Notes added by 'git notes %s'", argv[0]); } else { fprintf(stderr, _("Removing note for object %s\n"), sha1_to_hex(object)); remove_note(t, object); - snprintf(logmsg, sizeof(logmsg), "Notes removed by 'git notes %s'", - argv[0]); + logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]); } commit_notes(t, logmsg); + free(logmsg); free_note_data(&d); free_notes(t); return 0; @@ -707,7 +706,7 @@ static int merge_commit(struct notes_merge_options *o) if (get_oid("NOTES_MERGE_PARTIAL", &oid)) die(_("failed to read ref NOTES_MERGE_PARTIAL")); - else if (!(partial = lookup_commit_reference(oid.hash))) + else if (!(partial = lookup_commit_reference(&oid))) die(_("could not find commit from NOTES_MERGE_PARTIAL.")); else if (parse_commit(partial)) die(_("could not parse commit from NOTES_MERGE_PARTIAL.")); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 16517f2637..80439047aa 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -44,7 +44,7 @@ static uint32_t nr_result, nr_written; static int non_empty; static int reuse_delta = 1, reuse_object = 1; static int keep_unreachable, unpack_unreachable, include_tag; -static unsigned long unpack_unreachable_expiration; +static timestamp_t unpack_unreachable_expiration; static int pack_loose_unreachable; static int local; static int have_non_local_packs; @@ -106,12 +106,14 @@ static void *get_delta(struct object_entry *entry) void *buf, *base_buf, *delta_buf; enum object_type type; - buf = read_sha1_file(entry->idx.sha1, &type, &size); + buf = read_sha1_file(entry->idx.oid.hash, &type, &size); if (!buf) - die("unable to read %s", sha1_to_hex(entry->idx.sha1)); - base_buf = read_sha1_file(entry->delta->idx.sha1, &type, &base_size); + die("unable to read %s", oid_to_hex(&entry->idx.oid)); + base_buf = read_sha1_file(entry->delta->idx.oid.hash, &type, + &base_size); if (!base_buf) - die("unable to read %s", sha1_to_hex(entry->delta->idx.sha1)); + die("unable to read %s", + oid_to_hex(&entry->delta->idx.oid)); delta_buf = diff_delta(base_buf, base_size, buf, size, &delta_size, 0); if (!delta_buf || delta_size != entry->delta_size) @@ -239,7 +241,8 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent unsigned long limit, int usable_delta) { unsigned long size, datalen; - unsigned char header[10], dheader[10]; + unsigned char header[MAX_PACK_OBJECT_HEADER], + dheader[MAX_PACK_OBJECT_HEADER]; unsigned hdrlen; enum object_type type; void *buf; @@ -248,12 +251,14 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent if (!usable_delta) { if (entry->type == OBJ_BLOB && entry->size > big_file_threshold && - (st = open_istream(entry->idx.sha1, &type, &size, NULL)) != NULL) + (st = open_istream(entry->idx.oid.hash, &type, &size, NULL)) != NULL) buf = NULL; else { - buf = read_sha1_file(entry->idx.sha1, &type, &size); + buf = read_sha1_file(entry->idx.oid.hash, &type, + &size); if (!buf) - die(_("unable to read %s"), sha1_to_hex(entry->idx.sha1)); + die(_("unable to read %s"), + oid_to_hex(&entry->idx.oid)); } /* * make sure no cached delta data remains from a @@ -286,7 +291,8 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent * The object header is a byte of 'type' followed by zero or * more bytes of length. */ - hdrlen = encode_in_pack_object_header(type, size, header); + hdrlen = encode_in_pack_object_header(header, sizeof(header), + type, size); if (type == OBJ_OFS_DELTA) { /* @@ -320,7 +326,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent return 0; } sha1write(f, header, hdrlen); - sha1write(f, entry->delta->idx.sha1, 20); + sha1write(f, entry->delta->idx.oid.hash, 20); hdrlen += 20; } else { if (limit && hdrlen + datalen + 20 >= limit) { @@ -332,7 +338,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent sha1write(f, header, hdrlen); } if (st) { - datalen = write_large_blob_data(st, f, entry->idx.sha1); + datalen = write_large_blob_data(st, f, entry->idx.oid.hash); close_istream(st); } else { sha1write(f, buf, datalen); @@ -352,20 +358,23 @@ static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry, off_t offset; enum object_type type = entry->type; off_t datalen; - unsigned char header[10], dheader[10]; + unsigned char header[MAX_PACK_OBJECT_HEADER], + dheader[MAX_PACK_OBJECT_HEADER]; unsigned hdrlen; if (entry->delta) type = (allow_ofs_delta && entry->delta->idx.offset) ? OBJ_OFS_DELTA : OBJ_REF_DELTA; - hdrlen = encode_in_pack_object_header(type, entry->size, header); + hdrlen = encode_in_pack_object_header(header, sizeof(header), + type, entry->size); offset = entry->in_pack_offset; revidx = find_pack_revindex(p, offset); datalen = revidx[1].offset - offset; if (!pack_to_stdout && p->index_version > 1 && check_pack_crc(p, &w_curs, offset, datalen, revidx->nr)) { - error("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1)); + error("bad packed object CRC for %s", + oid_to_hex(&entry->idx.oid)); unuse_pack(&w_curs); return write_no_reuse_object(f, entry, limit, usable_delta); } @@ -375,7 +384,8 @@ static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry, if (!pack_to_stdout && p->index_version == 1 && check_pack_inflate(p, &w_curs, offset, datalen, entry->size)) { - error("corrupt packed object for %s", sha1_to_hex(entry->idx.sha1)); + error("corrupt packed object for %s", + oid_to_hex(&entry->idx.oid)); unuse_pack(&w_curs); return write_no_reuse_object(f, entry, limit, usable_delta); } @@ -400,7 +410,7 @@ static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry, return 0; } sha1write(f, header, hdrlen); - sha1write(f, entry->delta->idx.sha1, 20); + sha1write(f, entry->delta->idx.oid.hash, 20); hdrlen += 20; reused_delta++; } else { @@ -505,7 +515,7 @@ static enum write_one_status write_one(struct sha1file *f, recursing = (e->idx.offset == 1); if (recursing) { warning("recursive delta detected for object %s", - sha1_to_hex(e->idx.sha1)); + oid_to_hex(&e->idx.oid)); return WRITE_ONE_RECURSIVE; } else if (e->idx.offset || e->preferred_base) { /* offset is non zero if object is written already. */ @@ -1428,7 +1438,7 @@ static void check_object(struct object_entry *entry) ofs += 1; if (!ofs || MSB(ofs, 7)) { error("delta base offset overflow in pack for %s", - sha1_to_hex(entry->idx.sha1)); + oid_to_hex(&entry->idx.oid)); goto give_up; } c = buf[used_0++]; @@ -1437,7 +1447,7 @@ static void check_object(struct object_entry *entry) ofs = entry->in_pack_offset - ofs; if (ofs <= 0 || ofs >= entry->in_pack_offset) { error("delta base offset out of bound for %s", - sha1_to_hex(entry->idx.sha1)); + oid_to_hex(&entry->idx.oid)); goto give_up; } if (reuse_delta && !entry->preferred_base) { @@ -1494,7 +1504,7 @@ static void check_object(struct object_entry *entry) unuse_pack(&w_curs); } - entry->type = sha1_object_info(entry->idx.sha1, &entry->size); + entry->type = sha1_object_info(entry->idx.oid.hash, &entry->size); /* * The error condition is checked in prepare_pack(). This is * to permit a missing preferred base object to be ignored @@ -1510,7 +1520,7 @@ static int pack_offset_sort(const void *_a, const void *_b) /* avoid filesystem trashing with loose objects */ if (!a->in_pack && !b->in_pack) - return hashcmp(a->idx.sha1, b->idx.sha1); + return oidcmp(&a->idx.oid, &b->idx.oid); if (a->in_pack < b->in_pack) return -1; @@ -1556,7 +1566,8 @@ static void drop_reused_delta(struct object_entry *entry) * And if that fails, the error will be recorded in entry->type * and dealt with in prepare_pack(). */ - entry->type = sha1_object_info(entry->idx.sha1, &entry->size); + entry->type = sha1_object_info(entry->idx.oid.hash, + &entry->size); } } @@ -1848,26 +1859,29 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { read_lock(); - trg->data = read_sha1_file(trg_entry->idx.sha1, &type, &sz); + trg->data = read_sha1_file(trg_entry->idx.oid.hash, &type, + &sz); read_unlock(); if (!trg->data) die("object %s cannot be read", - sha1_to_hex(trg_entry->idx.sha1)); + oid_to_hex(&trg_entry->idx.oid)); if (sz != trg_size) die("object %s inconsistent object length (%lu vs %lu)", - sha1_to_hex(trg_entry->idx.sha1), sz, trg_size); + oid_to_hex(&trg_entry->idx.oid), sz, + trg_size); *mem_usage += sz; } if (!src->data) { read_lock(); - src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz); + src->data = read_sha1_file(src_entry->idx.oid.hash, &type, + &sz); read_unlock(); if (!src->data) { if (src_entry->preferred_base) { static int warned = 0; if (!warned++) warning("object %s cannot be read", - sha1_to_hex(src_entry->idx.sha1)); + oid_to_hex(&src_entry->idx.oid)); /* * Those objects are not included in the * resulting pack. Be resilient and ignore @@ -1877,11 +1891,12 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, return 0; } die("object %s cannot be read", - sha1_to_hex(src_entry->idx.sha1)); + oid_to_hex(&src_entry->idx.oid)); } if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", - sha1_to_hex(src_entry->idx.sha1), sz, src_size); + oid_to_hex(&src_entry->idx.oid), sz, + src_size); *mem_usage += sz; } if (!src->index) { @@ -2333,7 +2348,7 @@ static void add_tag_chain(const struct object_id *oid) if (packlist_find(&to_pack, oid->hash, NULL)) return; - tag = lookup_tag(oid->hash); + tag = lookup_tag(oid); while (1) { if (!tag || parse_tag(tag) || !tag->tagged) die("unable to pack objects reachable from tag %s", @@ -2402,7 +2417,7 @@ static void prepare_pack(int window, int depth) nr_deltas++; if (entry->type < 0) die("unable to get type of object %s", - sha1_to_hex(entry->idx.sha1)); + oid_to_hex(&entry->idx.oid)); } else { if (entry->type < 0) { /* @@ -2668,16 +2683,16 @@ static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1) * * This is filled by get_object_list. */ -static struct sha1_array recent_objects; +static struct oid_array recent_objects; -static int loosened_object_can_be_discarded(const unsigned char *sha1, - unsigned long mtime) +static int loosened_object_can_be_discarded(const struct object_id *oid, + timestamp_t mtime) { if (!unpack_unreachable_expiration) return 0; if (mtime > unpack_unreachable_expiration) return 0; - if (sha1_array_lookup(&recent_objects, sha1) >= 0) + if (oid_array_lookup(&recent_objects, oid) >= 0) return 0; return 1; } @@ -2686,7 +2701,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs) { struct packed_git *p; uint32_t i; - const unsigned char *sha1; + struct object_id oid; for (p = packed_git; p; p = p->next) { if (!p->pack_local || p->pack_keep) @@ -2696,11 +2711,11 @@ static void loosen_unused_packed_objects(struct rev_info *revs) die("cannot open pack index"); for (i = 0; i < p->num_objects; i++) { - sha1 = nth_packed_object_sha1(p, i); - if (!packlist_find(&to_pack, sha1, NULL) && - !has_sha1_pack_kept_or_nonlocal(sha1) && - !loosened_object_can_be_discarded(sha1, p->mtime)) - if (force_object_loose(sha1, p->mtime)) + nth_packed_object_oid(&oid, p, i); + if (!packlist_find(&to_pack, oid.hash, NULL) && + !has_sha1_pack_kept_or_nonlocal(oid.hash) && + !loosened_object_can_be_discarded(&oid, p->mtime)) + if (force_object_loose(oid.hash, p->mtime)) die("unable to force loose object"); } } @@ -2713,7 +2728,11 @@ static void loosen_unused_packed_objects(struct rev_info *revs) */ static int pack_options_allow_reuse(void) { - return pack_to_stdout && allow_ofs_delta; + return pack_to_stdout && + allow_ofs_delta && + !ignore_packed_keep && + (!local || !have_non_local_packs) && + !incremental; } static int get_object_list_from_bitmap(struct rev_info *revs) @@ -2739,12 +2758,12 @@ static void record_recent_object(struct object *obj, const char *name, void *data) { - sha1_array_append(&recent_objects, obj->oid.hash); + oid_array_append(&recent_objects, &obj->oid); } static void record_recent_commit(struct commit *commit, void *data) { - sha1_array_append(&recent_objects, commit->object.oid.hash); + oid_array_append(&recent_objects, &commit->object.oid); } static void get_object_list(int ac, const char **av) @@ -2773,10 +2792,10 @@ static void get_object_list(int ac, const char **av) continue; } if (starts_with(line, "--shallow ")) { - unsigned char sha1[20]; - if (get_sha1_hex(line + 10, sha1)) + struct object_id oid; + if (get_oid_hex(line + 10, &oid)) die("not an SHA-1 '%s'", line + 10); - register_shallow(sha1); + register_shallow(&oid); use_bitmap_index = 0; continue; } @@ -2812,7 +2831,7 @@ static void get_object_list(int ac, const char **av) if (unpack_unreachable) loosen_unused_packed_objects(&revs); - sha1_array_clear(&recent_objects); + oid_array_clear(&recent_objects); } static int option_parse_index_version(const struct option *opt, diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 72c815844d..cb1df1c761 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -442,6 +442,7 @@ static void minimize(struct pack_list **min) /* return if there are no objects missing from the unique set */ if (missing->size == 0) { *min = unique; + free(missing); return; } diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 39f9a55d16..b106a392a4 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -17,5 +17,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix) }; if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); - return pack_refs(flags); + return refs_pack_refs(get_main_ref_store(), flags); } diff --git a/builtin/patch-id.c b/builtin/patch-id.c index a84d0003a3..81552e02e4 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -55,7 +55,7 @@ static int scan_hunk_header(const char *p, int *p_before, int *p_after) static void flush_one_hunk(struct object_id *result, git_SHA_CTX *ctx) { - unsigned char hash[GIT_SHA1_RAWSZ]; + unsigned char hash[GIT_MAX_RAWSZ]; unsigned short carry = 0; int i; diff --git a/builtin/prune.c b/builtin/prune.c index 42633e0c6e..f0e2bff04c 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -13,7 +13,7 @@ static const char * const prune_usage[] = { }; static int show_only; static int verbose; -static unsigned long expire; +static timestamp_t expire; static int show_progress = -1; static int prune_tmp_file(const char *fullpath) @@ -111,7 +111,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix) }; char *s; - expire = ULONG_MAX; + expire = TIME_MAX; save_commit_buffer = 0; check_replace_refs = 0; ref_paranoia = 1; @@ -123,11 +123,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix) die(_("cannot prune in a precious-objects repo")); while (argc--) { - unsigned char sha1[20]; + struct object_id oid; const char *name = *argv++; - if (!get_sha1(name, sha1)) { - struct object *object = parse_object_or_die(sha1, name); + if (!get_oid(name, &oid)) { + struct object *object = parse_object_or_die(&oid, + name); add_pending_object(&revs, object, ""); } else diff --git a/builtin/pull.c b/builtin/pull.c index 3ecb881b0b..318c273eb3 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -330,21 +330,21 @@ static int git_pull_config(const char *var, const char *value, void *cb) * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ -static void get_merge_heads(struct sha1_array *merge_heads) +static void get_merge_heads(struct oid_array *merge_heads) { - const char *filename = git_path("FETCH_HEAD"); + const char *filename = git_path_fetch_head(); FILE *fp; struct strbuf sb = STRBUF_INIT; - unsigned char sha1[GIT_SHA1_RAWSZ]; + struct object_id oid; if (!(fp = fopen(filename, "r"))) die_errno(_("could not open '%s' for reading"), filename); while (strbuf_getline_lf(&sb, fp) != EOF) { - if (get_sha1_hex(sb.buf, sha1)) + if (get_oid_hex(sb.buf, &oid)) continue; /* invalid line: does not start with SHA1 */ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) continue; /* ref is not-for-merge */ - sha1_array_append(merge_heads, sha1); + oid_array_append(merge_heads, &oid); } fclose(fp); strbuf_release(&sb); @@ -514,8 +514,8 @@ static int run_fetch(const char *repo, const char **refspecs) /** * "Pulls into void" by branching off merge_head. */ -static int pull_into_void(const unsigned char *merge_head, - const unsigned char *curr_head) +static int pull_into_void(const struct object_id *merge_head, + const struct object_id *curr_head) { /* * Two-way merge: we treat the index as based on an empty tree, @@ -523,10 +523,10 @@ static int pull_into_void(const unsigned char *merge_head, * index/worktree changes that the user already made on the unborn * branch. */ - if (checkout_fast_forward(EMPTY_TREE_SHA1_BIN, merge_head, 0)) + if (checkout_fast_forward(&empty_tree_oid, merge_head, 0)) return 1; - if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR)) + if (update_ref("initial pull", "HEAD", merge_head->hash, curr_head->hash, 0, UPDATE_REFS_DIE_ON_ERR)) return 1; return 0; @@ -647,7 +647,7 @@ static const char *get_tracking_branch(const char *remote, const char *refspec) * current branch forked from its remote tracking branch. Returns 0 on success, * -1 on failure. */ -static int get_rebase_fork_point(unsigned char *fork_point, const char *repo, +static int get_rebase_fork_point(struct object_id *fork_point, const char *repo, const char *refspec) { int ret; @@ -678,7 +678,7 @@ static int get_rebase_fork_point(unsigned char *fork_point, const char *repo, if (ret) goto cleanup; - ret = get_sha1_hex(sb.buf, fork_point); + ret = get_oid_hex(sb.buf, fork_point); if (ret) goto cleanup; @@ -691,16 +691,16 @@ cleanup: * Sets merge_base to the octopus merge base of curr_head, merge_head and * fork_point. Returns 0 if a merge base is found, 1 otherwise. */ -static int get_octopus_merge_base(unsigned char *merge_base, - const unsigned char *curr_head, - const unsigned char *merge_head, - const unsigned char *fork_point) +static int get_octopus_merge_base(struct object_id *merge_base, + const struct object_id *curr_head, + const struct object_id *merge_head, + const struct object_id *fork_point) { struct commit_list *revs = NULL, *result; commit_list_insert(lookup_commit_reference(curr_head), &revs); commit_list_insert(lookup_commit_reference(merge_head), &revs); - if (!is_null_sha1(fork_point)) + if (!is_null_oid(fork_point)) commit_list_insert(lookup_commit_reference(fork_point), &revs); result = reduce_heads(get_octopus_merge_bases(revs)); @@ -708,7 +708,7 @@ static int get_octopus_merge_base(unsigned char *merge_base, if (!result) return 1; - hashcpy(merge_base, result->item->object.oid.hash); + oidcpy(merge_base, &result->item->object.oid); return 0; } @@ -717,16 +717,16 @@ static int get_octopus_merge_base(unsigned char *merge_base, * fork point calculated by get_rebase_fork_point(), runs git-rebase with the * appropriate arguments and returns its exit status. */ -static int run_rebase(const unsigned char *curr_head, - const unsigned char *merge_head, - const unsigned char *fork_point) +static int run_rebase(const struct object_id *curr_head, + const struct object_id *merge_head, + const struct object_id *fork_point) { int ret; - unsigned char oct_merge_base[GIT_SHA1_RAWSZ]; + struct object_id oct_merge_base; struct argv_array args = ARGV_ARRAY_INIT; - if (!get_octopus_merge_base(oct_merge_base, curr_head, merge_head, fork_point)) - if (!is_null_sha1(fork_point) && !hashcmp(oct_merge_base, fork_point)) + if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point)) + if (!is_null_oid(fork_point) && !oidcmp(&oct_merge_base, fork_point)) fork_point = NULL; argv_array_push(&args, "rebase"); @@ -754,12 +754,12 @@ static int run_rebase(const unsigned char *curr_head, warning(_("ignoring --verify-signatures for rebase")); argv_array_push(&args, "--onto"); - argv_array_push(&args, sha1_to_hex(merge_head)); + argv_array_push(&args, oid_to_hex(merge_head)); - if (fork_point && !is_null_sha1(fork_point)) - argv_array_push(&args, sha1_to_hex(fork_point)); + if (fork_point && !is_null_oid(fork_point)) + argv_array_push(&args, oid_to_hex(fork_point)); else - argv_array_push(&args, sha1_to_hex(merge_head)); + argv_array_push(&args, oid_to_hex(merge_head)); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); @@ -769,9 +769,9 @@ static int run_rebase(const unsigned char *curr_head, int cmd_pull(int argc, const char **argv, const char *prefix) { const char *repo, **refspecs; - struct sha1_array merge_heads = SHA1_ARRAY_INIT; - unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ]; - unsigned char rebase_fork_point[GIT_SHA1_RAWSZ]; + struct oid_array merge_heads = OID_ARRAY_INIT; + struct object_id orig_head, curr_head; + struct object_id rebase_fork_point; if (!getenv("GIT_REFLOG_ACTION")) set_reflog_message(argc, argv); @@ -791,11 +791,11 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (read_cache_unmerged()) die_resolve_conflict("pull"); - if (file_exists(git_path("MERGE_HEAD"))) + if (file_exists(git_path_merge_head())) die_conclude_merge(); - if (get_sha1("HEAD", orig_head)) - hashclr(orig_head); + if (get_oid("HEAD", &orig_head)) + oidclr(&orig_head); if (!opt_rebase && opt_autostash != -1) die(_("--[no-]autostash option is only valid with --rebase.")); @@ -805,15 +805,15 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (opt_autostash != -1) autostash = opt_autostash; - if (is_null_sha1(orig_head) && !is_cache_unborn()) + if (is_null_oid(&orig_head) && !is_cache_unborn()) die(_("Updating an unborn branch with changes added to the index.")); if (!autostash) require_clean_work_tree(N_("pull with rebase"), _("please commit or stash them."), 1, 0); - if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs)) - hashclr(rebase_fork_point); + if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs)) + oidclr(&rebase_fork_point); } if (run_fetch(repo, refspecs)) @@ -822,11 +822,11 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (opt_dry_run) return 0; - if (get_sha1("HEAD", curr_head)) - hashclr(curr_head); + if (get_oid("HEAD", &curr_head)) + oidclr(&curr_head); - if (!is_null_sha1(orig_head) && !is_null_sha1(curr_head) && - hashcmp(orig_head, curr_head)) { + if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) && + oidcmp(&orig_head, &curr_head)) { /* * The fetch involved updating the current branch. * @@ -837,15 +837,15 @@ int cmd_pull(int argc, const char **argv, const char *prefix) warning(_("fetch updated the current branch head.\n" "fast-forwarding your working tree from\n" - "commit %s."), sha1_to_hex(orig_head)); + "commit %s."), oid_to_hex(&orig_head)); - if (checkout_fast_forward(orig_head, curr_head, 0)) + if (checkout_fast_forward(&orig_head, &curr_head, 0)) die(_("Cannot fast-forward your working tree.\n" "After making sure that you saved anything precious from\n" "$ git diff %s\n" "output, run\n" "$ git reset --hard\n" - "to recover."), sha1_to_hex(orig_head)); + "to recover."), oid_to_hex(&orig_head)); } get_merge_heads(&merge_heads); @@ -853,10 +853,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (!merge_heads.nr) die_no_merge_candidates(repo, refspecs); - if (is_null_sha1(orig_head)) { + if (is_null_oid(&orig_head)) { if (merge_heads.nr > 1) die(_("Cannot merge multiple branches into empty head.")); - return pull_into_void(*merge_heads.sha1, curr_head); + return pull_into_void(merge_heads.oid, &curr_head); } if (opt_rebase && merge_heads.nr > 1) die(_("Cannot rebase onto multiple branches.")); @@ -865,15 +865,15 @@ int cmd_pull(int argc, const char **argv, const char *prefix) struct commit_list *list = NULL; struct commit *merge_head, *head; - head = lookup_commit_reference(orig_head); + head = lookup_commit_reference(&orig_head); commit_list_insert(head, &list); - merge_head = lookup_commit_reference(merge_heads.sha1[0]); + merge_head = lookup_commit_reference(&merge_heads.oid[0]); if (is_descendant_of(merge_head, list)) { /* we can fast-forward this without invoking rebase */ opt_ff = "--ff-only"; return run_merge(); } - return run_rebase(curr_head, *merge_heads.sha1, rebase_fork_point); + return run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point); } else { return run_merge(); } diff --git a/builtin/push.c b/builtin/push.c index 5c22e9f2e5..a597759d8f 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -510,8 +510,8 @@ int cmd_push(int argc, const char **argv, const char *prefix) int push_cert = -1; int rc; const char *repo = NULL; /* default repository */ - static struct string_list push_options = STRING_LIST_INIT_DUP; - static struct string_list_item *item; + struct string_list push_options = STRING_LIST_INIT_DUP; + const struct string_list_item *item; struct option options[] = { OPT__VERBOSITY(&verbosity), @@ -584,6 +584,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) die(_("push options must not have new line characters")); rc = do_push(repo, flags, &push_options); + string_list_clear(&push_options, 0); if (rc == -1) usage_with_options(push_usage, options); else diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 8ba64bc785..78d3193659 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -15,18 +15,21 @@ #include "builtin.h" #include "parse-options.h" #include "resolve-undo.h" +#include "submodule.h" +#include "submodule-config.h" static int nr_trees; static int read_empty; static struct tree *trees[MAX_UNPACK_TREES]; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int list_tree(unsigned char *sha1) +static int list_tree(struct object_id *oid) { struct tree *tree; if (nr_trees >= MAX_UNPACK_TREES) die("I cannot read more than %d trees", MAX_UNPACK_TREES); - tree = parse_tree_indirect(sha1); + tree = parse_tree_indirect(oid); if (!tree) return -1; trees[nr_trees++] = tree; @@ -96,12 +99,29 @@ static int debug_merge(const struct cache_entry * const *stages, return 0; } +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} + static struct lock_file lock_file; int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) { int i, stage = 0; - unsigned char sha1[20]; + struct object_id oid; struct tree_desc t[MAX_UNPACK_TREES]; struct unpack_trees_options opts; int prefix_set = 0; @@ -137,6 +157,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) N_("skip applying sparse checkout filter")), OPT_BOOL(0, "debug-unpack", &opts.debug_unpack, N_("debug unpack-trees")), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, + "checkout", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_END() }; @@ -152,6 +175,12 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) { + gitmodules_config(); + git_config(submodule_config, NULL); + set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON); + } + prefix_set = opts.prefix ? 1 : 0; if (1 < opts.merge + opts.reset + prefix_set) die("Which one? -m, --reset, or --prefix?"); @@ -175,13 +204,13 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) for (i = 0; i < argc; i++) { const char *arg = argv[i]; - if (get_sha1(arg, sha1)) + if (get_oid(arg, &oid)) die("Not a valid object name %s", arg); - if (list_tree(sha1) < 0) + if (list_tree(&oid) < 0) die("failed to unpack tree object %s", arg); stage++; } - if (nr_trees == 0 && !read_empty) + if (!nr_trees && !read_empty && !opts.merge) warning("read-tree: emptying the index with no arguments is deprecated; use --empty"); else if (nr_trees > 0 && read_empty) die("passing trees as arguments contradicts --empty"); @@ -197,9 +226,10 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) setup_work_tree(); if (opts.merge) { - if (stage < 2) - die("just how do you expect me to merge %d trees?", stage-1); switch (stage - 1) { + case 0: + die("you must specify at least one tree to merge"); + break; case 1: opts.fn = opts.prefix ? bind_merge : oneway_merge; break; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index fb2a090a0c..b1706a5731 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -78,7 +78,7 @@ static const char *NONCE_OK = "OK"; static const char *NONCE_SLOP = "SLOP"; static const char *nonce_status; static long nonce_stamp_slop; -static unsigned long nonce_stamp_slop_limit; +static timestamp_t nonce_stamp_slop_limit; static struct ref_transaction *transaction; static enum { @@ -225,10 +225,10 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static void show_ref(const char *path, const unsigned char *sha1) +static void show_ref(const char *path, const struct object_id *oid) { if (sent_capabilities) { - packet_write_fmt(1, "%s %s\n", sha1_to_hex(sha1), path); + packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), path); } else { struct strbuf cap = STRBUF_INIT; @@ -244,7 +244,7 @@ static void show_ref(const char *path, const unsigned char *sha1) strbuf_addstr(&cap, " push-options"); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); packet_write_fmt(1, "%s %s%c%s\n", - sha1_to_hex(sha1), path, 0, cap.buf); + oid_to_hex(oid), path, 0, cap.buf); strbuf_release(&cap); sent_capabilities = 1; } @@ -271,7 +271,7 @@ static int show_ref_cb(const char *path_full, const struct object_id *oid, } else { oidset_insert(seen, oid); } - show_ref(path, oid->hash); + show_ref(path, oid); return 0; } @@ -284,7 +284,7 @@ static void show_one_alternate_ref(const char *refname, if (oidset_insert(seen, oid)) return; - show_ref(".have", oid->hash); + show_ref(".have", oid); } static void write_head_info(void) @@ -295,7 +295,7 @@ static void write_head_info(void) for_each_alternate_ref(show_one_alternate_ref, &seen); oidset_clear(&seen); if (!sent_capabilities) - show_ref("capabilities^{}", null_sha1); + show_ref("capabilities^{}", &null_oid); advertise_shallow_grafts(1); @@ -309,8 +309,8 @@ struct command { unsigned int skip_update:1, did_not_exist:1; int index; - unsigned char old_sha1[20]; - unsigned char new_sha1[20]; + struct object_id old_oid; + struct object_id new_oid; char ref_name[FLEX_ARRAY]; /* more */ }; @@ -454,17 +454,17 @@ static void hmac_sha1(unsigned char *out, git_SHA1_Final(out, &ctx); } -static char *prepare_push_cert_nonce(const char *path, unsigned long stamp) +static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp) { struct strbuf buf = STRBUF_INIT; unsigned char sha1[20]; - strbuf_addf(&buf, "%s:%lu", path, stamp); + strbuf_addf(&buf, "%s:%"PRItime, path, stamp); hmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));; strbuf_release(&buf); /* RFC 2104 5. HMAC-SHA1-80 */ - strbuf_addf(&buf, "%lu-%.*s", stamp, 20, sha1_to_hex(sha1)); + strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, 20, sha1_to_hex(sha1)); return strbuf_detach(&buf, NULL); } @@ -473,7 +473,8 @@ static char *prepare_push_cert_nonce(const char *path, unsigned long stamp) * after dropping "_commit" from its name and possibly moving it out * of commit.c */ -static char *find_header(const char *msg, size_t len, const char *key) +static char *find_header(const char *msg, size_t len, const char *key, + const char **next_line) { int key_len = strlen(key); const char *line = msg; @@ -486,6 +487,8 @@ static char *find_header(const char *msg, size_t len, const char *key) if (line + key_len < eol && !memcmp(line, key, key_len) && line[key_len] == ' ') { int offset = key_len + 1; + if (next_line) + *next_line = *eol ? eol + 1 : eol; return xmemdupz(line + offset, (eol - line) - offset); } line = *eol ? eol + 1 : NULL; @@ -495,8 +498,8 @@ static char *find_header(const char *msg, size_t len, const char *key) static const char *check_nonce(const char *buf, size_t len) { - char *nonce = find_header(buf, len, "nonce"); - unsigned long stamp, ostamp; + char *nonce = find_header(buf, len, "nonce", NULL); + timestamp_t stamp, ostamp; char *bohmac, *expect = NULL; const char *retval = NONCE_BAD; @@ -534,7 +537,7 @@ static const char *check_nonce(const char *buf, size_t len) retval = NONCE_BAD; goto leave; } - stamp = strtoul(nonce, &bohmac, 10); + stamp = parse_timestamp(nonce, &bohmac, 10); if (bohmac == nonce || bohmac[0] != '-') { retval = NONCE_BAD; goto leave; @@ -552,7 +555,7 @@ static const char *check_nonce(const char *buf, size_t len) * would mean it was issued by another server with its clock * skewed in the future. */ - ostamp = strtoul(push_cert_nonce, NULL, 10); + ostamp = parse_timestamp(push_cert_nonce, NULL, 10); nonce_stamp_slop = (long)ostamp - (long)stamp; if (nonce_stamp_slop_limit && @@ -575,6 +578,45 @@ leave: return retval; } +/* + * Return 1 if there is no push_cert or if the push options in push_cert are + * the same as those in the argument; 0 otherwise. + */ +static int check_cert_push_options(const struct string_list *push_options) +{ + const char *buf = push_cert.buf; + int len = push_cert.len; + + char *option; + const char *next_line; + int options_seen = 0; + + int retval = 1; + + if (!len) + return 1; + + while ((option = find_header(buf, len, "push-option", &next_line))) { + len -= (next_line - buf); + buf = next_line; + options_seen++; + if (options_seen > push_options->nr + || strcmp(option, + push_options->items[options_seen - 1].string)) { + retval = 0; + goto leave; + } + free(option); + } + + if (options_seen != push_options->nr) + retval = 0; + +leave: + free(option); + return retval; +} + static void prepare_push_cert_sha1(struct child_process *proc) { static int already_done; @@ -723,7 +765,7 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep) return -1; /* EOF */ strbuf_reset(&state->buf); strbuf_addf(&state->buf, "%s %s %s\n", - sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1), + oid_to_hex(&cmd->old_oid), oid_to_hex(&cmd->new_oid), cmd->ref_name); state->cmd = cmd->next; if (bufp) { @@ -764,15 +806,14 @@ static int run_update_hook(struct command *cmd) return 0; argv[1] = cmd->ref_name; - argv[2] = sha1_to_hex(cmd->old_sha1); - argv[3] = sha1_to_hex(cmd->new_sha1); + argv[2] = oid_to_hex(&cmd->old_oid); + argv[3] = oid_to_hex(&cmd->new_oid); argv[4] = NULL; proc.no_stdin = 1; proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; proc.argv = argv; - proc.env = tmp_objdir_env(tmp_objdir); code = start_command(&proc); if (code) @@ -831,7 +872,7 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]); static int update_shallow_ref(struct command *cmd, struct shallow_info *si) { static struct lock_file shallow_lock; - struct sha1_array extra = SHA1_ARRAY_INIT; + struct oid_array extra = OID_ARRAY_INIT; struct check_connected_options opt = CHECK_CONNECTED_INIT; uint32_t mask = 1 << (cmd->index % 32); int i; @@ -842,13 +883,13 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) if (si->used_shallow[i] && (si->used_shallow[i][cmd->index / 32] & mask) && !delayed_reachability_test(si, i)) - sha1_array_append(&extra, si->shallow->sha1[i]); + oid_array_append(&extra, &si->shallow->oid[i]); opt.env = tmp_objdir_env(tmp_objdir); setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra); if (check_connected(command_singleton_iterator, cmd, &opt)) { rollback_lock_file(&shallow_lock); - sha1_array_clear(&extra); + oid_array_clear(&extra); return -1; } @@ -859,10 +900,10 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) * not lose these new roots.. */ for (i = 0; i < extra.nr; i++) - register_shallow(extra.sha1[i]); + register_shallow(&extra.oid[i]); si->shallow_ref[cmd->index] = 0; - sha1_array_clear(&extra); + oid_array_clear(&extra); return 0; } @@ -987,9 +1028,10 @@ static const char *update(struct command *cmd, struct shallow_info *si) { const char *name = cmd->ref_name; struct strbuf namespaced_name_buf = STRBUF_INIT; - const char *namespaced_name, *ret; - unsigned char *old_sha1 = cmd->old_sha1; - unsigned char *new_sha1 = cmd->new_sha1; + static char *namespaced_name; + const char *ret; + struct object_id *old_oid = &cmd->old_oid; + struct object_id *new_oid = &cmd->new_oid; /* only refs/... are allowed */ if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) { @@ -998,6 +1040,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) } strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name); + free(namespaced_name); namespaced_name = strbuf_detach(&namespaced_name_buf, NULL); if (is_ref_checked_out(namespaced_name)) { @@ -1014,20 +1057,20 @@ static const char *update(struct command *cmd, struct shallow_info *si) refuse_unconfigured_deny(); return "branch is currently checked out"; case DENY_UPDATE_INSTEAD: - ret = update_worktree(new_sha1); + ret = update_worktree(new_oid->hash); if (ret) return ret; break; } } - if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) { + if (!is_null_oid(new_oid) && !has_object_file(new_oid)) { error("unpack should have generated %s, " - "but I can't find it!", sha1_to_hex(new_sha1)); + "but I can't find it!", oid_to_hex(new_oid)); return "bad pack"; } - if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) { + if (!is_null_oid(old_oid) && is_null_oid(new_oid)) { if (deny_deletes && starts_with(name, "refs/heads/")) { rp_error("denying ref deletion for %s", name); return "deletion prohibited"; @@ -1053,14 +1096,14 @@ static const char *update(struct command *cmd, struct shallow_info *si) } } - if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && - !is_null_sha1(old_sha1) && + if (deny_non_fast_forwards && !is_null_oid(new_oid) && + !is_null_oid(old_oid) && starts_with(name, "refs/heads/")) { struct object *old_object, *new_object; struct commit *old_commit, *new_commit; - old_object = parse_object(old_sha1); - new_object = parse_object(new_sha1); + old_object = parse_object(old_oid); + new_object = parse_object(new_oid); if (!old_object || !new_object || old_object->type != OBJ_COMMIT || @@ -1081,10 +1124,10 @@ static const char *update(struct command *cmd, struct shallow_info *si) return "hook declined"; } - if (is_null_sha1(new_sha1)) { + if (is_null_oid(new_oid)) { struct strbuf err = STRBUF_INIT; - if (!parse_object(old_sha1)) { - old_sha1 = NULL; + if (!parse_object(old_oid)) { + old_oid = NULL; if (ref_exists(name)) { rp_warning("Allowing deletion of corrupt ref."); } else { @@ -1094,7 +1137,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) } if (ref_transaction_delete(transaction, namespaced_name, - old_sha1, + old_oid->hash, 0, "push", &err)) { rp_error("%s", err.buf); strbuf_release(&err); @@ -1111,7 +1154,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) if (ref_transaction_update(transaction, namespaced_name, - new_sha1, old_sha1, + new_oid->hash, old_oid->hash, 0, "push", &err)) { rp_error("%s", err.buf); @@ -1162,7 +1205,7 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) const char *dst_name; struct string_list_item *item; struct command *dst_cmd; - unsigned char sha1[GIT_SHA1_RAWSZ]; + unsigned char sha1[GIT_MAX_RAWSZ]; int flag; strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name); @@ -1187,8 +1230,8 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) dst_cmd = (struct command *) item->util; - if (!hashcmp(cmd->old_sha1, dst_cmd->old_sha1) && - !hashcmp(cmd->new_sha1, dst_cmd->new_sha1)) + if (!oidcmp(&cmd->old_oid, &dst_cmd->old_oid) && + !oidcmp(&cmd->new_oid, &dst_cmd->new_oid)) return; dst_cmd->skip_update = 1; @@ -1196,11 +1239,11 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) rp_error("refusing inconsistent update between symref '%s' (%s..%s) and" " its target '%s' (%s..%s)", cmd->ref_name, - find_unique_abbrev(cmd->old_sha1, DEFAULT_ABBREV), - find_unique_abbrev(cmd->new_sha1, DEFAULT_ABBREV), + find_unique_abbrev(cmd->old_oid.hash, DEFAULT_ABBREV), + find_unique_abbrev(cmd->new_oid.hash, DEFAULT_ABBREV), dst_cmd->ref_name, - find_unique_abbrev(dst_cmd->old_sha1, DEFAULT_ABBREV), - find_unique_abbrev(dst_cmd->new_sha1, DEFAULT_ABBREV)); + find_unique_abbrev(dst_cmd->old_oid.hash, DEFAULT_ABBREV), + find_unique_abbrev(dst_cmd->new_oid.hash, DEFAULT_ABBREV)); cmd->error_string = dst_cmd->error_string = "inconsistent aliased update"; @@ -1231,10 +1274,10 @@ static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]) struct command **cmd_list = cb_data; struct command *cmd = *cmd_list; - if (!cmd || is_null_sha1(cmd->new_sha1)) + if (!cmd || is_null_oid(&cmd->new_oid)) return -1; /* end of list */ *cmd_list = NULL; /* this returns only one */ - hashcpy(sha1, cmd->new_sha1); + hashcpy(sha1, cmd->new_oid.hash); return 0; } @@ -1275,8 +1318,8 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20]) if (shallow_update && data->si->shallow_ref[cmd->index]) /* to be checked in update_shallow_ref() */ continue; - if (!is_null_sha1(cmd->new_sha1) && !cmd->skip_update) { - hashcpy(sha1, cmd->new_sha1); + if (!is_null_oid(&cmd->new_oid) && !cmd->skip_update) { + hashcpy(sha1, cmd->new_oid.hash); *cmd_list = cmd->next; return 0; } @@ -1303,7 +1346,7 @@ static void reject_updates_to_hidden(struct command *commands) if (!ref_is_hidden(cmd->ref_name, refname_full.buf)) continue; - if (is_null_sha1(cmd->new_sha1)) + if (is_null_oid(&cmd->new_oid)) cmd->error_string = "deny deleting a hidden ref"; else cmd->error_string = "deny updating a hidden ref"; @@ -1486,23 +1529,23 @@ static struct command **queue_command(struct command **tail, const char *line, int linelen) { - unsigned char old_sha1[20], new_sha1[20]; + struct object_id old_oid, new_oid; struct command *cmd; const char *refname; int reflen; + const char *p; - if (linelen < 83 || - line[40] != ' ' || - line[81] != ' ' || - get_sha1_hex(line, old_sha1) || - get_sha1_hex(line + 41, new_sha1)) + if (parse_oid_hex(line, &old_oid, &p) || + *p++ != ' ' || + parse_oid_hex(p, &new_oid, &p) || + *p++ != ' ') die("protocol error: expected old/new/ref, got '%s'", line); - refname = line + 82; - reflen = linelen - 82; + refname = p; + reflen = linelen - (p - line); FLEX_ALLOC_MEM(cmd, ref_name, refname, reflen); - hashcpy(cmd->old_sha1, old_sha1); - hashcpy(cmd->new_sha1, new_sha1); + oidcpy(&cmd->old_oid, &old_oid); + oidcpy(&cmd->new_oid, &new_oid); *tail = cmd; return &cmd->next; } @@ -1524,12 +1567,12 @@ static void queue_commands_from_cert(struct command **tail, while (boc < eoc) { const char *eol = memchr(boc, '\n', eoc - boc); - tail = queue_command(tail, boc, eol ? eol - boc : eoc - eol); + tail = queue_command(tail, boc, eol ? eol - boc : eoc - boc); boc = eol ? eol + 1 : eoc; } } -static struct command *read_head_info(struct sha1_array *shallow) +static struct command *read_head_info(struct oid_array *shallow) { struct command *commands = NULL; struct command **p = &commands; @@ -1541,12 +1584,12 @@ static struct command *read_head_info(struct sha1_array *shallow) if (!line) break; - if (len == 48 && starts_with(line, "shallow ")) { - unsigned char sha1[20]; - if (get_sha1_hex(line + 8, sha1)) + if (len > 8 && starts_with(line, "shallow ")) { + struct object_id oid; + if (get_oid_hex(line + 8, &oid)) die("protocol error: expected shallow sha, got '%s'", line + 8); - sha1_array_append(shallow, sha1); + oid_array_append(shallow, &oid); continue; } @@ -1634,12 +1677,17 @@ static const char *parse_pack_header(struct pack_header *hdr) static const char *pack_lockfile; +static void push_header_arg(struct argv_array *args, struct pack_header *hdr) +{ + argv_array_pushf(args, "--pack_header=%"PRIu32",%"PRIu32, + ntohl(hdr->hdr_version), ntohl(hdr->hdr_entries)); +} + static const char *unpack(int err_fd, struct shallow_info *si) { struct pack_header hdr; const char *hdr_err; int status; - char hdr_arg[38]; struct child_process child = CHILD_PROCESS_INIT; int fsck_objects = (receive_fsck_objects >= 0 ? receive_fsck_objects @@ -1653,9 +1701,6 @@ static const char *unpack(int err_fd, struct shallow_info *si) close(err_fd); return hdr_err; } - snprintf(hdr_arg, sizeof(hdr_arg), - "--pack_header=%"PRIu32",%"PRIu32, - ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries)); if (si->nr_ours || si->nr_theirs) { alt_shallow_file = setup_temporary_shallow(si->shallow); @@ -1679,7 +1724,8 @@ static const char *unpack(int err_fd, struct shallow_info *si) tmp_objdir_add_as_alternate(tmp_objdir); if (ntohl(hdr.hdr_entries) < unpack_limit) { - argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL); + argv_array_push(&child.args, "unpack-objects"); + push_header_arg(&child.args, &hdr); if (quiet) argv_array_push(&child.args, "-q"); if (fsck_objects) @@ -1695,12 +1741,12 @@ static const char *unpack(int err_fd, struct shallow_info *si) if (status) return "unpack-objects abnormal exit"; } else { - char hostname[256]; + char hostname[HOST_NAME_MAX + 1]; - argv_array_pushl(&child.args, "index-pack", - "--stdin", hdr_arg, NULL); + argv_array_pushl(&child.args, "index-pack", "--stdin", NULL); + push_header_arg(&child.args, &hdr); - if (gethostname(hostname, sizeof(hostname))) + if (xgethostname(hostname, sizeof(hostname))) xsnprintf(hostname, sizeof(hostname), "localhost"); argv_array_pushf(&child.args, "--keep=receive-pack %"PRIuMAX" on %s", @@ -1804,7 +1850,7 @@ static void prepare_shallow_update(struct command *commands, static void update_shallow_info(struct command *commands, struct shallow_info *si, - struct sha1_array *ref) + struct oid_array *ref) { struct command *cmd; int *ref_status; @@ -1815,9 +1861,9 @@ static void update_shallow_info(struct command *commands, } for (cmd = commands; cmd; cmd = cmd->next) { - if (is_null_sha1(cmd->new_sha1)) + if (is_null_oid(&cmd->new_oid)) continue; - sha1_array_append(ref, cmd->new_sha1); + oid_array_append(ref, &cmd->new_oid); cmd->index = ref->nr - 1; } si->ref = ref; @@ -1830,7 +1876,7 @@ static void update_shallow_info(struct command *commands, ALLOC_ARRAY(ref_status, ref->nr); assign_shallow_commits_to_refs(si, NULL, ref_status); for (cmd = commands; cmd; cmd = cmd->next) { - if (is_null_sha1(cmd->new_sha1)) + if (is_null_oid(&cmd->new_oid)) continue; if (ref_status[cmd->index]) { cmd->error_string = "shallow update not allowed"; @@ -1868,7 +1914,7 @@ static int delete_only(struct command *commands) { struct command *cmd; for (cmd = commands; cmd; cmd = cmd->next) { - if (!is_null_sha1(cmd->new_sha1)) + if (!is_null_oid(&cmd->new_oid)) return 0; } return 1; @@ -1878,8 +1924,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int advertise_refs = 0; struct command *commands; - struct sha1_array shallow = SHA1_ARRAY_INIT; - struct sha1_array ref = SHA1_ARRAY_INIT; + struct oid_array shallow = OID_ARRAY_INIT; + struct oid_array ref = OID_ARRAY_INIT; struct shallow_info si; struct option options[] = { @@ -1927,6 +1973,11 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) if (use_push_options) read_push_options(&push_options); + if (!check_cert_push_options(&push_options)) { + struct command *cmd; + for (cmd = commands; cmd; cmd = cmd->next) + cmd->error_string = "inconsistent push options"; + } prepare_shallow_info(&si, &shallow); if (!si.nr_ours && !si.nr_theirs) @@ -1971,8 +2022,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) } if (use_sideband) packet_flush(1); - sha1_array_clear(&shallow); - sha1_array_clear(&ref); + oid_array_clear(&shallow); + oid_array_clear(&ref); free((void *)push_cert_nonce); return 0; } diff --git a/builtin/reflog.c b/builtin/reflog.c index 7472775778..920c16dac0 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -16,14 +16,14 @@ static const char reflog_delete_usage[] = static const char reflog_exists_usage[] = "git reflog exists <ref>"; -static unsigned long default_reflog_expire; -static unsigned long default_reflog_expire_unreachable; +static timestamp_t default_reflog_expire; +static timestamp_t default_reflog_expire_unreachable; struct cmd_reflog_expire_cb { struct rev_info revs; int stalefix; - unsigned long expire_total; - unsigned long expire_unreachable; + timestamp_t expire_total; + timestamp_t expire_unreachable; int recno; }; @@ -55,14 +55,14 @@ struct collect_reflog_cb { #define STUDYING (1u<<11) #define REACHABLE (1u<<12) -static int tree_is_complete(const unsigned char *sha1) +static int tree_is_complete(const struct object_id *oid) { struct tree_desc desc; struct name_entry entry; int complete; struct tree *tree; - tree = lookup_tree(sha1); + tree = lookup_tree(oid); if (!tree) return 0; if (tree->object.flags & SEEN) @@ -73,7 +73,7 @@ static int tree_is_complete(const unsigned char *sha1) if (!tree->buffer) { enum object_type type; unsigned long size; - void *data = read_sha1_file(sha1, &type, &size); + void *data = read_sha1_file(oid->hash, &type, &size); if (!data) { tree->object.flags |= INCOMPLETE; return 0; @@ -85,7 +85,7 @@ static int tree_is_complete(const unsigned char *sha1) complete = 1; while (tree_entry(&desc, &entry)) { if (!has_sha1_file(entry.oid->hash) || - (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid->hash))) { + (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid))) { tree->object.flags |= INCOMPLETE; complete = 0; } @@ -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.oid.hash)) + if (!c->object.parsed && !parse_object(&c->object.oid)) 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.oid.hash)) { + if (!tree_is_complete(&c->tree->object.oid)) { is_incomplete = 1; c->object.flags |= INCOMPLETE; } @@ -186,13 +186,13 @@ static int commit_is_complete(struct commit *commit) return !is_incomplete; } -static int keep_entry(struct commit **it, unsigned char *sha1) +static int keep_entry(struct commit **it, struct object_id *oid) { struct commit *commit; - if (is_null_sha1(sha1)) + if (is_null_oid(oid)) return 1; - commit = lookup_commit_reference_gently(sha1, 1); + commit = lookup_commit_reference_gently(oid, 1); if (!commit) return 0; @@ -219,7 +219,7 @@ static int keep_entry(struct commit **it, unsigned char *sha1) static void mark_reachable(struct expire_reflog_policy_cb *cb) { struct commit_list *pending; - unsigned long expire_limit = cb->mark_limit; + timestamp_t expire_limit = cb->mark_limit; struct commit_list *leftover = NULL; for (pending = cb->mark_list; pending; pending = pending->next) @@ -251,17 +251,17 @@ static void mark_reachable(struct expire_reflog_policy_cb *cb) cb->mark_list = leftover; } -static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, unsigned char *sha1) +static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid) { /* * We may or may not have the commit yet - if not, look it * up using the supplied sha1. */ if (!commit) { - if (is_null_sha1(sha1)) + if (is_null_oid(oid)) return 0; - commit = lookup_commit_reference_gently(sha1, 1); + commit = lookup_commit_reference_gently(oid, 1); /* Not a commit -- keep it */ if (!commit) @@ -283,8 +283,8 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit /* * Return true iff the specified reflog entry should be expired. */ -static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, - const char *email, unsigned long timestamp, int tz, +static int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, + const char *email, timestamp_t timestamp, int tz, const char *message, void *cb_data) { struct expire_reflog_policy_cb *cb = cb_data; @@ -295,13 +295,13 @@ static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, old = new = NULL; if (cb->cmd.stalefix && - (!keep_entry(&old, osha1) || !keep_entry(&new, nsha1))) + (!keep_entry(&old, ooid) || !keep_entry(&new, noid))) return 1; if (timestamp < cb->cmd.expire_unreachable) { if (cb->unreachable_expire_kind == UE_ALWAYS) return 1; - if (unreachable(cb, old, osha1) || unreachable(cb, new, nsha1)) + if (unreachable(cb, old, ooid) || unreachable(cb, new, noid)) return 1; } @@ -318,7 +318,7 @@ static int push_tip_to_list(const char *refname, const struct object_id *oid, struct commit *tip_commit; if (flags & REF_ISSYMREF) return 0; - tip_commit = lookup_commit_reference_gently(oid->hash, 1); + tip_commit = lookup_commit_reference_gently(oid, 1); if (!tip_commit) return 0; commit_list_insert(tip_commit, list); @@ -326,7 +326,7 @@ static int push_tip_to_list(const char *refname, const struct object_id *oid, } static void reflog_expiry_prepare(const char *refname, - const unsigned char *sha1, + const struct object_id *oid, void *cb_data) { struct expire_reflog_policy_cb *cb = cb_data; @@ -335,7 +335,7 @@ static void reflog_expiry_prepare(const char *refname, cb->tip_commit = NULL; cb->unreachable_expire_kind = UE_HEAD; } else { - cb->tip_commit = lookup_commit_reference_gently(sha1, 1); + cb->tip_commit = lookup_commit_reference_gently(oid, 1); if (!cb->tip_commit) cb->unreachable_expire_kind = UE_ALWAYS; else @@ -392,8 +392,8 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus static struct reflog_expire_cfg { struct reflog_expire_cfg *next; - unsigned long expire_total; - unsigned long expire_unreachable; + timestamp_t expire_total; + timestamp_t expire_unreachable; char pattern[FLEX_ARRAY]; } *reflog_expire_cfg, **reflog_expire_cfg_tail; @@ -415,7 +415,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) return ent; } -static int parse_expire_cfg_value(const char *var, const char *value, unsigned long *expire) +static int parse_expire_cfg_value(const char *var, const char *value, timestamp_t *expire) { if (!value) return config_error_nonbool(var); @@ -433,7 +433,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb) { const char *pattern, *key; int pattern_len; - unsigned long expire; + timestamp_t expire; int slot; struct reflog_expire_cfg *ent; @@ -515,7 +515,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) { struct expire_reflog_policy_cb cb; - unsigned long now = time(NULL); + timestamp_t now = time(NULL); int i, status, do_all; int explicit_expiry = 0; unsigned int flags = 0; @@ -616,7 +616,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) } static int count_reflog_ent(struct object_id *ooid, struct object_id *noid, - const char *email, unsigned long timestamp, int tz, + const char *email, timestamp_t timestamp, int tz, const char *message, void *cb_data) { struct expire_reflog_policy_cb *cb = cb_data; diff --git a/builtin/repack.c b/builtin/repack.c index 677bc7c81a..38ba4ef825 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -155,6 +155,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) int keep_unreachable = 0; const char *window = NULL, *window_memory = NULL; const char *depth = NULL; + const char *threads = NULL; const char *max_pack_size = NULL; int no_reuse_delta = 0, no_reuse_object = 0; int no_update_server_info = 0; @@ -190,6 +191,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("same as the above, but limit memory size instead of entries count")), OPT_STRING(0, "depth", &depth, N_("n"), N_("limits the maximum delta depth")), + OPT_STRING(0, "threads", &threads, N_("n"), + N_("limits the maximum number of threads")), OPT_STRING(0, "max-pack-size", &max_pack_size, N_("bytes"), N_("maximum size of each packfile")), OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects, @@ -234,6 +237,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argv_array_pushf(&cmd.args, "--window-memory=%s", window_memory); if (depth) argv_array_pushf(&cmd.args, "--depth=%s", depth); + if (threads) + argv_array_pushf(&cmd.args, "--threads=%s", threads); if (max_pack_size) argv_array_pushf(&cmd.args, "--max-pack-size=%s", max_pack_size); if (no_reuse_delta) diff --git a/builtin/replace.c b/builtin/replace.c index f83e7b8fc1..c921bc976f 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -93,28 +93,34 @@ typedef int (*each_replace_name_fn)(const char *name, const char *ref, static int for_each_replace_name(const char **argv, each_replace_name_fn fn) { const char **p, *full_hex; - char ref[PATH_MAX]; + struct strbuf ref = STRBUF_INIT; + size_t base_len; int had_error = 0; struct object_id oid; + strbuf_addstr(&ref, git_replace_ref_base); + base_len = ref.len; + for (p = argv; *p; p++) { if (get_oid(*p, &oid)) { error("Failed to resolve '%s' as a valid ref.", *p); had_error = 1; continue; } - full_hex = oid_to_hex(&oid); - snprintf(ref, sizeof(ref), "%s%s", git_replace_ref_base, full_hex); - /* read_ref() may reuse the buffer */ - full_hex = ref + strlen(git_replace_ref_base); - if (read_ref(ref, oid.hash)) { + + strbuf_setlen(&ref, base_len); + strbuf_addstr(&ref, oid_to_hex(&oid)); + full_hex = ref.buf + base_len; + + if (read_ref(ref.buf, oid.hash)) { error("replace ref '%s' not found.", full_hex); had_error = 1; continue; } - if (fn(full_hex, ref, &oid)) + if (fn(full_hex, ref.buf, &oid)) had_error = 1; } + strbuf_release(&ref); return had_error; } @@ -129,21 +135,18 @@ static int delete_replace_ref(const char *name, const char *ref, static void check_ref_valid(struct object_id *object, struct object_id *prev, - char *ref, - int ref_size, + struct strbuf *ref, int force) { - if (snprintf(ref, ref_size, - "%s%s", git_replace_ref_base, - oid_to_hex(object)) > ref_size - 1) - die("replace ref name too long: %.*s...", 50, ref); - if (check_refname_format(ref, 0)) - die("'%s' is not a valid ref name.", ref); - - if (read_ref(ref, prev->hash)) + strbuf_reset(ref); + strbuf_addf(ref, "%s%s", git_replace_ref_base, oid_to_hex(object)); + if (check_refname_format(ref->buf, 0)) + die("'%s' is not a valid ref name.", ref->buf); + + if (read_ref(ref->buf, prev->hash)) oidclr(prev); else if (!force) - die("replace ref '%s' already exists", ref); + die("replace ref '%s' already exists", ref->buf); } static int replace_object_oid(const char *object_ref, @@ -154,7 +157,7 @@ static int replace_object_oid(const char *object_ref, { struct object_id prev; enum object_type obj_type, repl_type; - char ref[PATH_MAX]; + struct strbuf ref = STRBUF_INIT; struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; @@ -167,16 +170,17 @@ static int replace_object_oid(const char *object_ref, object_ref, typename(obj_type), replace_ref, typename(repl_type)); - check_ref_valid(object, &prev, ref, sizeof(ref), force); + check_ref_valid(object, &prev, &ref, force); transaction = ref_transaction_begin(&err); if (!transaction || - ref_transaction_update(transaction, ref, repl->hash, prev.hash, + ref_transaction_update(transaction, ref.buf, repl->hash, prev.hash, 0, NULL, &err) || ref_transaction_commit(transaction, &err)) die("%s", err.buf); ref_transaction_free(transaction); + strbuf_release(&ref); return 0; } @@ -280,7 +284,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw) char *tmpfile = git_pathdup("REPLACE_EDITOBJ"); enum object_type type; struct object_id old, new, prev; - char ref[PATH_MAX]; + struct strbuf ref = STRBUF_INIT; if (get_oid(object_ref, &old) < 0) die("Not a valid object name: '%s'", object_ref); @@ -289,7 +293,8 @@ static int edit_and_replace(const char *object_ref, int force, int raw) if (type < 0) die("unable to get object type for %s", oid_to_hex(&old)); - check_ref_valid(&old, &prev, ref, sizeof(ref), force); + check_ref_valid(&old, &prev, &ref, force); + strbuf_release(&ref); export_object(&old, type, raw, tmpfile); if (launch_editor(tmpfile, NULL, NULL) < 0) @@ -323,7 +328,7 @@ static void replace_parents(struct strbuf *buf, int argc, const char **argv) struct object_id oid; if (get_oid(argv[i], &oid) < 0) die(_("Not a valid object name: '%s'"), argv[i]); - lookup_commit_or_die(oid.hash, argv[i]); + lookup_commit_or_die(&oid, argv[i]); strbuf_addf(&new_parents, "parent %s\n", oid_to_hex(&oid)); } @@ -350,7 +355,7 @@ static void check_one_mergetag(struct commit *commit, int i; hash_sha1_file(extra->value, extra->len, typename(OBJ_TAG), tag_oid.hash); - tag = lookup_tag(tag_oid.hash); + tag = lookup_tag(&tag_oid); if (!tag) die(_("bad mergetag in commit '%s'"), ref); if (parse_tag_buffer(tag, extra->value, extra->len)) @@ -389,7 +394,7 @@ static int create_graft(int argc, const char **argv, int force) if (get_oid(old_ref, &old) < 0) die(_("Not a valid object name: '%s'"), old_ref); - commit = lookup_commit_or_die(old.hash, old_ref); + commit = lookup_commit_or_die(&old, old_ref); buffer = get_commit_buffer(commit, &size); strbuf_add(&buf, buffer, size); diff --git a/builtin/reset.c b/builtin/reset.c index fc3b906c47..0afe1df250 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -21,6 +21,27 @@ #include "parse-options.h" #include "unpack-trees.h" #include "cache-tree.h" +#include "submodule.h" +#include "submodule-config.h" + +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; + +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} static const char * const git_reset_usage[] = { N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"), @@ -84,7 +105,7 @@ static int reset_index(const struct object_id *oid, int reset_type, int quiet) return -1; if (reset_type == MIXED || reset_type == HARD) { - tree = parse_tree_indirect(oid->hash); + tree = parse_tree_indirect(oid); prime_cache_tree(&the_index, tree); } @@ -154,7 +175,7 @@ static int read_from_tree(const struct pathspec *pathspec, opt.format_callback = update_index_from_diff; opt.format_callback_data = &intent_to_add; - if (do_diff_cache(tree_oid->hash, &opt)) + if (do_diff_cache(tree_oid, &opt)) return 1; diffcore_std(&opt); diff_flush(&opt); @@ -283,6 +304,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix) N_("reset HEAD, index and working tree"), MERGE), OPT_SET_INT(0, "keep", &reset_type, N_("reset HEAD but keep local changes"), KEEP), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, + "reset", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")), OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that removed paths will be added later")), @@ -295,6 +319,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH); parse_args(&pathspec, argv, prefix, patch_mode, &rev); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) { + gitmodules_config(); + git_config(submodule_config, NULL); + set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON); + } + unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ @@ -303,7 +333,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) struct commit *commit; if (get_sha1_committish(rev, oid.hash)) die(_("Failed to resolve '%s' as a valid revision."), rev); - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); if (!commit) die(_("Could not parse object '%s'."), rev); oidcpy(&oid, &commit->object.oid); @@ -311,7 +341,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) struct tree *tree; if (get_sha1_treeish(rev, oid.hash)) die(_("Failed to resolve '%s' as a valid tree."), rev); - tree = parse_tree_indirect(oid.hash); + tree = parse_tree_indirect(&oid); if (!tree) die(_("Could not parse object '%s'."), rev); oidcpy(&oid, &tree->object.oid); @@ -380,7 +410,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) update_ref_status = reset_refs(rev, &oid); if (reset_type == HARD && !update_ref_status && !quiet) - print_new_head_line(lookup_commit_reference(oid.hash)); + print_new_head_line(lookup_commit_reference(&oid)); } if (!pathspec.nr) remove_branch_state(); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 0aa93d5891..718c6059c9 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -80,7 +80,7 @@ static void show_commit(struct commit *commit, void *data) } if (info->show_timestamp) - printf("%lu ", commit->date); + printf("%"PRItime" ", commit->date); if (info->header_prefix) fputs(info->header_prefix, stdout); @@ -181,7 +181,7 @@ static void finish_object(struct object *obj, const char *name, void *cb_data) 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->oid.hash); + parse_object(&obj->oid); } static void show_object(struct object *obj, const char *name, void *cb_data) @@ -212,7 +212,7 @@ static void print_var_int(const char *var, int val) static int show_bisect_vars(struct rev_list_info *info, int reaches, int all) { int cnt, flags = info->flags; - char hex[GIT_SHA1_HEXSZ + 1] = ""; + char hex[GIT_MAX_HEXSZ + 1] = ""; struct commit_list *tried; struct rev_info *revs = info->revs; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 9e53a1a7ca..efdc14473b 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -121,7 +121,7 @@ static void show_with_type(int type, const char *arg) } /* Output a revision, only if filter allows it */ -static void show_rev(int type, const unsigned char *sha1, const char *name) +static void show_rev(int type, const struct object_id *oid, const char *name) { if (!(filter & DO_REVS)) return; @@ -129,10 +129,10 @@ static void show_rev(int type, const unsigned char *sha1, const char *name) if ((symbolic || abbrev_ref) && name) { if (symbolic == SHOW_SYMBOLIC_FULL || abbrev_ref) { - unsigned char discard[20]; + struct object_id discard; char *full; - switch (dwim_ref(name, strlen(name), discard, &full)) { + switch (dwim_ref(name, strlen(name), discard.hash, &full)) { case 0: /* * Not found -- not a ref. We could @@ -158,9 +158,9 @@ static void show_rev(int type, const unsigned char *sha1, const char *name) } } else if (abbrev) - show_with_type(type, find_unique_abbrev(sha1, abbrev)); + show_with_type(type, find_unique_abbrev(oid->hash, abbrev)); else - show_with_type(type, sha1_to_hex(sha1)); + show_with_type(type, oid_to_hex(oid)); } /* Output a flag, only if filter allows it. */ @@ -180,11 +180,11 @@ static int show_default(void) const char *s = def; if (s) { - unsigned char sha1[20]; + struct object_id oid; def = NULL; - if (!get_sha1(s, sha1)) { - show_rev(NORMAL, sha1, s); + if (!get_oid(s, &oid)) { + show_rev(NORMAL, &oid, s); return 1; } } @@ -195,31 +195,32 @@ static int show_reference(const char *refname, const struct object_id *oid, int { if (ref_excluded(ref_excludes, refname)) return 0; - show_rev(NORMAL, oid->hash, refname); + show_rev(NORMAL, oid, refname); return 0; } static int anti_reference(const char *refname, const struct object_id *oid, int flag, void *cb_data) { - show_rev(REVERSED, oid->hash, refname); + show_rev(REVERSED, oid, refname); return 0; } -static int show_abbrev(const unsigned char *sha1, void *cb_data) +static int show_abbrev(const struct object_id *oid, void *cb_data) { - show_rev(NORMAL, sha1, NULL); + show_rev(NORMAL, oid, NULL); return 0; } static void show_datestring(const char *flag, const char *datestr) { - static char buffer[100]; + char *buffer; /* date handling requires both flags and revs */ if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS)) return; - snprintf(buffer, sizeof(buffer), "%s%lu", flag, approxidate(datestr)); + buffer = xstrfmt("%s%"PRItime, flag, approxidate(datestr)); show(buffer); + free(buffer); } static int show_file(const char *arg, int output_prefix) @@ -241,8 +242,8 @@ static int show_file(const char *arg, int output_prefix) static int try_difference(const char *arg) { char *dotdot; - unsigned char sha1[20]; - unsigned char end[20]; + struct object_id oid; + struct object_id end; const char *next; const char *this; int symmetric; @@ -272,18 +273,18 @@ static int try_difference(const char *arg) return 0; } - if (!get_sha1_committish(this, sha1) && !get_sha1_committish(next, end)) { - show_rev(NORMAL, end, next); - show_rev(symmetric ? NORMAL : REVERSED, sha1, this); + if (!get_sha1_committish(this, oid.hash) && !get_sha1_committish(next, end.hash)) { + show_rev(NORMAL, &end, next); + show_rev(symmetric ? NORMAL : REVERSED, &oid, this); if (symmetric) { struct commit_list *exclude; struct commit *a, *b; - a = lookup_commit_reference(sha1); - b = lookup_commit_reference(end); + a = lookup_commit_reference(&oid); + b = lookup_commit_reference(&end); exclude = get_merge_bases(a, b); while (exclude) { struct commit *commit = pop_commit(&exclude); - show_rev(REVERSED, commit->object.oid.hash, NULL); + show_rev(REVERSED, &commit->object.oid, NULL); } } *dotdot = '.'; @@ -296,7 +297,7 @@ static int try_difference(const char *arg) static int try_parent_shorthands(const char *arg) { char *dotdot; - unsigned char sha1[20]; + struct object_id oid; struct commit *commit; struct commit_list *parents; int parent_number; @@ -326,12 +327,12 @@ static int try_parent_shorthands(const char *arg) return 0; *dotdot = 0; - if (get_sha1_committish(arg, sha1)) { + if (get_sha1_committish(arg, oid.hash)) { *dotdot = '^'; return 0; } - commit = lookup_commit_reference(sha1); + commit = lookup_commit_reference(&oid); if (exclude_parent && exclude_parent > commit_list_count(commit->parents)) { *dotdot = '^'; @@ -339,7 +340,7 @@ static int try_parent_shorthands(const char *arg) } if (include_rev) - show_rev(NORMAL, sha1, arg); + show_rev(NORMAL, &oid, arg); for (parents = commit->parents, parent_number = 1; parents; parents = parents->next, parent_number++) { @@ -351,7 +352,7 @@ static int try_parent_shorthands(const char *arg) if (symbolic) name = xstrfmt("%s^%d", arg, parent_number); show_rev(include_parents ? NORMAL : REVERSED, - parents->item->object.oid.hash, name); + &parents->item->object.oid, name); free(name); } @@ -570,7 +571,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) int did_repo_setup = 0; int has_dashdash = 0; int output_prefix = 0; - unsigned char sha1[20]; + struct object_id oid; unsigned int flags = 0; const char *name = NULL; struct object_context unused; @@ -909,11 +910,11 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) name++; type = REVERSED; } - if (!get_sha1_with_context(name, flags, sha1, &unused)) { + if (!get_sha1_with_context(name, flags, oid.hash, &unused)) { if (verify) revs_count++; else - show_rev(type, sha1, name); + show_rev(type, &oid, name); continue; } if (verify) @@ -928,7 +929,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) strbuf_release(&buf); if (verify) { if (revs_count == 1) { - show_rev(type, sha1, name); + show_rev(type, &oid, name); return 0; } else if (revs_count == 0 && show_default()) return 0; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 832fd7ed0a..b8e2e74fe0 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -131,8 +131,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) const char *dest = NULL; int fd[2]; struct child_process *conn; - struct sha1_array extra_have = SHA1_ARRAY_INIT; - struct sha1_array shallow = SHA1_ARRAY_INIT; + struct oid_array extra_have = OID_ARRAY_INIT; + struct oid_array shallow = OID_ARRAY_INIT; struct ref *remote_refs, *local_refs; int ret; int helper_status = 0; diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 19756595d5..4a6cc6f490 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -358,7 +358,7 @@ static void sort_ref_range(int bottom, int top) static int append_ref(const char *refname, const struct object_id *oid, int allow_dups) { - struct commit *commit = lookup_commit_reference_gently(oid->hash, 1); + struct commit *commit = lookup_commit_reference_gently(oid, 1); int i; if (!commit) @@ -735,7 +735,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) base = strtoul(reflog_base, &ep, 10); if (*ep) { /* Ah, that is a date spec... */ - unsigned long at; + timestamp_t at; at = approxidate(reflog_base); read_ref_at(ref, flags, at, -1, oid.hash, NULL, NULL, NULL, &base); @@ -746,7 +746,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) char *logmsg; char *nth_desc; const char *msg; - unsigned long timestamp; + timestamp_t timestamp; int tz; if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg, @@ -816,7 +816,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) MAX_REVS), MAX_REVS); if (get_sha1(ref_name[num_rev], revkey.hash)) die(_("'%s' is not a valid ref."), ref_name[num_rev]); - commit = lookup_commit_reference(revkey.hash); + commit = lookup_commit_reference(&revkey); if (!commit) die(_("cannot find commit %s (%s)"), ref_name[num_rev], oid_to_hex(&revkey)); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 15a5430c00..566a5b6a6f 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -270,6 +270,29 @@ static int module_list_compute(int argc, const char **argv, return result; } +static void module_list_active(struct module_list *list) +{ + int i; + struct module_list active_modules = MODULE_LIST_INIT; + + gitmodules_config(); + + for (i = 0; i < list->nr; i++) { + const struct cache_entry *ce = list->entries[i]; + + if (!is_submodule_initialized(ce->name)) + continue; + + ALLOC_GROW(active_modules.entries, + active_modules.nr + 1, + active_modules.alloc); + active_modules.entries[active_modules.nr++] = ce; + } + + free(list->entries); + *list = active_modules; +} + static int module_list(int argc, const char **argv, const char *prefix) { int i; @@ -334,6 +357,18 @@ static void init_submodule(const char *path, const char *prefix, int quiet) displaypath); /* + * NEEDSWORK: In a multi-working-tree world, this needs to be + * set in the per-worktree config. + * + * Set active flag for the submodule being initialized + */ + if (!is_submodule_initialized(path)) { + strbuf_reset(&sb); + strbuf_addf(&sb, "submodule.%s.active", sub->name); + git_config_set_gently(sb.buf, "true"); + } + + /* * Copy url setting when it is not set yet. * To look up the url in .git/config, we must not fall back to * .gitmodules, so look it up directly. @@ -341,12 +376,12 @@ static void init_submodule(const char *path, const char *prefix, int quiet) strbuf_reset(&sb); strbuf_addf(&sb, "submodule.%s.url", sub->name); if (git_config_get_string(sb.buf, &url)) { - url = xstrdup(sub->url); - - if (!url) + if (!sub->url) die(_("No url found for submodule path '%s' in .gitmodules"), displaypath); + url = xstrdup(sub->url); + /* Possibly a url relative to parent */ if (starts_with_dot_dot_slash(url) || starts_with_dot_slash(url)) { @@ -420,6 +455,13 @@ static int module_init(int argc, const char **argv, const char *prefix) if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) return 1; + /* + * If there are no path args and submodule.active is set then, + * by default, only initialize 'active' modules. + */ + if (!argc && git_config_get_value_multi("submodule.active")) + module_list_active(&list); + for (i = 0; i < list.nr; i++) init_submodule(list.entries[i]->name, prefix, quiet); @@ -577,9 +619,7 @@ static int module_clone(int argc, const char **argv, const char *prefix) const char *name = NULL, *url = NULL, *depth = NULL; int quiet = 0; int progress = 0; - FILE *submodule_dot_git; char *p, *path = NULL, *sm_gitdir; - struct strbuf rel_path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; struct string_list reference = STRING_LIST_INIT_NODUP; char *sm_alternate = NULL, *error_strategy = NULL; @@ -651,27 +691,12 @@ static int module_clone(int argc, const char **argv, const char *prefix) strbuf_reset(&sb); } - /* Write a .git file in the submodule to redirect to the superproject. */ - strbuf_addf(&sb, "%s/.git", path); - if (safe_create_leading_directories_const(sb.buf) < 0) - die(_("could not create leading directories of '%s'"), sb.buf); - submodule_dot_git = fopen(sb.buf, "w"); - if (!submodule_dot_git) - die_errno(_("cannot open file '%s'"), sb.buf); - - fprintf_or_die(submodule_dot_git, "gitdir: %s\n", - relative_path(sm_gitdir, path, &rel_path)); - if (fclose(submodule_dot_git)) - die(_("could not close file %s"), sb.buf); - strbuf_reset(&sb); - strbuf_reset(&rel_path); + /* Connect module worktree and git dir */ + connect_work_tree_and_git_dir(path, sm_gitdir); - /* Redirect the worktree of the submodule in the superproject's config */ p = git_pathdup_submodule(path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), path); - git_config_set_in_file(p, "core.worktree", - relative_path(path, sm_gitdir, &rel_path)); /* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */ git_config_get_string("submodule.alternateLocation", &sm_alternate); @@ -687,7 +712,6 @@ static int module_clone(int argc, const char **argv, const char *prefix) free(error_strategy); strbuf_release(&sb); - strbuf_release(&rel_path); free(sm_gitdir); free(path); free(p); @@ -759,7 +783,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, struct strbuf displaypath_sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; const char *displaypath = NULL; - char *url = NULL; int needs_cloning = 0; if (ce_stage(ce)) { @@ -793,15 +816,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, goto cleanup; } - /* - * Looking up the url in .git/config. - * We must not fall back to .gitmodules as we only want - * to process configured submodules. - */ - strbuf_reset(&sb); - strbuf_addf(&sb, "submodule.%s.url", sub->name); - git_config_get_string(sb.buf, &url); - if (!url) { + /* Check if the submodule has been initialized. */ + if (!is_submodule_initialized(ce->name)) { next_submodule_warn_missing(suc, out, displaypath); goto cleanup; } @@ -835,7 +851,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, argv_array_push(&child->args, "--depth=1"); argv_array_pushl(&child->args, "--path", sub->path, NULL); argv_array_pushl(&child->args, "--name", sub->name, NULL); - argv_array_pushl(&child->args, "--url", url, NULL); + argv_array_pushl(&child->args, "--url", sub->url, NULL); if (suc->references.nr) { struct string_list_item *item; for_each_string_list_item(item, &suc->references) @@ -845,7 +861,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, argv_array_push(&child->args, suc->depth); cleanup: - free(url); strbuf_reset(&displaypath_sb); strbuf_reset(&sb); @@ -1090,6 +1105,50 @@ static int resolve_remote_submodule_branch(int argc, const char **argv, return 0; } +static int push_check(int argc, const char **argv, const char *prefix) +{ + struct remote *remote; + + if (argc < 2) + die("submodule--helper push-check requires at least 1 argument"); + + /* + * The remote must be configured. + * This is to avoid pushing to the exact same URL as the parent. + */ + remote = pushremote_get(argv[1]); + if (!remote || remote->origin == REMOTE_UNCONFIGURED) + die("remote '%s' not configured", argv[1]); + + /* Check the refspec */ + if (argc > 2) { + int i, refspec_nr = argc - 2; + struct ref *local_refs = get_local_heads(); + struct refspec *refspec = parse_push_refspec(refspec_nr, + argv + 2); + + for (i = 0; i < refspec_nr; i++) { + struct refspec *rs = refspec + i; + + if (rs->pattern || rs->matching) + continue; + + /* + * LHS must match a single ref + * NEEDSWORK: add logic to special case 'HEAD' once + * working with submodules in a detached head state + * ceases to be the norm. + */ + if (count_refspec_match(rs->src, local_refs, NULL) != 1) + die("src refspec '%s' must name a ref", + rs->src); + } + free_refspec(refspec_nr, refspec); + } + + return 0; +} + static int absorb_git_dirs(int argc, const char **argv, const char *prefix) { int i; @@ -1127,6 +1186,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix) return 0; } +static int is_active(int argc, const char **argv, const char *prefix) +{ + if (argc != 2) + die("submodule--helper is-active takes exactly 1 argument"); + + gitmodules_config(); + + return !is_submodule_initialized(argv[1]); +} + #define SUPPORT_SUPER_PREFIX (1<<0) struct cmd_struct { @@ -1145,7 +1214,9 @@ static struct cmd_struct commands[] = { {"resolve-relative-url-test", resolve_relative_url_test, 0}, {"init", module_init, SUPPORT_SUPER_PREFIX}, {"remote-branch", resolve_remote_submodule_branch, 0}, + {"push-check", push_check, 0}, {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX}, + {"is-active", is_active, 0}, }; int cmd_submodule__helper(int argc, const char **argv, const char *prefix) diff --git a/builtin/tag.c b/builtin/tag.c index ad29be6923..1f74a56db7 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -22,7 +22,7 @@ static const char * const git_tag_usage[] = { N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"), N_("git tag -d <tagname>..."), - N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]" + N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]" "\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"), N_("git tag -v [--format=<format>] <tagname>..."), NULL @@ -66,45 +66,42 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con } typedef int (*each_tag_name_fn)(const char *name, const char *ref, - const unsigned char *sha1, const void *cb_data); + const struct object_id *oid, const void *cb_data); static int for_each_tag_name(const char **argv, each_tag_name_fn fn, const void *cb_data) { const char **p; - char ref[PATH_MAX]; + struct strbuf ref = STRBUF_INIT; int had_error = 0; - unsigned char sha1[20]; + struct object_id oid; for (p = argv; *p; p++) { - if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p) - >= sizeof(ref)) { - error(_("tag name too long: %.*s..."), 50, *p); - had_error = 1; - continue; - } - if (read_ref(ref, sha1)) { + strbuf_reset(&ref); + strbuf_addf(&ref, "refs/tags/%s", *p); + if (read_ref(ref.buf, oid.hash)) { error(_("tag '%s' not found."), *p); had_error = 1; continue; } - if (fn(*p, ref, sha1, cb_data)) + if (fn(*p, ref.buf, &oid, cb_data)) had_error = 1; } + strbuf_release(&ref); return had_error; } static int delete_tag(const char *name, const char *ref, - const unsigned char *sha1, const void *cb_data) + const struct object_id *oid, const void *cb_data) { - if (delete_ref(NULL, ref, sha1, 0)) + if (delete_ref(NULL, ref, oid->hash, 0)) return 1; - printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(sha1, DEFAULT_ABBREV)); + printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(oid->hash, DEFAULT_ABBREV)); return 0; } static int verify_tag(const char *name, const char *ref, - const unsigned char *sha1, const void *cb_data) + const struct object_id *oid, const void *cb_data) { int flags; const char *fmt_pretty = cb_data; @@ -113,11 +110,11 @@ static int verify_tag(const char *name, const char *ref, if (fmt_pretty) flags = GPG_VERIFY_OMIT_STATUS; - if (gpg_verify_tag(sha1, name, flags)) + if (gpg_verify_tag(oid->hash, name, flags)) return -1; if (fmt_pretty) - pretty_print_ref(name, sha1, fmt_pretty); + pretty_print_ref(name, oid->hash, fmt_pretty); return 0; } @@ -185,13 +182,13 @@ static int git_tag_config(const char *var, const char *value, void *cb) return git_default_config(var, value, cb); } -static void write_tag_body(int fd, const unsigned char *sha1) +static void write_tag_body(int fd, const struct object_id *oid) { unsigned long size; enum object_type type; char *buf, *sp; - buf = read_sha1_file(sha1, &type, &size); + buf = read_sha1_file(oid->hash, &type, &size); if (!buf) return; /* skip header */ @@ -207,11 +204,11 @@ static void write_tag_body(int fd, const unsigned char *sha1) free(buf); } -static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result) +static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result) { if (sign && do_sign(buf) < 0) return error(_("unable to sign the tag")); - if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0) + if (write_sha1_file(buf->buf, buf->len, tag_type, result->hash) < 0) return error(_("unable to write tag file")); return 0; } @@ -226,31 +223,27 @@ struct create_tag_options { } cleanup_mode; }; -static void create_tag(const unsigned char *object, const char *tag, +static void create_tag(const struct object_id *object, const char *tag, struct strbuf *buf, struct create_tag_options *opt, - unsigned char *prev, unsigned char *result) + struct object_id *prev, struct object_id *result) { enum object_type type; - char header_buf[1024]; - int header_len; + struct strbuf header = STRBUF_INIT; char *path = NULL; - type = sha1_object_info(object, NULL); + type = sha1_object_info(object->hash, NULL); if (type <= OBJ_NONE) die(_("bad object type.")); - header_len = snprintf(header_buf, sizeof(header_buf), - "object %s\n" - "type %s\n" - "tag %s\n" - "tagger %s\n\n", - sha1_to_hex(object), - typename(type), - tag, - git_committer_info(IDENT_STRICT)); - - if (header_len > sizeof(header_buf) - 1) - die(_("tag header too big.")); + strbuf_addf(&header, + "object %s\n" + "type %s\n" + "tag %s\n" + "tagger %s\n\n", + oid_to_hex(object), + typename(type), + tag, + git_committer_info(IDENT_STRICT)); if (!opt->message_given) { int fd; @@ -261,7 +254,7 @@ static void create_tag(const unsigned char *object, const char *tag, if (fd < 0) die_errno(_("could not create file '%s'"), path); - if (!is_null_sha1(prev)) { + if (!is_null_oid(prev)) { write_tag_body(fd, prev); } else { struct strbuf buf = STRBUF_INIT; @@ -288,7 +281,8 @@ static void create_tag(const unsigned char *object, const char *tag, if (!opt->message_given && !buf->len) die(_("no tag message?")); - strbuf_insert(buf, 0, header_buf, header_len); + strbuf_insert(buf, 0, header.buf, header.len); + strbuf_release(&header); if (build_tag_object(buf, opt->sign, result) < 0) { if (path) @@ -302,7 +296,7 @@ static void create_tag(const unsigned char *object, const char *tag, } } -static void create_reflog_msg(const unsigned char *sha1, struct strbuf *sb) +static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb) { enum object_type type; struct commit *c; @@ -315,36 +309,36 @@ static void create_reflog_msg(const unsigned char *sha1, struct strbuf *sb) if (rla) { strbuf_addstr(sb, rla); } else { - strbuf_addstr(sb, _("tag: tagging ")); - strbuf_add_unique_abbrev(sb, sha1, DEFAULT_ABBREV); + strbuf_addstr(sb, "tag: tagging "); + strbuf_add_unique_abbrev(sb, oid->hash, DEFAULT_ABBREV); } strbuf_addstr(sb, " ("); - type = sha1_object_info(sha1, NULL); + type = sha1_object_info(oid->hash, NULL); switch (type) { default: - strbuf_addstr(sb, _("object of unknown type")); + strbuf_addstr(sb, "object of unknown type"); break; case OBJ_COMMIT: - if ((buf = read_sha1_file(sha1, &type, &size)) != NULL) { + if ((buf = read_sha1_file(oid->hash, &type, &size)) != NULL) { subject_len = find_commit_subject(buf, &subject_start); strbuf_insert(sb, sb->len, subject_start, subject_len); } else { - strbuf_addstr(sb, _("commit object")); + strbuf_addstr(sb, "commit object"); } free(buf); - if ((c = lookup_commit_reference(sha1)) != NULL) + if ((c = lookup_commit_reference(oid)) != NULL) strbuf_addf(sb, ", %s", show_date(c->date, 0, DATE_MODE(SHORT))); break; case OBJ_TREE: - strbuf_addstr(sb, _("tree object")); + strbuf_addstr(sb, "tree object"); break; case OBJ_BLOB: - strbuf_addstr(sb, _("blob object")); + strbuf_addstr(sb, "blob object"); break; case OBJ_TAG: - strbuf_addstr(sb, _("other tag object")); + strbuf_addstr(sb, "other tag object"); break; } strbuf_addch(sb, ')'); @@ -384,7 +378,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) struct strbuf buf = STRBUF_INIT; struct strbuf ref = STRBUF_INIT; struct strbuf reflog_msg = STRBUF_INIT; - unsigned char object[20], prev[20]; + struct object_id object, prev; const char *object_ref, *tag; struct create_tag_options opt; char *cleanup_arg = NULL; @@ -424,14 +418,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_GROUP(N_("Tag listing options")), OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")), OPT_CONTAINS(&filter.with_commit, N_("print only tags that contain the commit")), + OPT_NO_CONTAINS(&filter.no_commit, N_("print only tags that don't contain the commit")), OPT_WITH(&filter.with_commit, N_("print only tags that contain the commit")), + OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")), OPT_MERGED(&filter, N_("print only tags that are merged")), OPT_NO_MERGED(&filter, N_("print only tags that are not merged")), OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"), N_("field name to sort on"), &parse_opt_ref_sorting), { OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"), - N_("print only tags of the object"), 0, parse_opt_object_name + N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT, + parse_opt_object_name, (intptr_t) "HEAD" }, OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")), @@ -454,8 +451,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix) } create_tag_object = (opt.sign || annotate || msg.given || msgfile); - if (argc == 0 && !cmdmode) - cmdmode = 'l'; + if (!cmdmode) { + if (argc == 0) + cmdmode = 'l'; + else if (filter.with_commit || filter.no_commit || + filter.points_at.nr || filter.merge_commit || + filter.lines != -1) + cmdmode = 'l'; + } if ((create_tag_object || force) && (cmdmode != 0)) usage_with_options(git_tag_usage, options); @@ -485,13 +488,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix) return ret; } if (filter.lines != -1) - die(_("-n option is only allowed with -l.")); + die(_("-n option is only allowed in list mode")); if (filter.with_commit) - die(_("--contains option is only allowed with -l.")); + die(_("--contains option is only allowed in list mode")); + if (filter.no_commit) + die(_("--no-contains option is only allowed in list mode")); if (filter.points_at.nr) - die(_("--points-at option is only allowed with -l.")); + die(_("--points-at option is only allowed in list mode")); if (filter.merge_commit) - die(_("--merged and --no-merged option are only allowed with -l")); + die(_("--merged and --no-merged options are only allowed in list mode")); if (cmdmode == 'd') return for_each_tag_name(argv, delete_tag, NULL); if (cmdmode == 'v') { @@ -523,14 +528,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (argc > 2) die(_("too many params")); - if (get_sha1(object_ref, object)) + if (get_oid(object_ref, &object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); if (strbuf_check_tag_ref(&ref, tag)) die(_("'%s' is not a valid tag name."), tag); - if (read_ref(ref.buf, prev)) - hashclr(prev); + if (read_ref(ref.buf, prev.hash)) + oidclr(&prev); else if (!force) die(_("tag '%s' already exists"), tag); @@ -545,24 +550,24 @@ int cmd_tag(int argc, const char **argv, const char *prefix) else die(_("Invalid cleanup mode %s"), cleanup_arg); - create_reflog_msg(object, &reflog_msg); + create_reflog_msg(&object, &reflog_msg); if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - create_tag(object, tag, &buf, &opt, prev, object); + create_tag(&object, tag, &buf, &opt, &prev, &object); } transaction = ref_transaction_begin(&err); if (!transaction || - ref_transaction_update(transaction, ref.buf, object, prev, + ref_transaction_update(transaction, ref.buf, object.hash, prev.hash, create_reflog ? REF_FORCE_CREATE_REFLOG : 0, reflog_msg.buf, &err) || ref_transaction_commit(transaction, &err)) die("%s", err.buf); ref_transaction_free(transaction); - if (force && !is_null_sha1(prev) && hashcmp(prev, object)) - printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev, DEFAULT_ABBREV)); + if (force && !is_null_oid(&prev) && oidcmp(&prev, &object)) + printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev.hash, DEFAULT_ABBREV)); strbuf_release(&err); strbuf_release(&buf); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 4532aa0831..8bc9997767 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -127,7 +127,7 @@ static void *get_data(unsigned long size) } struct delta_info { - unsigned char base_sha1[20]; + struct object_id base_oid; unsigned nr; off_t base_offset; unsigned long size; @@ -137,13 +137,13 @@ struct delta_info { static struct delta_info *delta_list; -static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1, +static void add_delta_to_list(unsigned nr, const struct object_id *base_oid, off_t base_offset, void *delta, unsigned long size) { struct delta_info *info = xmalloc(sizeof(*info)); - hashcpy(info->base_sha1, base_sha1); + oidcpy(&info->base_oid, base_oid); info->base_offset = base_offset; info->size = size; info->delta = delta; @@ -154,7 +154,7 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1, struct obj_info { off_t offset; - unsigned char sha1[20]; + struct object_id oid; struct object *obj; }; @@ -170,9 +170,9 @@ static unsigned nr_objects; */ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) { - unsigned char sha1[20]; + struct object_id oid; - if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), sha1) < 0) + if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), oid.hash) < 0) die("failed to write object %s", oid_to_hex(&obj->oid)); obj->flags |= FLAG_WRITTEN; } @@ -237,19 +237,19 @@ static void write_object(unsigned nr, enum object_type type, void *buf, unsigned long size) { if (!strict) { - if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0) + if (write_sha1_file(buf, size, typename(type), obj_list[nr].oid.hash) < 0) die("failed to write object"); added_object(nr, type, buf, size); free(buf); obj_list[nr].obj = NULL; } else if (type == OBJ_BLOB) { struct blob *blob; - if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0) + if (write_sha1_file(buf, size, typename(type), obj_list[nr].oid.hash) < 0) die("failed to write object"); added_object(nr, type, buf, size); free(buf); - blob = lookup_blob(obj_list[nr].sha1); + blob = lookup_blob(&obj_list[nr].oid); if (blob) blob->object.flags |= FLAG_WRITTEN; else @@ -258,9 +258,10 @@ static void write_object(unsigned nr, enum object_type type, } else { struct object *obj; int eaten; - hash_sha1_file(buf, size, typename(type), obj_list[nr].sha1); + hash_sha1_file(buf, size, typename(type), obj_list[nr].oid.hash); added_object(nr, type, buf, size); - obj = parse_object_buffer(obj_list[nr].sha1, type, size, buf, &eaten); + obj = parse_object_buffer(&obj_list[nr].oid, type, size, buf, + &eaten); if (!obj) die("invalid %s", typename(type)); add_object_buffer(obj, buf, size); @@ -296,7 +297,7 @@ static void added_object(unsigned nr, enum object_type type, struct delta_info *info; while ((info = *p) != NULL) { - if (!hashcmp(info->base_sha1, obj_list[nr].sha1) || + if (!oidcmp(&info->base_oid, &obj_list[nr].oid) || info->base_offset == obj_list[nr].offset) { *p = info->next; p = &delta_list; @@ -320,12 +321,12 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size, free(buf); } -static int resolve_against_held(unsigned nr, const unsigned char *base, +static int resolve_against_held(unsigned nr, const struct object_id *base, void *delta_data, unsigned long delta_size) { struct object *obj; struct obj_buffer *obj_buffer; - obj = lookup_object(base); + obj = lookup_object(base->hash); if (!obj) return 0; obj_buffer = lookup_object_buffer(obj); @@ -341,25 +342,25 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, { void *delta_data, *base; unsigned long base_size; - unsigned char base_sha1[20]; + struct object_id base_oid; if (type == OBJ_REF_DELTA) { - hashcpy(base_sha1, fill(20)); - use(20); + hashcpy(base_oid.hash, fill(GIT_SHA1_RAWSZ)); + use(GIT_SHA1_RAWSZ); delta_data = get_data(delta_size); if (dry_run || !delta_data) { free(delta_data); return; } - if (has_sha1_file(base_sha1)) + if (has_object_file(&base_oid)) ; /* Ok we have this one */ - else if (resolve_against_held(nr, base_sha1, + else if (resolve_against_held(nr, &base_oid, delta_data, delta_size)) return; /* we are done */ else { /* cannot resolve yet --- queue it */ - hashclr(obj_list[nr].sha1); - add_delta_to_list(nr, base_sha1, 0, delta_data, delta_size); + oidclr(&obj_list[nr].oid); + add_delta_to_list(nr, &base_oid, 0, delta_data, delta_size); return; } } else { @@ -399,8 +400,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, } else if (base_offset > obj_list[mid].offset) { lo = mid + 1; } else { - hashcpy(base_sha1, obj_list[mid].sha1); - base_found = !is_null_sha1(base_sha1); + oidcpy(&base_oid, &obj_list[mid].oid); + base_found = !is_null_oid(&base_oid); break; } } @@ -409,19 +410,19 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, * The delta base object is itself a delta that * has not been resolved yet. */ - hashclr(obj_list[nr].sha1); - add_delta_to_list(nr, null_sha1, base_offset, delta_data, delta_size); + oidclr(&obj_list[nr].oid); + add_delta_to_list(nr, &null_oid, base_offset, delta_data, delta_size); return; } } - if (resolve_against_held(nr, base_sha1, delta_data, delta_size)) + if (resolve_against_held(nr, &base_oid, delta_data, delta_size)) return; - base = read_sha1_file(base_sha1, &type, &base_size); + base = read_sha1_file(base_oid.hash, &type, &base_size); if (!base) { error("failed to read delta-pack base object %s", - sha1_to_hex(base_sha1)); + oid_to_hex(&base_oid)); if (!recover) exit(1); has_errors = 1; @@ -505,7 +506,7 @@ static void unpack_all(void) int cmd_unpack_objects(int argc, const char **argv, const char *prefix) { int i; - unsigned char sha1[20]; + struct object_id oid; check_replace_refs = 0; @@ -566,12 +567,12 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) git_SHA1_Init(&ctx); unpack_all(); git_SHA1_Update(&ctx, buffer, offset); - git_SHA1_Final(sha1, &ctx); + git_SHA1_Final(oid.hash, &ctx); if (strict) write_rest(); - if (hashcmp(fill(20), sha1)) + if (hashcmp(fill(GIT_SHA1_RAWSZ), oid.hash)) die("final sha1 did not match"); - use(20); + use(GIT_SHA1_RAWSZ); /* Write the last part of the buffer to stdout */ while (len) { diff --git a/builtin/update-index.c b/builtin/update-index.c index d74d72cc7f..ebfc09faa0 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -125,12 +125,16 @@ static int test_if_untracked_cache_is_supported(void) struct stat st; struct stat_data base; int fd, ret = 0; + char *cwd; strbuf_addstr(&mtime_dir, "mtime-test-XXXXXX"); if (!mkdtemp(mtime_dir.buf)) die_errno("Could not make temporary directory"); - fprintf(stderr, _("Testing mtime in '%s' "), xgetcwd()); + cwd = xgetcwd(); + fprintf(stderr, _("Testing mtime in '%s' "), cwd); + free(cwd); + atexit(remove_test_directory); xstat_mtime_dir(&st); fill_stat_data(&base, &st); diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 38bedf8f9f..05b734e6d1 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -18,14 +18,14 @@ static const char * const verify_commit_usage[] = { NULL }; -static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned long size, unsigned flags) +static int run_gpg_verify(const struct object_id *oid, const char *buf, unsigned long size, unsigned flags) { struct signature_check signature_check; int ret; memset(&signature_check, 0, sizeof(signature_check)); - ret = check_commit_signature(lookup_commit(sha1), &signature_check); + ret = check_commit_signature(lookup_commit(oid), &signature_check); print_signature_buffer(&signature_check, flags); signature_check_clear(&signature_check); @@ -35,22 +35,22 @@ static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned l static int verify_commit(const char *name, unsigned flags) { enum object_type type; - unsigned char sha1[20]; + struct object_id oid; char *buf; unsigned long size; int ret; - if (get_sha1(name, sha1)) + if (get_oid(name, &oid)) return error("commit '%s' not found.", name); - buf = read_sha1_file(sha1, &type, &size); + buf = read_sha1_file(oid.hash, &type, &size); if (!buf) return error("%s: unable to read file.", name); if (type != OBJ_COMMIT) return error("%s: cannot verify a non-commit object of type %s.", name, typename(type)); - ret = run_gpg_verify(sha1, buf, size, flags); + ret = run_gpg_verify(&oid, buf, size, flags); free(buf); return ret; diff --git a/builtin/worktree.c b/builtin/worktree.c index 9993ded41a..793306ea51 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -24,13 +24,14 @@ struct add_opts { int force; int detach; int checkout; + int keep_locked; const char *new_branch; int force_new_branch; }; static int show_only; static int verbose; -static unsigned long expire; +static timestamp_t expire; static int prune_worktree(const char *id, struct strbuf *reason) { @@ -106,8 +107,7 @@ static void prune_worktrees(void) printf("%s\n", reason.buf); if (show_only) continue; - strbuf_reset(&path); - strbuf_addstr(&path, git_path("worktrees/%s", d->d_name)); + git_path_buf(&path, "worktrees/%s", d->d_name); ret = remove_dir_recursively(&path, 0); if (ret < 0 && errno == ENOTDIR) ret = unlink(path.buf); @@ -131,7 +131,7 @@ static int prune(int ac, const char **av, const char *prefix) OPT_END() }; - expire = ULONG_MAX; + expire = TIME_MAX; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); if (ac) usage_with_options(worktree_usage, options); @@ -215,8 +215,7 @@ static int add_worktree(const char *path, const char *refname, } name = worktree_basename(path, &len); - strbuf_addstr(&sb_repo, - git_path("worktrees/%.*s", (int)(path + len - name), name)); + git_path_buf(&sb_repo, "worktrees/%.*s", (int)(path + len - name), name); len = sb_repo.len; if (safe_create_leading_directories_const(sb_repo.buf)) die_errno(_("could not create leading directories of '%s'"), @@ -242,7 +241,10 @@ static int add_worktree(const char *path, const char *refname, * after the preparation is over. */ strbuf_addf(&sb, "%s/locked", sb_repo.buf); - write_file(sb.buf, "initializing"); + if (!opts->keep_locked) + write_file(sb.buf, "initializing"); + else + write_file(sb.buf, "added with --lock"); strbuf_addf(&sb_git, "%s/.git", path); if (safe_create_leading_directories_const(sb_git.buf)) @@ -303,9 +305,11 @@ static int add_worktree(const char *path, const char *refname, junk_git_dir = NULL; done: - strbuf_reset(&sb); - strbuf_addf(&sb, "%s/locked", sb_repo.buf); - unlink_or_warn(sb.buf); + if (ret || !opts->keep_locked) { + strbuf_reset(&sb); + strbuf_addf(&sb, "%s/locked", sb_repo.buf); + unlink_or_warn(sb.buf); + } argv_array_clear(&child_env); strbuf_release(&sb); strbuf_release(&symref); @@ -328,6 +332,7 @@ static int add(int ac, const char **av, const char *prefix) N_("create or reset a branch")), OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), + OPT_BOOL(0, "lock", &opts.keep_locked, N_("keep the new working tree locked")), OPT_END() }; @@ -409,9 +414,11 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) find_unique_abbrev(wt->head_sha1, DEFAULT_ABBREV)); if (wt->is_detached) strbuf_addstr(&sb, "(detached HEAD)"); - else if (wt->head_ref) - strbuf_addf(&sb, "[%s]", shorten_unambiguous_ref(wt->head_ref, 0)); - else + else if (wt->head_ref) { + char *ref = shorten_unambiguous_ref(wt->head_ref, 0); + strbuf_addf(&sb, "[%s]", ref); + free(ref); + } else strbuf_addstr(&sb, "(error)"); } printf("%s\n", sb.buf); |