# Restore streaming receive-pack pushes

`0ed62c5`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·

Soph·3mo ago·4 files·+160 added/-15 removed

## Sessions

945161187c0fView transcript

[?\
Can you take a look at the go code (wasm) in /Users/soph/Work/entire/devenv/entire-io-worktree1 based a bit on that I wonder if something like this can be build:Codex·GPT-5.4·1 step](/content/gh/entireio/git-sync/session/019d6d29-8cf7-7fe3-adc9-8c3e4d9d5603#timeline-945161187c0f/index.html)

## Changes

4

- internal/gitproto
  
  - Mpush.go+23/-11
  
  - Mpush_test.go+77
  
  - Msmarthttp.go+16/-4
  
  - Msmarthttp_test.go+44

```
96 unmodified lines

req *packp.UpdateRequests,
packData io.Reader,
) error {
	var buf bytes.Buffer
	if err := req.Encode(&buf); err != nil {
		var header bytes.Buffer
		if err := req.Encode(&header); err != nil {
			return fmt.Errorf("encode update-request: %w", err)
		}
		body := io.Reader(bytes.NewReader(header.Bytes()))
		if packData != nil {
			if _, err := io.Copy(&buf, packData); err != nil {
				return fmt.Errorf("buffer pack data: %w", err)
			}
			body = io.MultiReader(body, packData)
		}
		reader, err := PostRPCStream(ctx, conn, transport.ReceivePackService, buf.Bytes(), false, "receive-pack push")
		reader, err := PostRPCStreamBody(ctx, conn, transport.ReceivePackService, body, false, "receive-pack push")
		if err != nil {
			return fmt.Errorf("target receive-pack: %w", err)
		}
	}

```

Minternal/gitproto/push.go+23/-11

```
5 unmodified lines

**

func TestPushPackStartsHTTPBeforePackFullyRead(t *testing.T) {
    started := make(chan struct{}, 1)
    release := make(chan struct{})

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        started <- struct{}{}
        _, _ = io.Copy(io.Discard, r.Body)
        _ = r.Body.Close()
        w.WriteHeader(http.StatusOK)
    }))
    defer srv.Close()

conn := connForServer(t, srv)
    adv := packp.NewAdvRefs()
    adv.Capabilities = capability.NewList()

pack := &gatedReadCloser{
        first:   []byte("PACK"),
        second:  strings.Repeat("x", 1024),
        release: release,
    }

done := make(chan error, 1)
    go func() {
        done <- PushPack(context.Background(), conn, adv, []PushCommand{ {
            Name: "refs/heads/main",
            New:  plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
        }}, pack, false)
    })

select {
    case <-started:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not start before full pack was released")
    }

close(release)

select {
    case err := <-done:
        if err != nil {
            t.Fatalf("PushPack returned error: %v", err)
        }
    case <-time.After(2 * time.Second):
        t.Fatal("PushPack did not complete after releasing pack")
    }
}

...

```
Minternal/gitproto/smarthttp.go+16/-4

```
