Cover v2 fetch-to-store cancellation behavior · Entire

Cover v2 fetch-to-store cancellation behavior

c6ecbcb→main·

Sessions

7fe8a1c82e41View 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-7fe8a1c82e41/index.html)

Changes

2

432 unmodified lines

Current rewrite note:
- Some of these are now covered, including empty source repo, tag force-retarget, duplicate/conflicting mappings, and tag creation when target objects already exist.
- Batched lightweight-tag creation without an extra pack is now covered directly.
- Basic context cancellation coverage now exists for probe and both v1/v2 source fetch paths.
- Basic context cancellation coverage now exists for probe, v1 fetch, v2 streaming fetch, and v2 fetch-to-store.
- Batched bootstrap resume mismatch and final-tip cutover paths now have direct integration coverage.
- Batched bootstrap reruns now also cover the "target ref already created, temp ref cleanup still pending" recovery path.
- Injected temp-ref delete failure during batched cutover is now covered end-to-end, including successful recovery on retry.

Mdocs/rewrite-issue-list.md+1/-1

14 unmodified lines

15
16
17
18
19
20
21
335 unmodified lines

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

14 unmodified lines

"github.com/go-git/go-git/v6/plumbing/protocol/packp/capability"
    "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband"
    "github.com/go-git/go-git/v6/plumbing/transport"
    "github.com/go-git/go-git/v6/storage/memory"

func TestCapabilities(t *testing.T) {
335 unmodified lines

}

func TestFetchToStoreV2ContextCanceled(t *testing.T) {
    started := make(chan struct{}, 1)
    ep, err := transport.NewEndpoint("https://example.com/repo.git")
    if err != nil {
        t.Fatalf("parse endpoint: %v", err)
    }
    conn := NewConn(ep, "source", nil, roundTripperFunc(func(req *http.Request) (*http.Response, error) {
        started <- struct{}{}
        <-req.Context().Done()
        return nil, req.Context().Err()
    }))

caps := &V2Capabilities{
        Caps: map[string]string{
            "fetch": "",
        },
    }
    desired := map[plumbing.ReferenceName]DesiredRef{
        plumbing.NewBranchReferenceName("main"): {
            SourceRef:  plumbing.NewBranchReferenceName("main"),
            TargetRef:  plumbing.NewBranchReferenceName("main"),
            SourceHash: plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
        },
    }

ctx, cancel := context.WithCancel(context.Background())
    done := make(chan error, 1)
    go func() {
        done <- fetchToStoreV2(ctx, memory.NewStorage(), conn, caps, desired, nil)
    }()

select {
    case <-started:
    case <-time.After(2 * time.Second):
        t.Fatal("request did not reach server before timeout")
    }
    cancel()

select {
    case err = <-done:
    case <-time.After(2 * time.Second):
        t.Fatal("fetchToStoreV2 did not return after cancellation")
    }
    if err == nil {
        t.Fatal("expected cancellation error")
    }
    if !errors.Is(err, context.Canceled) {
        t.Fatalf("expected context.Canceled, got %v", err)
    }
}

func TestFetchPackV1ClosesBodyOnDecodeError(t *testing.T) {
    ep, err := transport.NewEndpoint("https://example.com/repo.git")
    if err != nil {