git-tar-tree: don't RUN_SETUP
[gitweb.git] / receive-pack.c
index e79de917b542eb35d6b5752837b25ccae897646e..ea2dbd4e3398ca90823dcd453cbb52c5dcea135c 100644 (file)
@@ -2,16 +2,17 @@
 #include "refs.h"
 #include "pkt-line.h"
 #include "run-command.h"
-#include <sys/wait.h>
+#include "commit.h"
+#include "object.h"
 
 static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
 
-static const char unpacker[] = "git-unpack-objects";
+static const char *unpacker[] = { "unpack-objects", NULL };
 
-static int report_status = 0;
+static int report_status;
 
 static char capabilities[] = "report-status";
-static int capabilities_sent = 0;
+static int capabilities_sent;
 
 static int show_ref(const char *path, const unsigned char *sha1)
 {
@@ -37,10 +38,10 @@ struct command {
        const char *error_string;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
-       char ref_name[0];
+       char ref_name[FLEX_ARRAY]; /* more */
 };
 
-static struct command *commands = NULL;
+static struct command *commands;
 
 static int is_all_zeroes(const char *hex)
 {
@@ -92,7 +93,7 @@ static int run_update_hook(const char *refname,
        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
                return error("waitpid is confused");
        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-               return error("%s died of signal\n", update_hook);
+               return error("%s died of signal", update_hook);
        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
                return error("%s died strangely", update_hook);
        default:
@@ -128,6 +129,21 @@ static int update(struct command *cmd)
                return error("unpack should have generated %s, "
                             "but I can't find it!", new_hex);
        }
+       if (deny_non_fast_forwards && !is_null_sha1(old_sha1)) {
+               struct commit *old_commit, *new_commit;
+               struct commit_list *bases, *ent;
+
+               old_commit = (struct commit *)parse_object(old_sha1);
+               new_commit = (struct commit *)parse_object(new_sha1);
+               bases = get_merge_bases(old_commit, new_commit, 1);
+               for (ent = bases; ent; ent = ent->next)
+                       if (!hashcmp(old_sha1, ent->item->object.sha1))
+                               break;
+               free_commit_list(bases);
+               if (!ent)
+                       return error("denying non-fast forward;"
+                                    " you should pull first");
+       }
        safe_create_leading_directories(lock_name);
 
        newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
@@ -158,7 +174,7 @@ static int update(struct command *cmd)
        if (run_update_hook(name, old_hex, new_hex)) {
                unlink(lock_name);
                cmd->error_string = "hook declined";
-               return error("hook declined to update %s\n", name);
+               return error("hook declined to update %s", name);
        }
        else if (rename(lock_name, name) < 0) {
                unlink(lock_name);
@@ -177,7 +193,7 @@ static void run_update_post_hook(struct command *cmd)
 {
        struct command *cmd_p;
        int argc;
-       char **argv;
+       const char **argv;
 
        if (access(update_post_hook, X_OK) < 0)
                return;
@@ -190,10 +206,12 @@ static void run_update_post_hook(struct command *cmd)
        argv[0] = update_post_hook;
 
        for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
+               char *p;
                if (cmd_p->error_string)
                        continue;
-               argv[argc] = xmalloc(strlen(cmd_p->ref_name) + 1);
-               strcpy(argv[argc], cmd_p->ref_name);
+               p = xmalloc(strlen(cmd_p->ref_name) + 1);
+               strcpy(p, cmd_p->ref_name);
+               argv[argc] = p;
                argc++;
        }
        argv[argc] = NULL;
@@ -245,8 +263,8 @@ static void read_head_info(void)
                                report_status = 1;
                }
                cmd = xmalloc(sizeof(struct command) + len - 80);
-               memcpy(cmd->old_sha1, old_sha1, 20);
-               memcpy(cmd->new_sha1, new_sha1, 20);
+               hashcpy(cmd->old_sha1, old_sha1);
+               hashcpy(cmd->new_sha1, new_sha1);
                memcpy(cmd->ref_name, line + 82, len - 81);
                cmd->error_string = "n/a (unpacker error)";
                cmd->next = NULL;
@@ -257,7 +275,7 @@ static void read_head_info(void)
 
 static const char *unpack(int *error_code)
 {
-       int code = run_command(unpacker, NULL);
+       int code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
 
        *error_code = 0;
        switch (code) {