From: Junio C Hamano Date: Wed, 30 May 2018 12:51:27 +0000 (+0900) Subject: Merge branch 'jk/snprintf-truncation' X-Git-Tag: v2.18.0-rc0~6 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7c3d15fe3113cf48db60656eedd152c46f47bf6b?hp=-c Merge branch 'jk/snprintf-truncation' Avoid unchecked snprintf() to make future code auditing easier. * jk/snprintf-truncation: fmt_with_err: add a comment that truncation is OK shorten_unambiguous_ref: use xsnprintf fsmonitor: use internal argv_array of struct child_process log_write_email_headers: use strbufs http: use strbufs instead of fixed buffers --- 7c3d15fe3113cf48db60656eedd152c46f47bf6b diff --combined fsmonitor.c index ed3d1a074d,b6fcb0f08f..665bd2d425 --- a/fsmonitor.c +++ b/fsmonitor.c @@@ -97,19 -97,13 +97,13 @@@ void write_fsmonitor_extension(struct s static int query_fsmonitor(int version, uint64_t last_update, struct strbuf *query_result) { struct child_process cp = CHILD_PROCESS_INIT; - char ver[64]; - char date[64]; - const char *argv[4]; - if (!(argv[0] = core_fsmonitor)) + if (!core_fsmonitor) return -1; - snprintf(ver, sizeof(ver), "%d", version); - snprintf(date, sizeof(date), "%" PRIuMAX, (uintmax_t)last_update); - argv[1] = ver; - argv[2] = date; - argv[3] = NULL; - cp.argv = argv; + argv_array_push(&cp.args, core_fsmonitor); + argv_array_pushf(&cp.args, "%d", version); + argv_array_pushf(&cp.args, "%" PRIuMAX, (uintmax_t)last_update); cp.use_shell = 1; cp.dir = get_git_work_tree(); @@@ -185,9 -179,6 +179,9 @@@ void refresh_fsmonitor(struct index_sta for (i = 0; i < istate->cache_nr; i++) istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID; + /* If we're going to check every file, ensure we save the results */ + istate->cache_changed |= FSMONITOR_CHANGED; + if (istate->untracked) istate->untracked->use_fsmonitor = 0; } diff --combined http.c index d9155972d6,fc5fff90a7..deea47411a --- a/http.c +++ b/http.c @@@ -14,7 -14,6 +14,7 @@@ #include "packfile.h" #include "protocol.h" #include "string-list.h" +#include "object-store.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); static int trace_curl_data = 1; @@@ -63,9 -62,6 +63,9 @@@ static struct { "tlsv1.1", CURL_SSLVERSION_TLSv1_1 }, { "tlsv1.2", CURL_SSLVERSION_TLSv1_2 }, #endif +#if LIBCURL_VERSION_NUM >= 0x073400 + { "tlsv1.3", CURL_SSLVERSION_TLSv1_3 }, +#endif }; #if LIBCURL_VERSION_NUM >= 0x070903 static const char *ssl_key; @@@ -976,6 -972,21 +976,6 @@@ static void set_from_env(const char **v *var = val; } -static void protocol_http_header(void) -{ - if (get_protocol_version_config() > 0) { - struct strbuf protocol_header = STRBUF_INIT; - - strbuf_addf(&protocol_header, GIT_PROTOCOL_HEADER ": version=%d", - get_protocol_version_config()); - - - extra_http_headers = curl_slist_append(extra_http_headers, - protocol_header.buf); - strbuf_release(&protocol_header); - } -} - void http_init(struct remote *remote, const char *url, int proactive_auth) { char *low_speed_limit; @@@ -1006,6 -1017,8 +1006,6 @@@ if (remote) var_override(&http_proxy_authmethod, remote->http_proxy_authmethod); - protocol_http_header(); - pragma_header = curl_slist_append(http_copy_default_headers(), "Pragma: no-cache"); no_pragma_header = curl_slist_append(http_copy_default_headers(), @@@ -1778,14 -1791,6 +1778,14 @@@ static int http_request(const char *url headers = curl_slist_append(headers, buf.buf); + /* Add additional headers here */ + if (options && options->extra_headers) { + const struct string_list_item *item; + for_each_string_list_item(item, options->extra_headers) { + headers = curl_slist_append(headers, item->string); + } + } + curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip"); @@@ -1846,7 -1851,7 +1846,7 @@@ static int update_url_from_redirect(str return 0; if (!skip_prefix(asked, base->buf, &tail)) - die("BUG: update_url_from_redirect: %s is not a superset of %s", + BUG("update_url_from_redirect: %s is not a superset of %s", asked, base->buf); new_len = got->len; @@@ -1894,7 -1899,7 +1894,7 @@@ static int http_request_reauth(const ch strbuf_reset(result); break; default: - die("BUG: HTTP_KEEP_ERROR is only supported with strbufs"); + BUG("HTTP_KEEP_ERROR is only supported with strbufs"); } } @@@ -2038,8 -2043,7 +2038,8 @@@ int http_get_info_packs(const char *bas int ret = 0, i = 0; char *url, *data; struct strbuf buf = STRBUF_INIT; - unsigned char sha1[20]; + unsigned char hash[GIT_MAX_RAWSZ]; + const unsigned hexsz = the_hash_algo->hexsz; end_url_with_slash(&buf, base_url); strbuf_addstr(&buf, "objects/info/packs"); @@@ -2055,13 -2059,13 +2055,13 @@@ switch (data[i]) { case 'P': i++; - if (i + 52 <= buf.len && + if (i + hexsz + 12 <= buf.len && starts_with(data + i, " pack-") && - starts_with(data + i + 46, ".pack\n")) { - get_sha1_hex(data + i + 6, sha1); - fetch_and_setup_pack_index(packs_head, sha1, + starts_with(data + i + hexsz + 6, ".pack\n")) { + get_sha1_hex(data + i + 6, hash); + fetch_and_setup_pack_index(packs_head, hash, base_url); - i += 51; + i += hexsz + 11; break; } default: @@@ -2083,6 -2087,7 +2083,7 @@@ void release_http_pack_request(struct h preq->packfile = NULL; } preq->slot = NULL; + strbuf_release(&preq->tmpfile); free(preq->url); free(preq); } @@@ -2105,19 -2110,19 +2106,19 @@@ int finish_http_pack_request(struct htt lst = &((*lst)->next); *lst = (*lst)->next; - if (!strip_suffix(preq->tmpfile, ".pack.temp", &len)) + if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len)) - die("BUG: pack tmpfile does not end in .pack.temp?"); + BUG("pack tmpfile does not end in .pack.temp?"); - tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile); + tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf); argv_array_push(&ip.args, "index-pack"); argv_array_pushl(&ip.args, "-o", tmp_idx, NULL); - argv_array_push(&ip.args, preq->tmpfile); + argv_array_push(&ip.args, preq->tmpfile.buf); ip.git_cmd = 1; ip.no_stdin = 1; ip.no_stdout = 1; if (run_command(&ip)) { - unlink(preq->tmpfile); + unlink(preq->tmpfile.buf); unlink(tmp_idx); free(tmp_idx); return -1; @@@ -2125,13 -2130,13 +2126,13 @@@ unlink(sha1_pack_index_name(p->sha1)); - if (finalize_object_file(preq->tmpfile, sha1_pack_name(p->sha1)) + if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->sha1)) || finalize_object_file(tmp_idx, sha1_pack_index_name(p->sha1))) { free(tmp_idx); return -1; } - install_packed_git(p); + install_packed_git(the_repository, p); free(tmp_idx); return 0; } @@@ -2144,6 -2149,7 +2145,7 @@@ struct http_pack_request *new_http_pack struct http_pack_request *preq; preq = xcalloc(1, sizeof(*preq)); + strbuf_init(&preq->tmpfile, 0); preq->target = target; end_url_with_slash(&buf, base_url); @@@ -2151,12 -2157,11 +2153,11 @@@ sha1_to_hex(target->sha1)); preq->url = strbuf_detach(&buf, NULL); - snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp", - sha1_pack_name(target->sha1)); - preq->packfile = fopen(preq->tmpfile, "a"); + strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->sha1)); + preq->packfile = fopen(preq->tmpfile.buf, "a"); if (!preq->packfile) { error("Unable to open local file %s for pack", - preq->tmpfile); + preq->tmpfile.buf); goto abort; } @@@ -2183,6 -2188,7 +2184,7 @@@ return preq; abort: + strbuf_release(&preq->tmpfile); free(preq->url); free(preq); return NULL; @@@ -2202,7 -2208,7 +2204,7 @@@ static size_t fwrite_sha1_file(char *pt CURLcode c = curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code); if (c != CURLE_OK) - die("BUG: curl_easy_getinfo for HTTP code failed: %s", + BUG("curl_easy_getinfo for HTTP code failed: %s", curl_easy_strerror(c)); if (slot->http_code >= 300) return size; @@@ -2233,7 -2239,7 +2235,7 @@@ struct http_object_request *new_http_ob { char *hex = sha1_to_hex(sha1); struct strbuf filename = STRBUF_INIT; - char prevfile[PATH_MAX]; + struct strbuf prevfile = STRBUF_INIT; int prevlocal; char prev_buf[PREV_BUF_SIZE]; ssize_t prev_read = 0; @@@ -2241,40 -2247,41 +2243,41 @@@ struct http_object_request *freq; freq = xcalloc(1, sizeof(*freq)); + strbuf_init(&freq->tmpfile, 0); hashcpy(freq->sha1, sha1); freq->localfile = -1; - sha1_file_name(&filename, sha1); + sha1_file_name(the_repository, &filename, sha1); - snprintf(freq->tmpfile, sizeof(freq->tmpfile), - "%s.temp", filename.buf); + strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf); - snprintf(prevfile, sizeof(prevfile), "%s.prev", filename.buf); - unlink_or_warn(prevfile); - rename(freq->tmpfile, prevfile); - unlink_or_warn(freq->tmpfile); + strbuf_addf(&prevfile, "%s.prev", filename.buf); + unlink_or_warn(prevfile.buf); + rename(freq->tmpfile.buf, prevfile.buf); + unlink_or_warn(freq->tmpfile.buf); strbuf_release(&filename); if (freq->localfile != -1) error("fd leakage in start: %d", freq->localfile); - freq->localfile = open(freq->tmpfile, + freq->localfile = open(freq->tmpfile.buf, O_WRONLY | O_CREAT | O_EXCL, 0666); /* * This could have failed due to the "lazy directory creation"; * try to mkdir the last path component. */ if (freq->localfile < 0 && errno == ENOENT) { - char *dir = strrchr(freq->tmpfile, '/'); + char *dir = strrchr(freq->tmpfile.buf, '/'); if (dir) { *dir = 0; - mkdir(freq->tmpfile, 0777); + mkdir(freq->tmpfile.buf, 0777); *dir = '/'; } - freq->localfile = open(freq->tmpfile, + freq->localfile = open(freq->tmpfile.buf, O_WRONLY | O_CREAT | O_EXCL, 0666); } if (freq->localfile < 0) { - error_errno("Couldn't create temporary file %s", freq->tmpfile); + error_errno("Couldn't create temporary file %s", + freq->tmpfile.buf); goto abort; } @@@ -2288,7 -2295,7 +2291,7 @@@ * If a previous temp file is present, process what was already * fetched. */ - prevlocal = open(prevfile, O_RDONLY); + prevlocal = open(prevfile.buf, O_RDONLY); if (prevlocal != -1) { do { prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE); @@@ -2305,7 -2312,8 +2308,8 @@@ } while (prev_read > 0); close(prevlocal); } - unlink_or_warn(prevfile); + unlink_or_warn(prevfile.buf); + strbuf_release(&prevfile); /* * Reset inflate/SHA1 if there was an error reading the previous temp @@@ -2320,7 -2328,7 +2324,7 @@@ lseek(freq->localfile, 0, SEEK_SET); if (ftruncate(freq->localfile, 0) < 0) { error_errno("Couldn't truncate temporary file %s", - freq->tmpfile); + freq->tmpfile.buf); goto abort; } } @@@ -2350,6 -2358,7 +2354,7 @@@ return freq; abort: + strbuf_release(&prevfile); free(freq->url); free(freq); return NULL; @@@ -2377,24 -2386,25 +2382,24 @@@ int finish_http_object_request(struct h if (freq->http_code == 416) { warning("requested range invalid; we may already have all the data."); } else if (freq->curl_result != CURLE_OK) { - if (stat(freq->tmpfile, &st) == 0) + if (stat(freq->tmpfile.buf, &st) == 0) if (st.st_size == 0) - unlink_or_warn(freq->tmpfile); + unlink_or_warn(freq->tmpfile.buf); return -1; } git_inflate_end(&freq->stream); git_SHA1_Final(freq->real_sha1, &freq->c); if (freq->zret != Z_STREAM_END) { - unlink_or_warn(freq->tmpfile); + unlink_or_warn(freq->tmpfile.buf); return -1; } if (hashcmp(freq->sha1, freq->real_sha1)) { - unlink_or_warn(freq->tmpfile); + unlink_or_warn(freq->tmpfile.buf); return -1; } - - sha1_file_name(&filename, freq->sha1); + sha1_file_name(the_repository, &filename, freq->sha1); - freq->rename = finalize_object_file(freq->tmpfile, filename.buf); + freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf); strbuf_release(&filename); return freq->rename; @@@ -2402,7 -2412,7 +2407,7 @@@ void abort_http_object_request(struct http_object_request *freq) { - unlink_or_warn(freq->tmpfile); + unlink_or_warn(freq->tmpfile.buf); release_http_object_request(freq); } @@@ -2422,4 -2432,5 +2427,5 @@@ void release_http_object_request(struc release_active_slot(freq->slot); freq->slot = NULL; } + strbuf_release(&freq->tmpfile); } diff --combined http.h index 4df4a25e1a,d9379f9cb2..d305ca1dc7 --- a/http.h +++ b/http.h @@@ -172,13 -172,6 +172,13 @@@ struct http_get_options * for details. */ struct strbuf *base_url; + + /* + * If not NULL, contains additional HTTP headers to be sent with the + * request. The strings in the list must not be freed until after the + * request has completed. + */ + struct string_list *extra_headers; }; /* Return values for http_get_*() */ @@@ -207,7 -200,7 +207,7 @@@ struct http_pack_request struct packed_git *target; struct packed_git **lst; FILE *packfile; - char tmpfile[PATH_MAX]; + struct strbuf tmpfile; struct active_request_slot *slot; }; @@@ -219,7 -212,7 +219,7 @@@ extern void release_http_pack_request(s /* Helpers for fetching object */ struct http_object_request { char *url; - char tmpfile[PATH_MAX]; + struct strbuf tmpfile; int localfile; CURLcode curl_result; char errorstr[CURL_ERROR_SIZE]; diff --combined log-tree.c index 724bae0de2,4e83d7125b..4aef85331e --- a/log-tree.c +++ b/log-tree.c @@@ -177,7 -177,7 +177,7 @@@ static void show_parents(struct commit struct commit_list *p; for (p = commit->parents; p ; p = p->next) { struct commit *parent = p->item; - fprintf(file, " %s", find_unique_abbrev(parent->object.oid.hash, abbrev)); + fprintf(file, " %s", find_unique_abbrev(&parent->object.oid, abbrev)); } } @@@ -185,7 -185,7 +185,7 @@@ static void show_children(struct rev_in { struct commit_list *p = lookup_decoration(&opt->children, &commit->object); for ( ; p; p = p->next) { - fprintf(opt->diffopt.file, " %s", find_unique_abbrev(p->item->object.oid.hash, abbrev)); + fprintf(opt->diffopt.file, " %s", find_unique_abbrev(&p->item->object.oid, abbrev)); } } @@@ -362,8 -362,7 +362,8 @@@ void fmt_output_email_subject(struct st void log_write_email_headers(struct rev_info *opt, struct commit *commit, const char **extra_headers_p, - int *need_8bit_cte_p) + int *need_8bit_cte_p, + int maybe_multipart) { const char *extra_headers = opt->extra_headers; const char *name = oid_to_hex(opt->zero_commit ? @@@ -386,12 -385,16 +386,16 @@@ opt->ref_message_ids->items[i].string); graph_show_oneline(opt->graph); } - if (opt->mime_boundary) { + if (opt->mime_boundary && maybe_multipart) { - static char subject_buffer[1024]; - static char buffer[1024]; + static struct strbuf subject_buffer = STRBUF_INIT; + static struct strbuf buffer = STRBUF_INIT; struct strbuf filename = STRBUF_INIT; *need_8bit_cte_p = -1; /* NEVER */ - snprintf(subject_buffer, sizeof(subject_buffer) - 1, + + strbuf_reset(&subject_buffer); + strbuf_reset(&buffer); + + strbuf_addf(&subject_buffer, "%s" "MIME-Version: 1.0\n" "Content-Type: multipart/mixed;" @@@ -406,13 -409,13 +410,13 @@@ extra_headers ? extra_headers : "", mime_boundary_leader, opt->mime_boundary, mime_boundary_leader, opt->mime_boundary); - extra_headers = subject_buffer; + extra_headers = subject_buffer.buf; if (opt->numbered_files) strbuf_addf(&filename, "%d", opt->nr); else fmt_output_commit(&filename, commit, opt); - snprintf(buffer, sizeof(buffer) - 1, + strbuf_addf(&buffer, "\n--%s%s\n" "Content-Type: text/x-patch;" " name=\"%s\"\n" @@@ -423,7 -426,7 +427,7 @@@ filename.buf, opt->no_inline ? "attachment" : "inline", filename.buf); - opt->diffopt.stat_sep = buffer; + opt->diffopt.stat_sep = buffer.buf; strbuf_release(&filename); } *extra_headers_p = extra_headers; @@@ -489,9 -492,9 +493,9 @@@ static int is_common_merge(const struc && !commit->parents->next->next); } -static void show_one_mergetag(struct commit *commit, - struct commit_extra_header *extra, - void *data) +static int show_one_mergetag(struct commit *commit, + struct commit_extra_header *extra, + void *data) { struct rev_info *opt = (struct rev_info *)data; struct object_id oid; @@@ -503,7 -506,7 +507,7 @@@ hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid); tag = lookup_tag(&oid); if (!tag) - return; /* error message already given */ + return -1; /* error message already given */ strbuf_init(&verify_message, 256); if (parse_tag_buffer(tag, extra->value, extra->len)) @@@ -537,12 -540,11 +541,12 @@@ show_sig_lines(opt, status, verify_message.buf); strbuf_release(&verify_message); + return 0; } -static void show_mergetag(struct rev_info *opt, struct commit *commit) +static int show_mergetag(struct rev_info *opt, struct commit *commit) { - for_each_mergetag(show_one_mergetag, commit, opt); + return for_each_mergetag(show_one_mergetag, commit, opt); } void show_log(struct rev_info *opt) @@@ -560,7 -562,7 +564,7 @@@ if (!opt->graph) put_revision_mark(opt, commit); - fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), opt->diffopt.file); + fputs(find_unique_abbrev(&commit->object.oid, abbrev_commit), opt->diffopt.file); if (opt->print_parents) show_parents(commit, abbrev_commit, opt->diffopt.file); if (opt->children.name) @@@ -612,7 -614,7 +616,7 @@@ if (cmit_fmt_is_mail(opt->commit_format)) { log_write_email_headers(opt, commit, &extra_headers, - &ctx.need_8bit_cte); + &ctx.need_8bit_cte, 1); ctx.rev = opt; ctx.print_email_subject = 1; } else if (opt->commit_format != CMIT_FMT_USERFORMAT) { @@@ -622,8 -624,7 +626,8 @@@ if (!opt->graph) put_revision_mark(opt, commit); - fputs(find_unique_abbrev(commit->object.oid.hash, abbrev_commit), + fputs(find_unique_abbrev(&commit->object.oid, + abbrev_commit), opt->diffopt.file); if (opt->print_parents) show_parents(commit, abbrev_commit, opt->diffopt.file); @@@ -631,7 -632,8 +635,7 @@@ show_children(opt, commit, abbrev_commit); if (parent) fprintf(opt->diffopt.file, " (from %s)", - find_unique_abbrev(parent->object.oid.hash, - abbrev_commit)); + find_unique_abbrev(&parent->object.oid, abbrev_commit)); fputs(diff_get_color_opt(&opt->diffopt, DIFF_RESET), opt->diffopt.file); show_decorations(opt, commit); if (opt->commit_format == CMIT_FMT_ONELINE) { @@@ -808,7 -810,7 +812,7 @@@ static int log_tree_diff(struct rev_inf return 0; parse_commit_or_die(commit); - oid = &commit->tree->object.oid; + oid = get_commit_tree_oid(commit); /* Root commit? */ parents = get_saved_parents(opt, commit); @@@ -833,7 -835,7 +837,7 @@@ * we merged _in_. */ parse_commit_or_die(parents->item); - diff_tree_oid(&parents->item->tree->object.oid, + diff_tree_oid(get_commit_tree_oid(parents->item), oid, "", &opt->diffopt); log_tree_diff_flush(opt); return !opt->loginfo; @@@ -848,7 -850,7 +852,7 @@@ struct commit *parent = parents->item; parse_commit_or_die(parent); - diff_tree_oid(&parent->tree->object.oid, + diff_tree_oid(get_commit_tree_oid(parent), oid, "", &opt->diffopt); log_tree_diff_flush(opt); diff --combined refs.c index 20fb35d895,bd7ac72aa7..0eb379f931 --- a/refs.c +++ b/refs.c @@@ -13,8 -13,6 +13,8 @@@ #include "tag.h" #include "submodule.h" #include "worktree.h" +#include "argv-array.h" +#include "repository.h" /* * List of all available backends @@@ -208,7 -206,7 +208,7 @@@ char *refs_resolve_refdup(struct ref_st char *resolve_refdup(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_resolve_refdup(get_main_ref_store(), + return refs_resolve_refdup(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@@ -230,7 -228,7 +230,7 @@@ int refs_read_ref_full(struct ref_stor int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_read_ref_full(get_main_ref_store(), refname, + return refs_read_ref_full(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@@ -303,7 -301,7 +303,7 @@@ enum peel_status peel_object(const stru struct object *o = lookup_unknown_object(name->hash); if (o->type == OBJ_NONE) { - int type = sha1_object_info(name->hash, NULL); + int type = oid_object_info(the_repository, name, NULL); if (type < 0 || !object_as_type(o, type, 0)) return PEEL_INVALID; } @@@ -377,7 -375,7 +377,7 @@@ int refs_for_each_tag_ref(struct ref_st int for_each_tag_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@@ -387,7 -385,7 +387,7 @@@ int for_each_branch_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) @@@ -397,7 -395,7 +397,7 @@@ int for_each_remote_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data); } int head_ref_namespaced(each_ref_fn fn, void *cb_data) @@@ -503,19 -501,6 +503,19 @@@ int refname_match(const char *abbrev_na return 0; } +/* + * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add + * the results to 'prefixes' + */ +void expand_ref_prefix(struct argv_array *prefixes, const char *prefix) +{ + const char **p; + int len = strlen(prefix); + + for (p = ref_rev_parse_rules; *p; p++) + argv_array_pushf(prefixes, *p, len, prefix); +} + /* * *string and *len will only be substituted, and *string returned (for * later free()ing) if the string passed in is a magic short-hand form @@@ -615,8 -600,7 +615,8 @@@ int dwim_log(const char *str, int len, static int is_per_worktree_ref(const char *refname) { return !strcmp(refname, "HEAD") || - starts_with(refname, "refs/bisect/"); + starts_with(refname, "refs/bisect/") || + starts_with(refname, "refs/rewritten/"); } static int is_pseudoref_syntax(const char *refname) @@@ -660,7 -644,7 +660,7 @@@ static int write_pseudoref(const char * { const char *filename; int fd; - static struct lock_file lock; + struct lock_file lock = LOCK_INIT; struct strbuf buf = STRBUF_INIT; int ret = -1; @@@ -670,7 -654,8 +670,7 @@@ strbuf_addf(&buf, "%s\n", oid_to_hex(oid)); filename = git_path("%s", pseudoref); - fd = hold_lock_file_for_update_timeout(&lock, filename, - LOCK_DIE_ON_ERROR, + fd = hold_lock_file_for_update_timeout(&lock, filename, 0, get_files_ref_lock_timeout_ms()); if (fd < 0) { strbuf_addf(err, "could not open '%s' for writing: %s", @@@ -681,21 -666,10 +681,21 @@@ if (old_oid) { struct object_id actual_old_oid; - if (read_ref(pseudoref, &actual_old_oid)) - die("could not read ref '%s'", pseudoref); - if (oidcmp(&actual_old_oid, old_oid)) { - strbuf_addf(err, "unexpected sha1 when writing '%s'", pseudoref); + if (read_ref(pseudoref, &actual_old_oid)) { + if (!is_null_oid(old_oid)) { + strbuf_addf(err, "could not read ref '%s'", + pseudoref); + rollback_lock_file(&lock); + goto done; + } + } else if (is_null_oid(old_oid)) { + strbuf_addf(err, "ref '%s' already exists", + pseudoref); + rollback_lock_file(&lock); + goto done; + } else if (oidcmp(&actual_old_oid, old_oid)) { + strbuf_addf(err, "unexpected object ID when writing '%s'", + pseudoref); rollback_lock_file(&lock); goto done; } @@@ -716,28 -690,24 +716,28 @@@ done static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid) { - static struct lock_file lock; const char *filename; filename = git_path("%s", pseudoref); if (old_oid && !is_null_oid(old_oid)) { + struct lock_file lock = LOCK_INIT; int fd; struct object_id actual_old_oid; fd = hold_lock_file_for_update_timeout( - &lock, filename, LOCK_DIE_ON_ERROR, + &lock, filename, 0, get_files_ref_lock_timeout_ms()); - if (fd < 0) - die_errno(_("Could not open '%s' for writing"), filename); + if (fd < 0) { + error_errno(_("could not open '%s' for writing"), + filename); + return -1; + } if (read_ref(pseudoref, &actual_old_oid)) die("could not read ref '%s'", pseudoref); if (oidcmp(&actual_old_oid, old_oid)) { - warning("Unexpected sha1 when deleting %s", pseudoref); + error("unexpected object ID when deleting '%s'", + pseudoref); rollback_lock_file(&lock); return -1; } @@@ -760,7 -730,7 +760,7 @@@ int refs_delete_ref(struct ref_store *r struct strbuf err = STRBUF_INIT; if (ref_type(refname) == REF_TYPE_PSEUDOREF) { - assert(refs == get_main_ref_store()); + assert(refs == get_main_ref_store(the_repository)); return delete_pseudoref(refname, old_oid); } @@@ -782,7 -752,7 +782,7 @@@ int delete_ref(const char *msg, const char *refname, const struct object_id *old_oid, unsigned int flags) { - return refs_delete_ref(get_main_ref_store(), msg, refname, + return refs_delete_ref(get_main_ref_store(the_repository), msg, refname, old_oid, flags); } @@@ -958,7 -928,7 +958,7 @@@ struct ref_transaction *ref_store_trans struct ref_transaction *ref_transaction_begin(struct strbuf *err) { - return ref_store_transaction_begin(get_main_ref_store(), err); + return ref_store_transaction_begin(get_main_ref_store(the_repository), err); } void ref_transaction_free(struct ref_transaction *transaction) @@@ -974,10 -944,10 +974,10 @@@ /* OK */ break; case REF_TRANSACTION_PREPARED: - die("BUG: free called on a prepared reference transaction"); + BUG("free called on a prepared reference transaction"); break; default: - die("BUG: unexpected reference transaction state"); + BUG("unexpected reference transaction state"); break; } @@@ -999,7 -969,7 +999,7 @@@ struct ref_update *ref_transaction_add_ struct ref_update *update; if (transaction->state != REF_TRANSACTION_OPEN) - die("BUG: update called for transaction that is not open"); + BUG("update called for transaction that is not open"); FLEX_ALLOC_STR(update, refname, refname); ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc); @@@ -1049,7 -1019,7 +1049,7 @@@ int ref_transaction_create(struct ref_t struct strbuf *err) { if (!new_oid || is_null_oid(new_oid)) - die("BUG: create called without valid new_oid"); + BUG("create called without valid new_oid"); return ref_transaction_update(transaction, refname, new_oid, &null_oid, flags, msg, err); } @@@ -1061,7 -1031,7 +1061,7 @@@ int ref_transaction_delete(struct ref_t struct strbuf *err) { if (old_oid && is_null_oid(old_oid)) - die("BUG: delete called with old_oid set to zeros"); + BUG("delete called with old_oid set to zeros"); return ref_transaction_update(transaction, refname, &null_oid, old_oid, flags, msg, err); @@@ -1074,7 -1044,7 +1074,7 @@@ int ref_transaction_verify(struct ref_t struct strbuf *err) { if (!old_oid) - die("BUG: verify called with old_oid set to NULL"); + BUG("verify called with old_oid set to NULL"); return ref_transaction_update(transaction, refname, NULL, old_oid, flags, NULL, err); @@@ -1090,7 -1060,7 +1090,7 @@@ int refs_update_ref(struct ref_store *r int ret = 0; if (ref_type(refname) == REF_TYPE_PSEUDOREF) { - assert(refs == get_main_ref_store()); + assert(refs == get_main_ref_store(the_repository)); ret = write_pseudoref(refname, new_oid, old_oid, &err); } else { t = ref_store_transaction_begin(refs, &err); @@@ -1129,7 -1099,7 +1129,7 @@@ int update_ref(const char *msg, const c const struct object_id *old_oid, unsigned int flags, enum action_on_err onerr) { - return refs_update_ref(get_main_ref_store(), msg, refname, new_oid, + return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid, old_oid, flags, onerr); } @@@ -1162,8 -1132,8 +1162,8 @@@ char *shorten_unambiguous_ref(const cha for (i = 0; i < nr_rules; i++) { assert(offset < total_len); scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset; - offset += snprintf(scanf_fmts[i], total_len - offset, - ref_rev_parse_rules[i], 2, "%s") + 1; + offset += xsnprintf(scanf_fmts[i], total_len - offset, + ref_rev_parse_rules[i], 2, "%s") + 1; } } @@@ -1350,7 -1320,7 +1350,7 @@@ int refs_head_ref(struct ref_store *ref int head_ref(each_ref_fn fn, void *cb_data) { - return refs_head_ref(get_main_ref_store(), fn, cb_data); + return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data); } struct ref_iterator *refs_ref_iterator_begin( @@@ -1409,7 -1379,7 +1409,7 @@@ int refs_for_each_ref(struct ref_store int for_each_ref(each_ref_fn fn, void *cb_data) { - return refs_for_each_ref(get_main_ref_store(), fn, cb_data); + return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_ref_in(struct ref_store *refs, const char *prefix, @@@ -1420,7 -1390,7 +1420,7 @@@ int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data) { - return refs_for_each_ref_in(get_main_ref_store(), prefix, fn, cb_data); + return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data); } int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken) @@@ -1429,7 -1399,7 +1429,7 @@@ if (broken) flag = DO_FOR_EACH_INCLUDE_BROKEN; - return do_for_each_ref(get_main_ref_store(), + return do_for_each_ref(get_main_ref_store(the_repository), prefix, fn, 0, flag, cb_data); } @@@ -1444,9 -1414,9 +1444,9 @@@ int refs_for_each_fullref_in(struct ref return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data); } -int for_each_replace_ref(each_ref_fn fn, void *cb_data) +int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data) { - return do_for_each_ref(get_main_ref_store(), + return do_for_each_ref(get_main_ref_store(r), git_replace_ref_base, fn, strlen(git_replace_ref_base), DO_FOR_EACH_INCLUDE_BROKEN, cb_data); @@@ -1457,7 -1427,7 +1457,7 @@@ int for_each_namespaced_ref(each_ref_f struct strbuf buf = STRBUF_INIT; int ret; strbuf_addf(&buf, "%srefs/", get_git_namespace()); - ret = do_for_each_ref(get_main_ref_store(), + ret = do_for_each_ref(get_main_ref_store(the_repository), buf.buf, fn, 0, 0, cb_data); strbuf_release(&buf); return ret; @@@ -1471,7 -1441,7 +1471,7 @@@ int refs_for_each_rawref(struct ref_sto int for_each_rawref(each_ref_fn fn, void *cb_data) { - return refs_for_each_rawref(get_main_ref_store(), fn, cb_data); + return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data); } int refs_read_raw_ref(struct ref_store *ref_store, @@@ -1577,7 -1547,7 +1577,7 @@@ const char *refs_resolve_ref_unsafe(str /* backend functions */ int refs_init_db(struct strbuf *err) { - struct ref_store *refs = get_main_ref_store(); + struct ref_store *refs = get_main_ref_store(the_repository); return refs->be->init_db(refs, err); } @@@ -1585,7 -1555,7 +1585,7 @@@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, struct object_id *oid, int *flags) { - return refs_resolve_ref_unsafe(get_main_ref_store(), refname, + return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname, resolve_flags, oid, flags); } @@@ -1637,6 -1607,9 +1637,6 @@@ static struct ref_store_hash_entry *all return entry; } -/* A pointer to the ref_store for the main repository: */ -static struct ref_store *main_ref_store; - /* A hashmap of ref_stores, stored by submodule name: */ static struct hashmap submodule_ref_stores; @@@ -1672,22 -1645,19 +1672,22 @@@ static struct ref_store *ref_store_init struct ref_store *refs; if (!be) - die("BUG: reference backend %s is unknown", be_name); + BUG("reference backend %s is unknown", be_name); refs = be->init(gitdir, flags); return refs; } -struct ref_store *get_main_ref_store(void) +struct ref_store *get_main_ref_store(struct repository *r) { - if (main_ref_store) - return main_ref_store; + if (r->refs) + return r->refs; + + if (!r->gitdir) + BUG("attempting to get main_ref_store outside of repository"); - main_ref_store = ref_store_init(get_git_dir(), REF_STORE_ALL_CAPS); - return main_ref_store; + r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS); + return r->refs; } /* @@@ -1703,7 -1673,7 +1703,7 @@@ static void register_ref_store_map(stru hashmap_init(map, ref_store_hash_cmp, NULL, 0); if (hashmap_put(map, alloc_ref_store_hash_entry(name, refs))) - die("BUG: %s ref_store '%s' initialized twice", type, name); + BUG("%s ref_store '%s' initialized twice", type, name); } struct ref_store *get_submodule_ref_store(const char *submodule) @@@ -1756,7 -1726,7 +1756,7 @@@ struct ref_store *get_worktree_ref_stor const char *id; if (wt->is_current) - return get_main_ref_store(); + return get_main_ref_store(the_repository); id = wt->id ? wt->id : "/"; refs = lookup_ref_store_map(&worktree_ref_stores, id); @@@ -1812,7 -1782,7 +1812,7 @@@ int refs_peel_ref(struct ref_store *ref int peel_ref(const char *refname, struct object_id *oid) { - return refs_peel_ref(get_main_ref_store(), refname, oid); + return refs_peel_ref(get_main_ref_store(the_repository), refname, oid); } int refs_create_symref(struct ref_store *refs, @@@ -1828,7 -1798,7 +1828,7 @@@ int create_symref(const char *ref_target, const char *refs_heads_master, const char *logmsg) { - return refs_create_symref(get_main_ref_store(), ref_target, + return refs_create_symref(get_main_ref_store(the_repository), ref_target, refs_heads_master, logmsg); } @@@ -1849,7 -1819,7 +1849,7 @@@ int ref_update_reject_duplicates(struc refnames->items[i].string); return 1; } else if (cmp > 0) { - die("BUG: ref_update_reject_duplicates() received unsorted list"); + BUG("ref_update_reject_duplicates() received unsorted list"); } } return 0; @@@ -1865,13 -1835,13 +1865,13 @@@ int ref_transaction_prepare(struct ref_ /* Good. */ break; case REF_TRANSACTION_PREPARED: - die("BUG: prepare called twice on reference transaction"); + BUG("prepare called twice on reference transaction"); break; case REF_TRANSACTION_CLOSED: - die("BUG: prepare called on a closed reference transaction"); + BUG("prepare called on a closed reference transaction"); break; default: - die("BUG: unexpected reference transaction state"); + BUG("unexpected reference transaction state"); break; } @@@ -1898,10 -1868,10 +1898,10 @@@ int ref_transaction_abort(struct ref_tr ret = refs->be->transaction_abort(refs, transaction, err); break; case REF_TRANSACTION_CLOSED: - die("BUG: abort called on a closed reference transaction"); + BUG("abort called on a closed reference transaction"); break; default: - die("BUG: unexpected reference transaction state"); + BUG("unexpected reference transaction state"); break; } @@@ -1926,10 -1896,10 +1926,10 @@@ int ref_transaction_commit(struct ref_t /* Fall through to finish. */ break; case REF_TRANSACTION_CLOSED: - die("BUG: commit called on a closed reference transaction"); + BUG("commit called on a closed reference transaction"); break; default: - die("BUG: unexpected reference transaction state"); + BUG("unexpected reference transaction state"); break; } @@@ -2010,7 -1980,7 +2010,7 @@@ int refs_verify_refname_available(struc } if (ok != ITER_DONE) - die("BUG: error while iterating over references"); + BUG("error while iterating over references"); extra_refname = find_descendant_ref(dirname.buf, extras, skip); if (extra_refname) @@@ -2036,7 -2006,7 +2036,7 @@@ int refs_for_each_reflog(struct ref_sto int for_each_reflog(each_ref_fn fn, void *cb_data) { - return refs_for_each_reflog(get_main_ref_store(), fn, cb_data); + return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data); } int refs_for_each_reflog_ent_reverse(struct ref_store *refs, @@@ -2051,7 -2021,7 +2051,7 @@@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data) { - return refs_for_each_reflog_ent_reverse(get_main_ref_store(), + return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository), refname, fn, cb_data); } @@@ -2064,7 -2034,7 +2064,7 @@@ int refs_for_each_reflog_ent(struct ref int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data) { - return refs_for_each_reflog_ent(get_main_ref_store(), refname, + return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname, fn, cb_data); } @@@ -2075,7 -2045,7 +2075,7 @@@ int refs_reflog_exists(struct ref_stor int reflog_exists(const char *refname) { - return refs_reflog_exists(get_main_ref_store(), refname); + return refs_reflog_exists(get_main_ref_store(the_repository), refname); } int refs_create_reflog(struct ref_store *refs, const char *refname, @@@ -2087,7 -2057,7 +2087,7 @@@ int safe_create_reflog(const char *refname, int force_create, struct strbuf *err) { - return refs_create_reflog(get_main_ref_store(), refname, + return refs_create_reflog(get_main_ref_store(the_repository), refname, force_create, err); } @@@ -2098,7 -2068,7 +2098,7 @@@ int refs_delete_reflog(struct ref_stor int delete_reflog(const char *refname) { - return refs_delete_reflog(get_main_ref_store(), refname); + return refs_delete_reflog(get_main_ref_store(the_repository), refname); } int refs_reflog_expire(struct ref_store *refs, @@@ -2121,7 -2091,7 +2121,7 @@@ int reflog_expire(const char *refname, reflog_expiry_cleanup_fn cleanup_fn, void *policy_cb_data) { - return refs_reflog_expire(get_main_ref_store(), + return refs_reflog_expire(get_main_ref_store(the_repository), refname, oid, flags, prepare_fn, should_prune_fn, cleanup_fn, policy_cb_data); @@@ -2144,7 -2114,7 +2144,7 @@@ int refs_delete_refs(struct ref_store * int delete_refs(const char *msg, struct string_list *refnames, unsigned int flags) { - return refs_delete_refs(get_main_ref_store(), msg, refnames, flags); + return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags); } int refs_rename_ref(struct ref_store *refs, const char *oldref, @@@ -2155,7 -2125,7 +2155,7 @@@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) { - return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg); + return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); } int refs_copy_existing_ref(struct ref_store *refs, const char *oldref, @@@ -2166,5 -2136,5 +2166,5 @@@ int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg) { - return refs_copy_existing_ref(get_main_ref_store(), oldref, newref, logmsg); + return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg); } diff --combined usage.c index 9c84dccfa9,b3c78931ad..cc803336bd --- a/usage.c +++ b/usage.c @@@ -148,6 -148,7 +148,7 @@@ static const char *fmt_with_err(char *b } } str_error[j] = 0; + /* Truncation is acceptable here */ snprintf(buf, n, "%s: %s", fmt, str_error); return buf; } @@@ -210,9 -211,6 +211,9 @@@ void warning(const char *warn, ... va_end(params); } +/* Only set this, ever, from t/helper/, when verifying that bugs are caught. */ +int BUG_exit_code; + static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params) { char prefix[256]; @@@ -224,8 -222,6 +225,8 @@@ snprintf(prefix, sizeof(prefix), "BUG: "); vreportf(prefix, fmt, params); + if (BUG_exit_code) + exit(BUG_exit_code); abort(); }