smart-http: support shallow fetch/clone
[gitweb.git] / send-pack.c
index 97ab336097bfb45c63aec739a6eef2df26cc4790..cd536b4ed5436b9bd63e0649618508f5fdf7ec4e 100644 (file)
@@ -5,10 +5,12 @@
 #include "sideband.h"
 #include "run-command.h"
 #include "remote.h"
+#include "connect.h"
 #include "send-pack.h"
 #include "quote.h"
 #include "transport.h"
 #include "version.h"
+#include "sha1-array.h"
 
 static int feed_object(const unsigned char *sha1, int fd, int negative)
 {
@@ -27,7 +29,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative)
 /*
  * Make a pack stream and spit it out into file descriptor fd
  */
-static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
+static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, struct send_pack_args *args)
 {
        /*
         * The child becomes pack-objects --revs; we feed
@@ -70,7 +72,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
         * parameters by writing to the pipe.
         */
        for (i = 0; i < extra->nr; i++)
-               if (!feed_object(extra->array[i], po.in, 1))
+               if (!feed_object(extra->sha1[i], po.in, 1))
                        break;
 
        while (refs) {
@@ -106,15 +108,11 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
 static int receive_status(int in, struct ref *refs)
 {
        struct ref *hint;
-       char line[1000];
        int ret = 0;
-       int len = packet_read_line(in, line, sizeof(line));
-       if (len < 10 || memcmp(line, "unpack ", 7))
+       char *line = packet_read_line(in, NULL);
+       if (prefixcmp(line, "unpack "))
                return error("did not receive remote status");
-       if (memcmp(line, "unpack ok\n", 10)) {
-               char *p = line + strlen(line) - 1;
-               if (*p == '\n')
-                       *p = '\0';
+       if (strcmp(line, "unpack ok")) {
                error("unpack failed: %s", line + 7);
                ret = -1;
        }
@@ -122,17 +120,15 @@ static int receive_status(int in, struct ref *refs)
        while (1) {
                char *refname;
                char *msg;
-               len = packet_read_line(in, line, sizeof(line));
-               if (!len)
+               line = packet_read_line(in, NULL);
+               if (!line)
                        break;
-               if (len < 3 ||
-                   (memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3))) {
-                       fprintf(stderr, "protocol error: %s\n", line);
+               if (prefixcmp(line, "ok ") && prefixcmp(line, "ng ")) {
+                       error("invalid ref status from remote: %s", line);
                        ret = -1;
                        break;
                }
 
-               line[strlen(line)-1] = '\0';
                refname = line + 3;
                msg = strchr(refname, ' ');
                if (msg)
@@ -182,7 +178,7 @@ static int sideband_demux(int in, int out, void *data)
 int send_pack(struct send_pack_args *args,
              int fd[], struct child_process *conn,
              struct ref *remote_refs,
-             struct extra_have_objects *extra_have)
+             struct sha1_array *extra_have)
 {
        int in = fd[0];
        int out = fd[1];
@@ -218,6 +214,9 @@ int send_pack(struct send_pack_args *args,
                return 0;
        }
 
+       if (!args->dry_run)
+               advertise_shallow_grafts(out);
+
        /*
         * Finally, tell the other end!
         */
@@ -232,6 +231,7 @@ int send_pack(struct send_pack_args *args,
                case REF_STATUS_REJECT_ALREADY_EXISTS:
                case REF_STATUS_REJECT_FETCH_FIRST:
                case REF_STATUS_REJECT_NEEDS_FORCE:
+               case REF_STATUS_REJECT_STALE:
                case REF_STATUS_UPTODATE:
                        continue;
                default:
@@ -281,7 +281,7 @@ int send_pack(struct send_pack_args *args,
                        send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
                }
        } else {
-               safe_write(out, req_buf.buf, req_buf.len);
+               write_or_die(out, req_buf.buf, req_buf.len);
                packet_flush(out);
        }
        strbuf_release(&req_buf);
@@ -306,8 +306,12 @@ int send_pack(struct send_pack_args *args,
                                shutdown(fd[0], SHUT_WR);
                        if (use_sideband)
                                finish_async(&demux);
+                       fd[1] = -1;
                        return -1;
                }
+               if (!args->stateless_rpc)
+                       /* Closed by pack_objects() via start_command() */
+                       fd[1] = -1;
        }
        if (args->stateless_rpc && cmds_sent)
                packet_flush(out);