Subsequent patches will change how the output of pack-objects is
processed, so extract that processing into its own function.

Currently, at most 1 character can be buffered (in the "buffered" local
variable). One of those patches will require a larger buffer, so replace
that "buffered" local variable with a buffer array.

Signed-off-by: Jonathan Tan <jonathanta...@google.com>
---
 upload-pack.c | 80 +++++++++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/upload-pack.c b/upload-pack.c
index 5e81f1ff24..cec43e0a46 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -101,14 +101,51 @@ static int write_one_shallow(const struct commit_graft 
*graft, void *cb_data)
        return 0;
 }
 
+struct output_state {
+       char buffer[8193];
+       int used;
+};
+
+static int read_pack_objects_stdout(int outfd, struct output_state *os)
+{
+       /* Data ready; we keep the last byte to ourselves
+        * in case we detect broken rev-list, so that we
+        * can leave the stream corrupted.  This is
+        * unfortunate -- unpack-objects would happily
+        * accept a valid packdata with trailing garbage,
+        * so appending garbage after we pass all the
+        * pack data is not good enough to signal
+        * breakage to downstream.
+        */
+       ssize_t readsz;
+
+       readsz = xread(outfd, os->buffer + os->used,
+                      sizeof(os->buffer) - os->used);
+       if (readsz < 0) {
+               return readsz;
+       }
+       os->used += readsz;
+
+       if (os->used > 1) {
+               send_client_data(1, os->buffer, os->used - 1);
+               os->buffer[0] = os->buffer[os->used - 1];
+               os->used = 1;
+       } else {
+               send_client_data(1, os->buffer, os->used);
+               os->used = 0;
+       }
+
+       return readsz;
+}
+
 static void create_pack_file(const struct object_array *have_obj,
                             const struct object_array *want_obj)
 {
        struct child_process pack_objects = CHILD_PROCESS_INIT;
-       char data[8193], progress[128];
+       struct output_state output_state = {0};
+       char progress[128];
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
-       int buffered = -1;
        ssize_t sz;
        int i;
        FILE *pipe_fd;
@@ -235,39 +272,15 @@ static void create_pack_file(const struct object_array 
*have_obj,
                        continue;
                }
                if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
-                       /* Data ready; we keep the last byte to ourselves
-                        * in case we detect broken rev-list, so that we
-                        * can leave the stream corrupted.  This is
-                        * unfortunate -- unpack-objects would happily
-                        * accept a valid packdata with trailing garbage,
-                        * so appending garbage after we pass all the
-                        * pack data is not good enough to signal
-                        * breakage to downstream.
-                        */
-                       char *cp = data;
-                       ssize_t outsz = 0;
-                       if (0 <= buffered) {
-                               *cp++ = buffered;
-                               outsz++;
-                       }
-                       sz = xread(pack_objects.out, cp,
-                                 sizeof(data) - outsz);
-                       if (0 < sz)
-                               ;
-                       else if (sz == 0) {
+                       int result = read_pack_objects_stdout(pack_objects.out,
+                                                             &output_state);
+
+                       if (result == 0) {
                                close(pack_objects.out);
                                pack_objects.out = -1;
-                       }
-                       else
+                       } else if (result < 0) {
                                goto fail;
-                       sz += outsz;
-                       if (1 < sz) {
-                               buffered = data[sz-1] & 0xFF;
-                               sz--;
                        }
-                       else
-                               buffered = -1;
-                       send_client_data(1, data, sz);
                }
 
                /*
@@ -292,9 +305,8 @@ static void create_pack_file(const struct object_array 
*have_obj,
        }
 
        /* flush the data */
-       if (0 <= buffered) {
-               data[0] = buffered;
-               send_client_data(1, data, 1);
+       if (output_state.used > 0) {
+               send_client_data(1, output_state.buffer, output_state.used);
                fprintf(stderr, "flushed.\n");
        }
        if (use_sideband)
-- 
2.19.0.271.gfe8321ec05.dirty

Reply via email to