coccicheck: use --all-includes by default
[gitweb.git] / builtin / receive-pack.c
index 3c9360aa6dfee96d3101a58b3c8bd899e51b4db3..896b16f2cceba73a44529f3b3d4f6ecdc33e892c 100644 (file)
@@ -46,6 +46,7 @@ static int transfer_unpack_limit = -1;
 static int advertise_atomic_push = 1;
 static int advertise_push_options;
 static int unpack_limit = 100;
+static off_t max_input_size;
 static int report_status;
 static int use_sideband;
 static int use_atomic;
@@ -78,6 +79,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) {
@@ -200,6 +208,16 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "receive.keepalive") == 0) {
+               keepalive_in_sec = git_config_int(var, value);
+               return 0;
+       }
+
+       if (strcmp(var, "receive.maxinputsize") == 0) {
+               max_input_size = git_config_int64(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
@@ -328,10 +346,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);
@@ -713,47 +781,39 @@ static int is_ref_checked_out(const char *ref)
        return !strcmp(head_name, ref);
 }
 
-static char *refuse_unconfigured_deny_msg[] = {
-       "By default, updating the current branch in a non-bare repository",
-       "is denied, because it will make the index and work tree inconsistent",
-       "with what you pushed, and will require 'git reset --hard' to match",
-       "the work tree to HEAD.",
-       "",
-       "You can set 'receive.denyCurrentBranch' configuration variable to",
-       "'ignore' or 'warn' in the remote repository to allow pushing into",
-       "its current branch; however, this is not recommended unless you",
-       "arranged to update its work tree to match what you pushed in some",
-       "other way.",
-       "",
-       "To squelch this message and still keep the default behaviour, set",
-       "'receive.denyCurrentBranch' configuration variable to 'refuse'."
-};
+static char *refuse_unconfigured_deny_msg =
+       N_("By default, updating the current branch in a non-bare repository\n"
+          "is denied, because it will make the index and work tree inconsistent\n"
+          "with what you pushed, and will require 'git reset --hard' to match\n"
+          "the work tree to HEAD.\n"
+          "\n"
+          "You can set 'receive.denyCurrentBranch' configuration variable to\n"
+          "'ignore' or 'warn' in the remote repository to allow pushing into\n"
+          "its current branch; however, this is not recommended unless you\n"
+          "arranged to update its work tree to match what you pushed in some\n"
+          "other way.\n"
+          "\n"
+          "To squelch this message and still keep the default behaviour, set\n"
+          "'receive.denyCurrentBranch' configuration variable to 'refuse'.");
 
 static void refuse_unconfigured_deny(void)
 {
-       int i;
-       for (i = 0; i < ARRAY_SIZE(refuse_unconfigured_deny_msg); i++)
-               rp_error("%s", refuse_unconfigured_deny_msg[i]);
+       rp_error("%s", _(refuse_unconfigured_deny_msg));
 }
 
-static char *refuse_unconfigured_deny_delete_current_msg[] = {
-       "By default, deleting the current branch is denied, because the next",
-       "'git clone' won't result in any file checked out, causing confusion.",
-       "",
-       "You can set 'receive.denyDeleteCurrent' configuration variable to",
-       "'warn' or 'ignore' in the remote repository to allow deleting the",
-       "current branch, with or without a warning message.",
-       "",
-       "To squelch this message, you can set it to 'refuse'."
-};
+static char *refuse_unconfigured_deny_delete_current_msg =
+       N_("By default, deleting the current branch is denied, because the next\n"
+          "'git clone' won't result in any file checked out, causing confusion.\n"
+          "\n"
+          "You can set 'receive.denyDeleteCurrent' configuration variable to\n"
+          "'warn' or 'ignore' in the remote repository to allow deleting the\n"
+          "current branch, with or without a warning message.\n"
+          "\n"
+          "To squelch this message, you can set it to 'refuse'.");
 
 static void refuse_unconfigured_deny_delete_current(void)
 {
-       int i;
-       for (i = 0;
-            i < ARRAY_SIZE(refuse_unconfigured_deny_delete_current_msg);
-            i++)
-               rp_error("%s", refuse_unconfigured_deny_delete_current_msg[i]);
+       rp_error("%s", _(refuse_unconfigured_deny_delete_current_msg));
 }
 
 static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]);
@@ -761,7 +821,7 @@ 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;
-       const char *alt_file;
+       struct check_connected_options opt = CHECK_CONNECTED_INIT;
        uint32_t mask = 1 << (cmd->index % 32);
        int i;
 
@@ -773,9 +833,8 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
                    !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;
@@ -1184,8 +1243,8 @@ static void set_connectivity_errors(struct command *commands,
                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";
        }
@@ -1343,9 +1402,12 @@ static void execute_commands(struct command *commands,
                             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)
@@ -1353,11 +1415,25 @@ static void execute_commands(struct command *commands,
                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, push_options)) {
@@ -1400,11 +1476,9 @@ static struct command **queue_command(struct command **tail,
 
        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;
 }
@@ -1572,6 +1646,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
                if (fsck_objects)
                        argv_array_pushf(&child.args, "--strict%s",
                                fsck_msg_types.buf);
+               if (max_input_size)
+                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                               (uintmax_t)max_input_size);
                child.no_stdout = 1;
                child.err = err_fd;
                child.git_cmd = 1;
@@ -1591,11 +1668,18 @@ static const char *unpack(int err_fd, struct shallow_info *si)
                                 (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 (!reject_thin)
                        argv_array_push(&child.args, "--fix-thin");
+               if (max_input_size)
+                       argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+                               (uintmax_t)max_input_size);
                child.out = -1;
                child.err = err_fd;
                child.git_cmd = 1;
@@ -1620,6 +1704,7 @@ static const char *unpack_with_sideband(struct shallow_info *si)
        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;
@@ -1811,6 +1896,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                        unpack_status = unpack_with_sideband(&si);
                        update_shallow_info(commands, &si, &ref);
                }
+               use_keepalive = KEEPALIVE_ALWAYS;
                execute_commands(commands, unpack_status, &si,
                                 &push_options);
                if (pack_lockfile)