diff options
Diffstat (limited to 'upload-pack.c')
| -rw-r--r-- | upload-pack.c | 203 |
1 files changed, 94 insertions, 109 deletions
diff --git a/upload-pack.c b/upload-pack.c index 2537affa90..0052c6a4dc 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "environment.h" @@ -28,6 +30,7 @@ #include "shallow.h" #include "write-or-die.h" #include "json-writer.h" +#include "strmap.h" /* Remember to update object flag allocation in object.h */ #define THEY_HAVE (1u << 11) @@ -61,12 +64,11 @@ struct upload_pack_data { struct string_list symref; /* v0 only */ struct object_array want_obj; struct object_array have_obj; - struct oid_array haves; /* v2 only */ - struct string_list wanted_refs; /* v2 only */ + struct strmap wanted_refs; /* v2 only */ struct strvec hidden_refs; struct object_array shallows; - struct string_list deepen_not; + struct oidset deepen_not; struct object_array extra_edge_obj; int depth; timestamp_t deepen_since; @@ -94,7 +96,7 @@ struct upload_pack_data { struct packet_writer writer; - const char *pack_objects_hook; + char *pack_objects_hook; unsigned stateless_rpc : 1; /* v0 only */ unsigned no_done : 1; /* v0 only */ @@ -113,6 +115,8 @@ struct upload_pack_data { unsigned done : 1; /* v2 only */ unsigned allow_ref_in_want : 1; /* v2 only */ unsigned allow_sideband_all : 1; /* v2 only */ + unsigned seen_haves : 1; /* v2 only */ + unsigned allow_packfile_uris : 1; /* v2 only */ unsigned advertise_sid : 1; unsigned sent_capabilities : 1; }; @@ -120,13 +124,12 @@ struct upload_pack_data { static void upload_pack_data_init(struct upload_pack_data *data) { struct string_list symref = STRING_LIST_INIT_DUP; - struct string_list wanted_refs = STRING_LIST_INIT_DUP; + struct strmap wanted_refs = STRMAP_INIT; struct strvec hidden_refs = STRVEC_INIT; struct object_array want_obj = OBJECT_ARRAY_INIT; struct object_array have_obj = OBJECT_ARRAY_INIT; - struct oid_array haves = OID_ARRAY_INIT; struct object_array shallows = OBJECT_ARRAY_INIT; - struct string_list deepen_not = STRING_LIST_INIT_DUP; + struct oidset deepen_not = OID_ARRAY_INIT; struct string_list uri_protocols = STRING_LIST_INIT_DUP; struct object_array extra_edge_obj = OBJECT_ARRAY_INIT; struct string_list allowed_filters = STRING_LIST_INIT_DUP; @@ -137,7 +140,6 @@ static void upload_pack_data_init(struct upload_pack_data *data) data->hidden_refs = hidden_refs; data->want_obj = want_obj; data->have_obj = have_obj; - data->haves = haves; data->shallows = shallows; data->deepen_not = deepen_not; data->uri_protocols = uri_protocols; @@ -155,13 +157,12 @@ static void upload_pack_data_init(struct upload_pack_data *data) static void upload_pack_data_clear(struct upload_pack_data *data) { string_list_clear(&data->symref, 1); - string_list_clear(&data->wanted_refs, 1); + strmap_clear(&data->wanted_refs, 1); strvec_clear(&data->hidden_refs); object_array_clear(&data->want_obj); object_array_clear(&data->have_obj); - oid_array_clear(&data->haves); object_array_clear(&data->shallows); - string_list_clear(&data->deepen_not, 0); + oidset_clear(&data->deepen_not); object_array_clear(&data->extra_edge_obj); list_objects_filter_release(&data->filter_options); string_list_clear(&data->allowed_filters, 0); @@ -463,7 +464,7 @@ static void create_pack_file(struct upload_pack_data *pack_data, fail: free(output_state); - send_client_data(3, abort_msg, sizeof(abort_msg), + send_client_data(3, abort_msg, strlen(abort_msg), pack_data->use_sideband); die("git upload-pack: %s", abort_msg); } @@ -471,7 +472,9 @@ static void create_pack_file(struct upload_pack_data *pack_data, static int do_got_oid(struct upload_pack_data *data, const struct object_id *oid) { int we_knew_they_have = 0; - struct object *o = parse_object(the_repository, oid); + struct object *o = parse_object_with_flags(the_repository, oid, + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) die("oops (%s)", oid_to_hex(oid)); @@ -528,8 +531,6 @@ static int get_common_commits(struct upload_pack_data *data, int got_other = 0; int sent_ready = 0; - save_commit_buffer = 0; - for (;;) { const char *arg; @@ -619,7 +620,8 @@ static void for_each_namespaced_ref_1(each_ref_fn fn, if (allow_hidden_refs(data->allow_uor)) excludes = hidden_refs_to_excludes(&data->hidden_refs); - for_each_namespaced_ref(excludes, fn, data); + refs_for_each_namespaced_ref(get_main_ref_store(the_repository), + excludes, fn, data); } @@ -874,7 +876,8 @@ static void deepen(struct upload_pack_data *data, int depth) * Checking for reachable shallows requires that our refs be * marked with OUR_REF. */ - head_ref_namespaced(check_ref, data); + refs_head_ref_namespaced(get_main_ref_store(the_repository), + check_ref, data); for_each_namespaced_ref_1(check_ref, data); get_reachable_list(data, &reachable_shallows); @@ -926,12 +929,13 @@ static int send_shallow_list(struct upload_pack_data *data) strvec_push(&av, "rev-list"); if (data->deepen_since) strvec_pushf(&av, "--max-age=%"PRItime, data->deepen_since); - if (data->deepen_not.nr) { + if (oidset_size(&data->deepen_not)) { + const struct object_id *oid; + struct oidset_iter iter; strvec_push(&av, "--not"); - for (i = 0; i < data->deepen_not.nr; i++) { - struct string_list_item *s = data->deepen_not.items + i; - strvec_push(&av, s->string); - } + oidset_iter_init(&data->deepen_not, &iter); + while ((oid = oidset_iter_next(&iter))) + strvec_push(&av, oid_to_hex(oid)); strvec_push(&av, "--not"); } for (i = 0; i < data->want_obj.nr; i++) { @@ -1007,7 +1011,7 @@ static int process_deepen_since(const char *line, timestamp_t *deepen_since, int return 0; } -static int process_deepen_not(const char *line, struct string_list *deepen_not, int *deepen_rev_list) +static int process_deepen_not(const char *line, struct oidset *deepen_not, int *deepen_rev_list) { const char *arg; if (skip_prefix(line, "deepen-not ", &arg)) { @@ -1015,7 +1019,7 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not, struct object_id oid; if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1) die("git upload-pack: ambiguous deepen-not: %s", line); - string_list_append(deepen_not, ref); + oidset_insert(deepen_not, &oid); free(ref); *deepen_rev_list = 1; return 1; @@ -1151,7 +1155,9 @@ static void receive_needs(struct upload_pack_data *data, free(client_sid); } - o = parse_object(the_repository, &oid_buf); + o = parse_object_with_flags(the_repository, &oid_buf, + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) { packet_writer_error(&data->writer, "upload-pack: not our ref %s", @@ -1265,7 +1271,7 @@ static void write_v0_ref(struct upload_pack_data *data, packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons); } capabilities = NULL; - if (!peel_iterated_oid(oid, &peeled)) + if (!peel_iterated_oid(the_repository, oid, &peeled)) packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons); return; } @@ -1286,7 +1292,8 @@ static int find_symref(const char *refname, if ((flag & REF_ISSYMREF) == 0) return 0; - symref_target = resolve_ref_unsafe(refname, 0, NULL, &flag); + symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), + refname, 0, NULL, &flag); if (!symref_target || (flag & REF_ISSYMREF) == 0) die("'%s' is a symref but it is not?", refname); item = string_list_append(cb_data, strip_namespace(refname)); @@ -1362,6 +1369,9 @@ static int upload_pack_config(const char *var, const char *value, data->allow_ref_in_want = git_config_bool(var, value); } else if (!strcmp("uploadpack.allowsidebandall", var)) { data->allow_sideband_all = git_config_bool(var, value); + } else if (!strcmp("uploadpack.blobpackfileuri", var)) { + if (value) + data->allow_packfile_uris = 1; } else if (!strcmp("core.precomposeunicode", var)) { precomposed_unicode = git_config_bool(var, value); } else if (!strcmp("transfer.advertisesid", var)) { @@ -1385,10 +1395,13 @@ static int upload_pack_protected_config(const char *var, const char *value, return 0; } -static void get_upload_pack_config(struct upload_pack_data *data) +static void get_upload_pack_config(struct repository *r, + struct upload_pack_data *data) { - git_config(upload_pack_config, data); + repo_config(r, upload_pack_config, data); git_protected_config(upload_pack_protected_config, data); + + data->allow_sideband_all |= git_env_bool("GIT_TEST_SIDEBAND_ALL", 0); } void upload_pack(const int advertise_refs, const int stateless_rpc, @@ -1398,20 +1411,22 @@ void upload_pack(const int advertise_refs, const int stateless_rpc, struct upload_pack_data data; upload_pack_data_init(&data); - get_upload_pack_config(&data); + get_upload_pack_config(the_repository, &data); data.stateless_rpc = stateless_rpc; data.timeout = timeout; if (data.timeout) data.daemon_mode = 1; - head_ref_namespaced(find_symref, &data.symref); + refs_head_ref_namespaced(get_main_ref_store(the_repository), + find_symref, &data.symref); if (advertise_refs || !data.stateless_rpc) { reset_timeout(data.timeout); if (advertise_refs) data.no_done = 1; - head_ref_namespaced(send_ref, &data); + refs_head_ref_namespaced(get_main_ref_store(the_repository), + send_ref, &data); for_each_namespaced_ref_1(send_ref, &data); if (!data.sent_capabilities) { const char *refname = "capabilities^{}"; @@ -1425,7 +1440,8 @@ void upload_pack(const int advertise_refs, const int stateless_rpc, advertise_shallow_grafts(1); packet_flush(1); } else { - head_ref_namespaced(check_ref, &data); + refs_head_ref_namespaced(get_main_ref_store(the_repository), + check_ref, &data); for_each_namespaced_ref_1(check_ref, &data); } @@ -1468,7 +1484,8 @@ static int parse_want(struct packet_writer *writer, const char *line, "expected to get oid, not '%s'", line); o = parse_object_with_flags(the_repository, &oid, - PARSE_OBJECT_SKIP_HASH_CHECK); + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) { packet_writer_error(writer, @@ -1490,27 +1507,29 @@ static int parse_want(struct packet_writer *writer, const char *line, } static int parse_want_ref(struct packet_writer *writer, const char *line, - struct string_list *wanted_refs, + struct strmap *wanted_refs, struct strvec *hidden_refs, struct object_array *want_obj) { const char *refname_nons; if (skip_prefix(line, "want-ref ", &refname_nons)) { struct object_id oid; - struct string_list_item *item; struct object *o = NULL; struct strbuf refname = STRBUF_INIT; strbuf_addf(&refname, "%s%s", get_git_namespace(), refname_nons); if (ref_is_hidden(refname_nons, refname.buf, hidden_refs) || - read_ref(refname.buf, &oid)) { + refs_read_ref(get_main_ref_store(the_repository), refname.buf, &oid)) { packet_writer_error(writer, "unknown ref %s", refname_nons); die("unknown ref %s", refname_nons); } strbuf_release(&refname); - item = string_list_append(wanted_refs, refname_nons); - item->util = oiddup(&oid); + if (strmap_put(wanted_refs, refname_nons, oiddup(&oid))) { + packet_writer_error(writer, "duplicate want-ref %s", + refname_nons); + die("duplicate want-ref %s", refname_nons); + } if (!starts_with(refname_nons, "refs/tags/")) { struct commit *commit = lookup_commit_in_graph(the_repository, &oid); @@ -1532,15 +1551,14 @@ static int parse_want_ref(struct packet_writer *writer, const char *line, return 0; } -static int parse_have(const char *line, struct oid_array *haves) +static int parse_have(const char *line, struct upload_pack_data *data) { const char *arg; if (skip_prefix(line, "have ", &arg)) { struct object_id oid; - if (get_oid_hex(arg, &oid)) - die("git upload-pack: expected SHA1 object, got '%s'", arg); - oid_array_append(haves, &oid); + got_oid(data, arg, &oid); + data->seen_haves = 1; return 1; } @@ -1552,13 +1570,13 @@ static void trace2_fetch_info(struct upload_pack_data *data) struct json_writer jw = JSON_WRITER_INIT; jw_object_begin(&jw, 0); - jw_object_intmax(&jw, "haves", data->haves.nr); + jw_object_intmax(&jw, "haves", data->have_obj.nr); jw_object_intmax(&jw, "wants", data->want_obj.nr); - jw_object_intmax(&jw, "want-refs", data->wanted_refs.nr); + jw_object_intmax(&jw, "want-refs", strmap_get_size(&data->wanted_refs)); jw_object_intmax(&jw, "depth", data->depth); jw_object_intmax(&jw, "shallows", data->shallows.nr); jw_object_bool(&jw, "deepen-since", data->deepen_since); - jw_object_intmax(&jw, "deepen-not", data->deepen_not.nr); + jw_object_intmax(&jw, "deepen-not", oidset_size(&data->deepen_not)); jw_object_bool(&jw, "deepen-relative", data->deepen_relative); if (data->filter_options.choice) jw_object_string(&jw, "filter", list_object_filter_config_name(data->filter_options.choice)); @@ -1586,7 +1604,7 @@ static void process_args(struct packet_reader *request, &data->hidden_refs, &data->want_obj)) continue; /* process have line */ - if (parse_have(arg, &data->haves)) + if (parse_have(arg, data)) continue; /* process args like thin-pack */ @@ -1638,14 +1656,17 @@ static void process_args(struct packet_reader *request, continue; } - if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) || - data->allow_sideband_all) && + if (data->allow_sideband_all && !strcmp(arg, "sideband-all")) { data->writer.use_sideband = 1; continue; } - if (skip_prefix(arg, "packfile-uris ", &p)) { + if (data->allow_packfile_uris && + skip_prefix(arg, "packfile-uris ", &p)) { + if (data->uri_protocols.nr) + send_err_and_die(data, + "multiple packfile-uris lines forbidden"); string_list_split(&data->uri_protocols, p, ',', -1); continue; } @@ -1664,27 +1685,7 @@ static void process_args(struct packet_reader *request, trace2_fetch_info(data); } -static int process_haves(struct upload_pack_data *data, struct oid_array *common) -{ - int i; - - /* Process haves */ - for (i = 0; i < data->haves.nr; i++) { - const struct object_id *oid = &data->haves.oid[i]; - - if (!repo_has_object_file_with_flags(the_repository, oid, - OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT)) - continue; - - oid_array_append(common, oid); - - do_got_oid(data, oid); - } - - return 0; -} - -static int send_acks(struct upload_pack_data *data, struct oid_array *acks) +static int send_acks(struct upload_pack_data *data, struct object_array *acks) { int i; @@ -1696,7 +1697,7 @@ static int send_acks(struct upload_pack_data *data, struct oid_array *acks) for (i = 0; i < acks->nr; i++) { packet_writer_write(&data->writer, "ACK %s\n", - oid_to_hex(&acks->oid[i])); + oid_to_hex(&acks->objects[i].item->oid)); } if (!data->wait_for_done && ok_to_give_up(data)) { @@ -1710,13 +1711,11 @@ static int send_acks(struct upload_pack_data *data, struct oid_array *acks) static int process_haves_and_send_acks(struct upload_pack_data *data) { - struct oid_array common = OID_ARRAY_INIT; int ret = 0; - process_haves(data, &common); if (data->done) { ret = 1; - } else if (send_acks(data, &common)) { + } else if (send_acks(data, &data->have_obj)) { packet_writer_delim(&data->writer); ret = 1; } else { @@ -1725,24 +1724,23 @@ static int process_haves_and_send_acks(struct upload_pack_data *data) ret = 0; } - oid_array_clear(&data->haves); - oid_array_clear(&common); return ret; } static void send_wanted_ref_info(struct upload_pack_data *data) { - const struct string_list_item *item; + struct hashmap_iter iter; + const struct strmap_entry *e; - if (!data->wanted_refs.nr) + if (strmap_empty(&data->wanted_refs)) return; packet_writer_write(&data->writer, "wanted-refs\n"); - for_each_string_list_item(item, &data->wanted_refs) { + strmap_for_each_entry(&data->wanted_refs, &iter, e) { packet_writer_write(&data->writer, "%s %s\n", - oid_to_hex(item->util), - item->string); + oid_to_hex(e->value), + e->key); } packet_writer_delim(&data->writer); @@ -1771,7 +1769,7 @@ enum fetch_state { FETCH_DONE, }; -int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) +int upload_pack_v2(struct repository *r, struct packet_reader *request) { enum fetch_state state = FETCH_PROCESS_ARGS; struct upload_pack_data data; @@ -1780,7 +1778,7 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) upload_pack_data_init(&data); data.use_sideband = LARGE_PACKET_MAX; - get_upload_pack_config(&data); + get_upload_pack_config(r, &data); while (state != FETCH_DONE) { switch (state) { @@ -1796,7 +1794,7 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) * they didn't want anything. */ state = FETCH_DONE; - } else if (data.haves.nr) { + } else if (data.seen_haves) { /* * Request had 'have' lines, so lets ACK them. */ @@ -1839,41 +1837,28 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) int upload_pack_advertise(struct repository *r, struct strbuf *value) { - if (value) { - int allow_filter_value; - int allow_ref_in_want; - int allow_sideband_all_value; - char *str = NULL; + struct upload_pack_data data; + upload_pack_data_init(&data); + get_upload_pack_config(r, &data); + + if (value) { strbuf_addstr(value, "shallow wait-for-done"); - if (!repo_config_get_bool(r, - "uploadpack.allowfilter", - &allow_filter_value) && - allow_filter_value) + if (data.allow_filter) strbuf_addstr(value, " filter"); - if (!repo_config_get_bool(r, - "uploadpack.allowrefinwant", - &allow_ref_in_want) && - allow_ref_in_want) + if (data.allow_ref_in_want) strbuf_addstr(value, " ref-in-want"); - if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) || - (!repo_config_get_bool(r, - "uploadpack.allowsidebandall", - &allow_sideband_all_value) && - allow_sideband_all_value)) + if (data.allow_sideband_all) strbuf_addstr(value, " sideband-all"); - if (!repo_config_get_string(r, - "uploadpack.blobpackfileuri", - &str) && - str) { + if (data.allow_packfile_uris) strbuf_addstr(value, " packfile-uris"); - free(str); - } } + upload_pack_data_clear(&data); + return 1; } |
