send-pack: handle partial pushes correctly.
[gitweb.git] / send-pack.c
index 9b4be6130cad815384a3116be82af1264b9e286f..3b66185401adf2d7b5a1b40cb1b7ada0ee73396e 100644 (file)
@@ -4,7 +4,8 @@
 #include "pkt-line.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--exec=git-receive-pack] [host:]directory [heads]*";
+"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
+"  --all and explicit <head> specification are mutually exclusive.";
 static const char *exec = "git-receive-pack";
 static int send_all = 0;
 static int force_update = 0;
@@ -42,7 +43,8 @@ static void exec_rev_list(struct ref *refs)
                char *buf = malloc(100);
                if (i > 900)
                        die("git-rev-list environment overflow");
-               if (!is_zero_sha1(refs->old_sha1)) {
+               if (!is_zero_sha1(refs->old_sha1) &&
+                   has_sha1_file(refs->old_sha1)) {
                        args[i++] = buf;
                        snprintf(buf, 50, "^%s", sha1_to_hex(refs->old_sha1));
                        buf += 50;
@@ -202,6 +204,12 @@ static int send_pack(int in, int out, int nr_match, char **match)
                        continue;
                }
 
+               if (!has_sha1_file(ref->old_sha1)) {
+                       error("remote '%s' object %s does not exist on local",
+                             name, sha1_to_hex(ref->old_sha1));
+                       continue;
+               }
+
                if (!ref_newer(new_sha1, ref->old_sha1)) {
                        error("remote '%s' isn't a strict parent of local", name);
                        continue;
@@ -214,7 +222,7 @@ static int send_pack(int in, int out, int nr_match, char **match)
        /*
         * See if we have any refs that the other end didn't have
         */
-       if (nr_match) {
+       if (nr_match || send_all) {
                local_ref_nr_match = nr_match;
                local_ref_match = match;
                local_ref_list = ref_list;
@@ -281,6 +289,8 @@ int main(int argc, char **argv)
        }
        if (!dest)
                usage(send_pack_usage);
+       if (heads && send_all)
+               usage(send_pack_usage);
        pid = git_connect(fd, dest, exec);
        if (pid < 0)
                return 1;