From: Junio C Hamano Date: Wed, 17 Aug 2016 21:07:46 +0000 (-0700) Subject: Merge branch 'jk/tighten-alloc' X-Git-Tag: v2.10.0-rc1~11 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/2f664566c56db3ddbf12033c2b8f8091b693dc79?hp=-c Merge branch 'jk/tighten-alloc' Small code and comment clean-up. * jk/tighten-alloc: receive-pack: use FLEX_ALLOC_MEM in queue_command() correct FLEXPTR_* example in comment --- 2f664566c56db3ddbf12033c2b8f8091b693dc79 diff --combined builtin/receive-pack.c index 92e1213ecc,b55d0aaee7..011db00d31 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@@ -21,10 -21,7 +21,10 @@@ #include "sigchain.h" #include "fsck.h" -static const char receive_pack_usage[] = "git receive-pack "; +static const char * const receive_pack_usage[] = { + N_("git receive-pack "), + NULL +}; enum deny_action { DENY_UNCONFIGURED, @@@ -44,17 -41,15 +44,17 @@@ static struct strbuf fsck_msg_types = S static int receive_unpack_limit = -1; static int transfer_unpack_limit = -1; static int advertise_atomic_push = 1; +static int advertise_push_options; static int unpack_limit = 100; static int report_status; static int use_sideband; static int use_atomic; +static int use_push_options; static int quiet; static int prefer_ofs_delta = 1; static int auto_update_server_info; static int auto_gc = 1; -static int fix_thin = 1; +static int reject_thin; static int stateless_rpc; static const char *service_dir; static const char *head_name; @@@ -78,13 -73,6 +78,13 @@@ static long nonce_stamp_slop static unsigned long nonce_stamp_slop_limit; static struct ref_transaction *transaction; +static enum { + KEEPALIVE_NEVER = 0, + KEEPALIVE_AFTER_NUL, + KEEPALIVE_ALWAYS +} use_keepalive; +static int keepalive_in_sec = 5; + static enum deny_action parse_deny_action(const char *var, const char *value) { if (value) { @@@ -202,16 -190,6 +202,16 @@@ static int receive_pack_config(const ch return 0; } + if (strcmp(var, "receive.advertisepushoptions") == 0) { + advertise_push_options = git_config_bool(var, value); + return 0; + } + + if (strcmp(var, "receive.keepalive") == 0) { + keepalive_in_sec = git_config_int(var, value); + return 0; + } + return git_default_config(var, value, cb); } @@@ -230,8 -208,6 +230,8 @@@ static void show_ref(const char *path, strbuf_addstr(&cap, " ofs-delta"); if (push_cert_nonce) strbuf_addf(&cap, " push-cert=%s", push_cert_nonce); + if (advertise_push_options) + strbuf_addstr(&cap, " push-options"); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), path, 0, cap.buf); @@@ -340,60 -316,10 +340,60 @@@ static void rp_error(const char *err, . static int copy_to_sideband(int in, int out, void *arg) { char data[128]; + int keepalive_active = 0; + + if (keepalive_in_sec <= 0) + use_keepalive = KEEPALIVE_NEVER; + if (use_keepalive == KEEPALIVE_ALWAYS) + keepalive_active = 1; + while (1) { - ssize_t sz = xread(in, data, sizeof(data)); + ssize_t sz; + + if (keepalive_active) { + struct pollfd pfd; + int ret; + + pfd.fd = in; + pfd.events = POLLIN; + ret = poll(&pfd, 1, 1000 * keepalive_in_sec); + + if (ret < 0) { + if (errno == EINTR) + continue; + else + break; + } else if (ret == 0) { + /* no data; send a keepalive packet */ + static const char buf[] = "0005\1"; + write_or_die(1, buf, sizeof(buf) - 1); + continue; + } /* else there is actual data to read */ + } + + sz = xread(in, data, sizeof(data)); if (sz <= 0) break; + + if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active) { + const char *p = memchr(data, '\0', sz); + if (p) { + /* + * The NUL tells us to start sending keepalives. Make + * sure we send any other data we read along + * with it. + */ + keepalive_active = 1; + send_sideband(1, 2, data, p - data, use_sideband); + send_sideband(1, 2, p + 1, sz - (p - data + 1), use_sideband); + continue; + } + } + + /* + * Either we're not looking for a NUL signal, or we didn't see + * it yet; just pass along the data. + */ send_sideband(1, 2, data, sz, use_sideband); } close(in); @@@ -621,16 -547,8 +621,16 @@@ static void prepare_push_cert_sha1(stru } } +struct receive_hook_feed_state { + struct command *cmd; + int skip_broken; + struct strbuf buf; + const struct string_list *push_options; +}; + typedef int (*feed_fn)(void *, const char **, size_t *); -static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state) +static int run_and_feed_hook(const char *hook_name, feed_fn feed, + struct receive_hook_feed_state *feed_state) { struct child_process proc = CHILD_PROCESS_INIT; struct async muxer; @@@ -646,16 -564,6 +646,16 @@@ proc.argv = argv; proc.in = -1; proc.stdout_to_stderr = 1; + if (feed_state->push_options) { + int i; + for (i = 0; i < feed_state->push_options->nr; i++) + argv_array_pushf(&proc.env_array, + "GIT_PUSH_OPTION_%d=%s", i, + feed_state->push_options->items[i].string); + argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d", + feed_state->push_options->nr); + } else + argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT"); if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); @@@ -695,6 -603,12 +695,6 @@@ return finish_command(&proc); } -struct receive_hook_feed_state { - struct command *cmd; - int skip_broken; - struct strbuf buf; -}; - static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep) { struct receive_hook_feed_state *state = state_; @@@ -717,10 -631,8 +717,10 @@@ return 0; } -static int run_receive_hook(struct command *commands, const char *hook_name, - int skip_broken) +static int run_receive_hook(struct command *commands, + const char *hook_name, + int skip_broken, + const struct string_list *push_options) { struct receive_hook_feed_state state; int status; @@@ -731,7 -643,6 +731,7 @@@ if (feed_receive_hook(&state, NULL, NULL)) return 0; state.cmd = commands; + state.push_options = push_options; status = run_and_feed_hook(hook_name, feed_receive_hook, &state); strbuf_release(&state.buf); return status; @@@ -823,7 -734,7 +823,7 @@@ static int update_shallow_ref(struct co { static struct lock_file shallow_lock; struct sha1_array extra = SHA1_ARRAY_INIT; - const char *alt_file; + struct check_connected_options opt = CHECK_CONNECTED_INIT; uint32_t mask = 1 << (cmd->index % 32); int i; @@@ -835,8 -746,9 +835,8 @@@ !delayed_reachability_test(si, i)) sha1_array_append(&extra, si->shallow->sha1[i]); - setup_alternate_shallow(&shallow_lock, &alt_file, &extra); - if (check_shallow_connected(command_singleton_iterator, - 0, cmd, alt_file)) { + 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); return -1; @@@ -1169,13 -1081,13 +1169,13 @@@ static void check_aliased_update(struc if (!(flag & REF_ISSYMREF)) return; - dst_name = strip_namespace(dst_name); if (!dst_name) { rp_error("refusing update to broken symref '%s'", cmd->ref_name); cmd->skip_update = 1; cmd->error_string = "broken symref"; return; } + dst_name = strip_namespace(dst_name); if ((item = string_list_lookup(list, dst_name)) == NULL) return; @@@ -1245,8 -1157,8 +1245,8 @@@ static void set_connectivity_errors(str if (shallow_update && si->shallow_ref[cmd->index]) /* to be checked in update_shallow_ref() */ continue; - if (!check_everything_connected(command_singleton_iterator, - 0, &singleton)) + if (!check_connected(command_singleton_iterator, &singleton, + NULL)) continue; cmd->error_string = "missing necessary objects"; } @@@ -1401,15 -1313,11 +1401,15 @@@ cleanup static void execute_commands(struct command *commands, const char *unpacker_error, - struct shallow_info *si) + struct shallow_info *si, + const struct string_list *push_options) { + struct check_connected_options opt = CHECK_CONNECTED_INIT; struct command *cmd; unsigned char sha1[20]; struct iterate_data data; + struct async muxer; + int err_fd = 0; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) @@@ -1417,28 -1325,14 +1417,28 @@@ return; } + if (use_sideband) { + memset(&muxer, 0, sizeof(muxer)); + muxer.proc = copy_to_sideband; + muxer.in = -1; + if (!start_async(&muxer)) + err_fd = muxer.in; + /* ...else, continue without relaying sideband */ + } + data.cmds = commands; data.si = si; - if (check_everything_connected(iterate_receive_command_list, 0, &data)) + opt.err_fd = err_fd; + opt.progress = err_fd && !quiet; + if (check_connected(iterate_receive_command_list, &data, &opt)) set_connectivity_errors(commands, si); + if (use_sideband) + finish_async(&muxer); + reject_updates_to_hidden(commands); - if (run_receive_hook(commands, "pre-receive", 0)) { + if (run_receive_hook(commands, "pre-receive", 0, push_options)) { for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) cmd->error_string = "pre-receive hook declined"; @@@ -1478,11 -1372,9 +1478,9 @@@ static struct command **queue_command(s refname = line + 82; reflen = linelen - 82; - cmd = xcalloc(1, st_add3(sizeof(struct command), reflen, 1)); + FLEX_ALLOC_MEM(cmd, ref_name, refname, reflen); hashcpy(cmd->old_sha1, old_sha1); hashcpy(cmd->new_sha1, new_sha1); - memcpy(cmd->ref_name, refname, reflen); - cmd->ref_name[reflen] = '\0'; *tail = cmd; return &cmd->next; } @@@ -1542,9 -1434,6 +1540,9 @@@ static struct command *read_head_info(s if (advertise_atomic_push && parse_feature_request(feature_list, "atomic")) use_atomic = 1; + if (advertise_push_options + && parse_feature_request(feature_list, "push-options")) + use_push_options = 1; } if (!strcmp(line, "push-cert")) { @@@ -1577,21 -1466,6 +1575,21 @@@ return commands; } +static void read_push_options(struct string_list *options) +{ + while (1) { + char *line; + int len; + + line = packet_read_line(0, &len); + + if (!line) + break; + + string_list_append(options, line); + } +} + static const char *parse_pack_header(struct pack_header *hdr) { switch (read_pack_header(0, hdr)) { @@@ -1669,14 -1543,10 +1667,14 @@@ static const char *unpack(int err_fd, s (uintmax_t)getpid(), hostname); + if (!quiet && err_fd) + argv_array_push(&child.args, "--show-resolving-progress"); + if (use_sideband) + argv_array_push(&child.args, "--report-end-of-input"); if (fsck_objects) argv_array_pushf(&child.args, "--strict%s", fsck_msg_types.buf); - if (fix_thin) + if (!reject_thin) argv_array_push(&child.args, "--fix-thin"); child.out = -1; child.err = err_fd; @@@ -1702,7 -1572,6 +1700,7 @@@ static const char *unpack_with_sideband if (!use_sideband) return unpack(0, si); + use_keepalive = KEEPALIVE_AFTER_NUL; memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; muxer.in = -1; @@@ -1836,29 -1705,45 +1834,29 @@@ static int delete_only(struct command * int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int advertise_refs = 0; - int i; struct command *commands; struct sha1_array shallow = SHA1_ARRAY_INIT; struct sha1_array ref = SHA1_ARRAY_INIT; struct shallow_info si; - packet_trace_identity("receive-pack"); + struct option options[] = { + OPT__QUIET(&quiet, N_("quiet")), + OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL), + OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL), + OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL), + OPT_END() + }; - argv++; - for (i = 1; i < argc; i++) { - const char *arg = *argv++; + packet_trace_identity("receive-pack"); - if (*arg == '-') { - if (!strcmp(arg, "--quiet")) { - quiet = 1; - continue; - } + argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0); - if (!strcmp(arg, "--advertise-refs")) { - advertise_refs = 1; - continue; - } - if (!strcmp(arg, "--stateless-rpc")) { - stateless_rpc = 1; - continue; - } - if (!strcmp(arg, "--reject-thin-pack-for-testing")) { - fix_thin = 0; - continue; - } + if (argc > 1) + usage_msg_opt(_("Too many arguments."), receive_pack_usage, options); + if (argc == 0) + usage_msg_opt(_("You must specify a directory."), receive_pack_usage, options); - usage(receive_pack_usage); - } - if (service_dir) - usage(receive_pack_usage); - service_dir = arg; - } - if (!service_dir) - usage(receive_pack_usage); + service_dir = argv[0]; setup_path(); @@@ -1882,10 -1767,6 +1880,10 @@@ if ((commands = read_head_info(&shallow)) != NULL) { const char *unpack_status = NULL; + struct string_list push_options = STRING_LIST_INIT_DUP; + + if (use_push_options) + read_push_options(&push_options); prepare_shallow_info(&si, &shallow); if (!si.nr_ours && !si.nr_theirs) @@@ -1894,36 -1775,20 +1892,36 @@@ unpack_status = unpack_with_sideband(&si); update_shallow_info(commands, &si, &ref); } - execute_commands(commands, unpack_status, &si); + use_keepalive = KEEPALIVE_ALWAYS; + execute_commands(commands, unpack_status, &si, + &push_options); if (pack_lockfile) unlink_or_warn(pack_lockfile); if (report_status) report(commands, unpack_status); - run_receive_hook(commands, "post-receive", 1); + run_receive_hook(commands, "post-receive", 1, + &push_options); run_update_post_hook(commands); + if (push_options.nr) + string_list_clear(&push_options, 0); if (auto_gc) { const char *argv_gc_auto[] = { "gc", "--auto", "--quiet", NULL, }; - int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + struct child_process proc = CHILD_PROCESS_INIT; + + proc.no_stdin = 1; + proc.stdout_to_stderr = 1; + proc.err = use_sideband ? -1 : 0; + proc.git_cmd = 1; + proc.argv = argv_gc_auto; + close_all_packs(); - run_command_v_opt(argv_gc_auto, opt); + if (!start_command(&proc)) { + if (use_sideband) + copy_to_sideband(proc.err, -1, NULL); + finish_command(&proc); + } } if (auto_update_server_info) update_server_info(0); diff --combined git-compat-util.h index 590bfddf73,17918d028a..f52e00b580 --- a/git-compat-util.h +++ b/git-compat-util.h @@@ -279,6 -279,9 +279,6 @@@ extern char *gitdirname(char *) #endif #include #include -#ifdef NO_HMAC_CTX_CLEANUP -#define HMAC_CTX_cleanup HMAC_cleanup -#endif #endif /* On most systems would have given us this, but @@@ -330,6 -333,10 +330,6 @@@ #define _PATH_DEFPATH "/usr/local/bin:/usr/bin:/bin" #endif -#ifndef STRIP_EXTENSION -#define STRIP_EXTENSION "" -#endif - #ifndef has_dos_drive_prefix static inline int git_has_dos_drive_prefix(const char *path) { @@@ -409,9 -416,7 +409,9 @@@ extern NORETURN void usagef(const char extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2))); extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); #ifndef NO_OPENSSL #ifdef APPLE_COMMON_CRYPTO @@@ -473,23 -478,6 +473,23 @@@ static inline int skip_prefix(const cha return 0; } +/* + * Like skip_prefix, but promises never to read past "len" bytes of the input + * buffer, and returns the remaining number of bytes in "out" via "outlen". + */ +static inline int skip_prefix_mem(const char *buf, size_t len, + const char *prefix, + const char **out, size_t *outlen) +{ + size_t prefix_len = strlen(prefix); + if (prefix_len <= len && !memcmp(buf, prefix, prefix_len)) { + *out = buf + prefix_len; + *outlen = len - prefix_len; + return 1; + } + return 0; +} + /* * If buf ends with suffix, return 1 and subtract the length of the suffix * from *len. Otherwise, return 0 and leave *len untouched. @@@ -731,8 -719,8 +731,8 @@@ static inline size_t st_add(size_t a, s (uintmax_t)a, (uintmax_t)b); return a + b; } -#define st_add3(a,b,c) st_add((a),st_add((b),(c))) -#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d))) +#define st_add3(a,b,c) st_add(st_add((a),(b)),(c)) +#define st_add4(a,b,c,d) st_add(st_add3((a),(b),(c)),(d)) static inline size_t st_mult(size_t a, size_t b) { @@@ -815,7 -803,7 +815,7 @@@ extern FILE *fopen_for_writing(const ch * you can do: * * struct foo *f; - * FLEX_ALLOC_STR(f, name, src); + * FLEXPTR_ALLOC_STR(f, name, src); * * and "name" will point to a block of memory after the struct, which will be * freed along with the struct (but the pointer can be repointed anywhere). @@@ -1062,5 -1050,3 +1062,5 @@@ struct tm *git_gmtime_r(const time_t * #endif #endif + +extern int cmd_main(int, const char **);