Merge branch 'sb/read-tree'
[gitweb.git] / builtin-receive-pack.c
index 035b723e50a72427a26102b91f5900b131d44095..6ec1d056e6fa24bf6008d9114df5d5cdacd837af 100644 (file)
@@ -27,10 +27,9 @@ static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
+static int prefer_ofs_delta = 1;
 static const char *head_name;
-
-static char capabilities[] = " report-status delete-refs ";
-static int capabilities_sent;
+static char *capabilities_to_send;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
 {
@@ -84,24 +83,29 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
+               prefer_ofs_delta = git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 {
-       if (capabilities_sent)
+       if (!capabilities_to_send)
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
        else
                packet_write(1, "%s %s%c%s\n",
-                            sha1_to_hex(sha1), path, 0, capabilities);
-       capabilities_sent = 1;
+                            sha1_to_hex(sha1), path, 0, capabilities_to_send);
+       capabilities_to_send = NULL;
        return 0;
 }
 
 static void write_head_info(void)
 {
        for_each_ref(show_ref, NULL);
-       if (!capabilities_sent)
+       if (capabilities_to_send)
                show_ref("capabilities^{}", null_sha1, 0, NULL);
 
 }
@@ -119,27 +123,27 @@ static struct command *commands;
 static const char pre_receive_hook[] = "hooks/pre-receive";
 static const char post_receive_hook[] = "hooks/post-receive";
 
-static int hook_status(int code, const char *hook_name)
+static int run_status(int code, const char *cmd_name)
 {
        switch (code) {
        case 0:
                return 0;
        case -ERR_RUN_COMMAND_FORK:
-               return error("hook fork failed");
+               return error("fork of %s failed", cmd_name);
        case -ERR_RUN_COMMAND_EXEC:
-               return error("hook execute failed");
+               return error("execute of %s failed", cmd_name);
        case -ERR_RUN_COMMAND_PIPE:
-               return error("hook pipe failed");
+               return error("pipe failed");
        case -ERR_RUN_COMMAND_WAITPID:
                return error("waitpid failed");
        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
                return error("waitpid is confused");
        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-               return error("%s died of signal", hook_name);
+               return error("%s died of signal", cmd_name);
        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-               return error("%s died strangely", hook_name);
+               return error("%s died strangely", cmd_name);
        default:
-               error("%s exited with error code %d", hook_name, -code);
+               error("%s exited with error code %d", cmd_name, -code);
                return -code;
        }
 }
@@ -170,7 +174,7 @@ static int run_receive_hook(const char *hook_name)
 
        code = start_command(&proc);
        if (code)
-               return hook_status(code, hook_name);
+               return run_status(code, hook_name);
        for (cmd = commands; cmd; cmd = cmd->next) {
                if (!cmd->error_string) {
                        size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -182,13 +186,12 @@ static int run_receive_hook(const char *hook_name)
                }
        }
        close(proc.in);
-       return hook_status(finish_command(&proc), hook_name);
+       return run_status(finish_command(&proc), hook_name);
 }
 
 static int run_update_hook(struct command *cmd)
 {
        static const char update_hook[] = "hooks/update";
-       struct child_process proc;
        const char *argv[5];
 
        if (access(update_hook, X_OK) < 0)
@@ -200,12 +203,9 @@ static int run_update_hook(struct command *cmd)
        argv[3] = sha1_to_hex(cmd->new_sha1);
        argv[4] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
-       proc.argv = argv;
-       proc.no_stdin = 1;
-       proc.stdout_to_stderr = 1;
-
-       return hook_status(run_command(&proc), update_hook);
+       return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+                                       RUN_COMMAND_STDOUT_TO_STDERR),
+                       update_hook);
 }
 
 static int is_ref_checked_out(const char *ref)
@@ -394,7 +394,7 @@ static char update_post_hook[] = "hooks/post-update";
 static void run_update_post_hook(struct command *cmd)
 {
        struct command *cmd_p;
-       int argc;
+       int argc, status;
        const char **argv;
 
        for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
@@ -417,8 +417,9 @@ static void run_update_post_hook(struct command *cmd)
                argc++;
        }
        argv[argc] = NULL;
-       run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
-               | RUN_COMMAND_STDOUT_TO_STDERR);
+       status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
+                       | RUN_COMMAND_STDOUT_TO_STDERR);
+       run_status(status, update_post_hook);
 }
 
 static void execute_commands(const char *unpacker_error)
@@ -534,24 +535,10 @@ static const char *unpack(void)
                unpacker[i++] = hdr_arg;
                unpacker[i++] = NULL;
                code = run_command_v_opt(unpacker, RUN_GIT_CMD);
-               switch (code) {
-               case 0:
+               if (!code)
                        return NULL;
-               case -ERR_RUN_COMMAND_FORK:
-                       return "unpack fork failed";
-               case -ERR_RUN_COMMAND_EXEC:
-                       return "unpack execute failed";
-               case -ERR_RUN_COMMAND_WAITPID:
-                       return "waitpid failed";
-               case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
-                       return "waitpid is confused";
-               case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-                       return "unpacker died of signal";
-               case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-                       return "unpacker died strangely";
-               default:
-                       return "unpacker exited with error code";
-               }
+               run_status(code, unpacker[0]);
+               return "unpack-objects abnormal exit";
        } else {
                const char *keeper[7];
                int s, status, i = 0;
@@ -574,8 +561,11 @@ static const char *unpack(void)
                ip.argv = keeper;
                ip.out = -1;
                ip.git_cmd = 1;
-               if (start_command(&ip))
+               status = start_command(&ip);
+               if (status) {
+                       run_status(status, keeper[0]);
                        return "index-pack fork failed";
+               }
                pack_lockfile = index_pack_lockfile(ip.out);
                close(ip.out);
                status = finish_command(&ip);
@@ -583,6 +573,7 @@ static const char *unpack(void)
                        reprepare_packed_git();
                        return NULL;
                }
+               run_status(status, keeper[0]);
                return "index-pack abnormal exit";
        }
 }
@@ -687,6 +678,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
        else if (0 <= receive_unpack_limit)
                unpack_limit = receive_unpack_limit;
 
+       capabilities_to_send = (prefer_ofs_delta) ?
+               " report-status delete-refs ofs-delta " :
+               " report-status delete-refs ";
+
        add_alternate_refs();
        write_head_info();
        clear_extra_refs();