receive-pack: use in_merge_bases() for fast-forward check
[gitweb.git] / builtin / receive-pack.c
index 8c9e91e78c95a4a3d581aae59d0f00bc95b2c942..58f3a37a39afbe3b7737fa3a0d9b90f57cec2b75 100644 (file)
@@ -33,6 +33,7 @@ static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
 static int use_sideband;
+static int quiet;
 static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
 static int auto_gc = 1;
@@ -122,7 +123,7 @@ static void show_ref(const char *path, const unsigned char *sha1)
        else
                packet_write(1, "%s %s%c%s%s\n",
                             sha1_to_hex(sha1), path, 0,
-                            " report-status delete-refs side-band-64k",
+                            " report-status delete-refs side-band-64k quiet",
                             prefer_ofs_delta ? " ofs-delta" : "");
        sent_capabilities = 1;
 }
@@ -477,7 +478,6 @@ static const char *update(struct command *cmd)
            !prefixcmp(name, "refs/heads/")) {
                struct object *old_object, *new_object;
                struct commit *old_commit, *new_commit;
-               struct commit_list *bases, *ent;
 
                old_object = parse_object(old_sha1);
                new_object = parse_object(new_sha1);
@@ -490,12 +490,7 @@ static const char *update(struct command *cmd)
                }
                old_commit = (struct commit *)old_object;
                new_commit = (struct commit *)new_object;
-               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) {
+               if (!in_merge_bases(old_commit, new_commit)) {
                        rp_error("denying non-fast-forward %s"
                                 " (you should pull first)", name);
                        return "non-fast-forward";
@@ -641,8 +636,10 @@ static void check_aliased_updates(struct command *commands)
        }
        sort_string_list(&ref_list);
 
-       for (cmd = commands; cmd; cmd = cmd->next)
-               check_aliased_update(cmd, &ref_list);
+       for (cmd = commands; cmd; cmd = cmd->next) {
+               if (!cmd->error_string)
+                       check_aliased_update(cmd, &ref_list);
+       }
 
        string_list_clear(&ref_list, 0);
 }
@@ -706,8 +703,10 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
                set_connectivity_errors(commands);
 
        if (run_receive_hook(commands, pre_receive_hook, 0)) {
-               for (cmd = commands; cmd; cmd = cmd->next)
-                       cmd->error_string = "pre-receive hook declined";
+               for (cmd = commands; cmd; cmd = cmd->next) {
+                       if (!cmd->error_string)
+                               cmd->error_string = "pre-receive hook declined";
+               }
                return;
        }
 
@@ -716,9 +715,15 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
        free(head_name_to_free);
        head_name = head_name_to_free = resolve_refdup("HEAD", sha1, 0, NULL);
 
-       for (cmd = commands; cmd; cmd = cmd->next)
-               if (!cmd->skip_update)
-                       cmd->error_string = update(cmd);
+       for (cmd = commands; cmd; cmd = cmd->next) {
+               if (cmd->error_string)
+                       continue;
+
+               if (cmd->skip_update)
+                       continue;
+
+               cmd->error_string = update(cmd);
+       }
 }
 
 static struct command *read_head_info(void)
@@ -748,10 +753,13 @@ static struct command *read_head_info(void)
                refname = line + 82;
                reflen = strlen(refname);
                if (reflen + 82 < len) {
-                       if (strstr(refname + reflen + 1, "report-status"))
+                       const char *feature_list = refname + reflen + 1;
+                       if (parse_feature_request(feature_list, "report-status"))
                                report_status = 1;
-                       if (strstr(refname + reflen + 1, "side-band-64k"))
+                       if (parse_feature_request(feature_list, "side-band-64k"))
                                use_sideband = LARGE_PACKET_MAX;
+                       if (parse_feature_request(feature_list, "quiet"))
+                               quiet = 1;
                }
                cmd = xcalloc(1, sizeof(struct command) + len - 80);
                hashcpy(cmd->old_sha1, old_sha1);
@@ -805,8 +813,10 @@ static const char *unpack(void)
 
        if (ntohl(hdr.hdr_entries) < unpack_limit) {
                int code, i = 0;
-               const char *unpacker[4];
+               const char *unpacker[5];
                unpacker[i++] = "unpack-objects";
+               if (quiet)
+                       unpacker[i++] = "-q";
                if (fsck_objects)
                        unpacker[i++] = "--strict";
                unpacker[i++] = hdr_arg;
@@ -901,6 +911,11 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                const char *arg = *argv++;
 
                if (*arg == '-') {
+                       if (!strcmp(arg, "--quiet")) {
+                               quiet = 1;
+                               continue;
+                       }
+
                        if (!strcmp(arg, "--advertise-refs")) {
                                advertise_refs = 1;
                                continue;