# Add incremental relay test harness

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

Soph·3mo ago·4 files·+116 added/-2 removed

## Sessions

4a7575f2583fView 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-4a7575f2583f/index.html)

## Changes

4

- MREADME.md+8

- internal/syncer

- Mgit_http_backend_test.go+67

- Alive_source_test.go+35

- Msyncer.go+6/-2

````
251 unmodified lines

252
253
254
255
256
257
258
259
260
261
262
263
264
265

251 unmodified lines

That path exercises real smart HTTP fetch and push with a local bare source repo and a local bare target repo.

There is also an optional live read-only smoke against the public Linux repository:

```bash
env GOCACHE=/tmp/go-build GITSYNC_E2E_LIVE_LINUX=1 go test ./internal/syncer -run TestFetch_LiveLinuxSource -v
```

That is useful for large-source protocol and memory measurement checks without requiring a writable remote.

## Planned Bootstrap Path

There is a planned `bootstrap` command path for large initial syncs into an empty target. The intent is to relay a fetched source pack directly into target `receive-pack` instead of decoding the full object graph into local memory first.
````

MREADME.md+8

``
58 unmodified lines

59
60
61
62
63
64
65
66
67
12 unmodified lines

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

58 unmodified lines

if result.Pushed != 1 || result.Blocked != 0 {
		t.Fatalf("unexpected initial result: %+v", result)
	}
	if !result.Relay || result.RelayMode != "bootstrap" {
		t.Fatalf("expected initial empty-target sync to use bootstrap relay, got %+v", result)
	}

assertGitRefEqual(t, sourceBare, targetBare, plumbing.NewBranchReferenceName(testBranch))

12 unmodified lines

if result.Pushed != 1 || result.Blocked != 0 {
		t.Fatalf("unexpected incremental result: %+v", result)
	}
	if result.Relay || result.RelayMode != "" {
		t.Fatalf("expected incremental sync to stay on normal path for now, got %+v", result)
	}

assertGitRefEqual(t, sourceBare, targetBare, plumbing.NewBranchReferenceName(testBranch))
}

func TestRun_GitHTTPBackendSyncDivergedTarget(t *testing.T) {
	if os.Getenv(gitHTTPBackendEnv) == "" {
		t.Skip("set GITSYNC_E2E_GIT_HTTP_BACKEND=1 to run git-http-backend integration test")
	}

if _, err := exec.LookPath("git"); err != nil {
		t.Skipf("git not available: %v", err)
	}

root := t.TempDir()
	sourceBare := filepath.Join(root, "source.git")
	targetBare := filepath.Join(root, "target.git")
	sourceWorktree := filepath.Join(root, "source-work")
	targetWorktree := filepath.Join(root, "target-work")

runGit(t, root, "init", "--bare", sourceBare)
	runGit(t, root, "init", "--bare", targetBare)
	runGit(t, targetBare, "config", "http.receivepack", "true")
	runGit(t, root, "init", "-b", testBranch, sourceWorktree)
	runGit(t, sourceWorktree, "config", "user.name", "git-sync test")
	runGit(t, sourceWorktree, "config", "user.email", "git-sync@example.com")

writeFile(t, filepath.Join(sourceWorktree, "README.md"), "base\n")
	runGit(t, sourceWorktree, "add", "README.md")
	runGit(t, sourceWorktree, "commit", "-m", "base")
	runGit(t, sourceWorktree, "remote", "add", "source", sourceBare)
	runGit(t, sourceWorktree, "remote", "add", "target", targetBare)
	runGit(t, sourceWorktree, "push", "source", "HEAD:refs/heads/"+testBranch)
	runGit(t, sourceWorktree, "push", "target", "HEAD:refs/heads/"+testBranch)

runGit(t, root, "init", "-b", testBranch, targetWorktree)
	runGit(t, targetWorktree, "remote", "add", "origin", targetBare)
	runGit(t, targetWorktree, "fetch", "origin", testBranch)
	runGit(t, targetWorktree, "reset", "--hard", "origin/"+testBranch)
	runGit(t, targetWorktree, "config", "user.name", "git-sync test")
	runGit(t, targetWorktree, "config", "user.email", "git-sync@example.com")
	writeFile(t, filepath.Join(targetWorktree, "TARGET.txt"), "target-only\n")
	runGit(t, targetWorktree, "add", "TARGET.txt")
	runGit(t, targetWorktree, "commit", "-m", "target diverges")
	runGit(t, targetWorktree, "push", "origin", "HEAD:refs/heads/"+testBranch)

writeFile(t, filepath.Join(sourceWorktree, "SOURCE.txt"), "source-only\n")
	runGit(t, sourceWorktree, "add", "SOURCE.txt")
	runGit(t, sourceWorktree, "commit", "-m", "source diverges")
	runGit(t, sourceWorktree, "push", "source", "HEAD:refs/heads/"+testBranch)

server := newGitHTTPBackendServer(t, root)
	defer server.Close()

_, err := Run(context.Background(), Config{
		Source: Endpoint{URL: server.RepoURL("source.git")},
		Target: Endpoint{URL: server.RepoURL("target.git")},
	})
	if err == nil {
		t.Fatalf("expected diverged target sync to fail")
	}
	if !strings.Contains(err.Error(), "blocked") {
		t.Fatalf("expected blocked error, got %v", err)
	}
}

func TestBootstrap_GitHTTPBackendSync(t *testing.T) {
	if os.Getenv(gitHTTPBackendEnv) == "" {
		t.Skip("set GITSYNC_E2E_GIT_HTTP_BACKEND=1 to run git-http-backend integration test")
	}

result, err := Fetch(context.Background(), Config{
		Source: Endpoint{URL: "https://github.com/torvalds/linux.git"},
		Branches: []string{"master"},
		ProtocolMode: protocolModeAuto,
		ShowStats: true,
		MeasureMemory: true,
	}, nil, nil)
	if err != nil {
		t.Fatalf("live linux fetch failed: %v", err)
	}
	if result.Protocol == "" {
		t.Fatalf("expected negotiated protocol, got empty result")
	}
	if len(result.Wants) == 0 {
		t.Fatalf("expected at least one wanted ref")
	}
	if !result.Measurement.Enabled {
		t.Fatalf("expected measurement to be enabled")
	}
}
