# Shape stable gitsync results for embedders

`661eec5`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·
Soph·3mo ago·2 files·+109 added/-36 removed

## Sessions

59490433b887View transcript

## Changes

2

- pkg/gitsync

- Mclient_test.go+50
  
  - Mtypes.go+59/-36

```
6 unmodified lines
7
8
9
10
11
12
13
14
15
85 unmodified lines

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

6 unmodified lines

"testing"

"github.com/go-git/go-git/v6/plumbing"

"github.com/soph/git-sync/internal/planner"
	"github.com/soph/git-sync/internal/syncer"

func TestBuildSyncConfigUsesDefaultProtocolAndMaterializedLimit(t *testing.T) {
85 unmodified lines

t.Fatalf("expected auth provider error")
	}
}

func TestFromSyncerResultShapesStableSummary(t *testing.T) {
	got := fromSyncerResult(syncer.Result{
		Plans: []planner.BranchPlan{
			{
				Branch:     "main",
				SourceRef:  plumbing.ReferenceName("refs/heads/main"),
				TargetRef:  plumbing.ReferenceName("refs/heads/main"),
				SourceHash: plumbing.NewHash("1111111111111111111111111111111111111111"),
				TargetHash: plumbing.NewHash("2222222222222222222222222222222222222222"),
				Kind:       planner.RefKindBranch,
				Action:     planner.ActionUpdate,
				Reason:     "fast-forward",
			},
		},
		Pushed:             1,
		Skipped:            2,
		Blocked:            3,
		Deleted:            4,
		DryRun:             true,
		Relay:              true,
		RelayMode:          "incremental-relay",
		RelayReason:        "fast-forward",
		Batching:           true,
		BatchCount:         5,
		PlannedBatchCount:  6,
		TempRefs:           []string{"refs/gitsync/bootstrap/heads/main/1"},
		BootstrapSuggested: true,
		Protocol:           "v2",
	})

if len(got.Refs) != 1 || got.Refs[0].Branch != "main" {
		t.Fatalf("unexpected refs: %+v", got.Refs)
	}
	if got.Counts.Applied != 1 || got.Counts.Skipped != 2 || got.Counts.Blocked != 3 || got.Counts.Deleted != 4 {
		t.Fatalf("unexpected counts: %+v", got.Counts)
	}
	if !got.Execution.DryRun || !got.Execution.Relay || got.Execution.Mode != "incremental-relay" || got.Execution.Reason != "fast-forward" {
		t.Fatalf("unexpected execution summary: %+v", got.Execution)
	}
	if !got.Execution.Batch.Enabled || got.Execution.Batch.Done != 5 || got.Execution.Batch.Planned != 6 {
		t.Fatalf("unexpected batch summary: %+v", got.Execution.Batch)
	}
	if !got.Execution.BootstrapSuggested {
		t.Fatalf("expected bootstrap suggestion in execution summary")
	}
}
```

---

// RefPlan describes the outcome for a single ref.
type RefPlan struct {
type RefResult struct {
	Branch     string  `json:"branch"`
	SourceRef  string  `json:"source_ref"`
	TargetRef  string  `json:"target_ref"`

Reason     string  `json:"reason"`
}

// RefPlan is kept as an alias for early adopters while the stable result// surface converges on the more explicit RefResult name.
type RefPlan = RefResult

// RefInfo identifies a named ref.
type RefInfo struct {
	Name string `json:"name"`

}

// SyncCounts summarizes per-run ref outcomes.
type SyncCounts struct {
	Applied int `json:"applied"`
	Skipped int `json:"skipped"`
	Blocked int `json:"blocked"`
	Deleted int `json:"deleted"`
}

// BatchSummary describes batching behavior when it was used.
type BatchSummary struct {
	Enabled bool `json:"enabled"`
	Planned int  `json:"planned"`
	Done    int  `json:"done"`
}

// ExecutionSummary describes how a sync was carried out.
type ExecutionSummary struct {
	DryRun             bool         `json:"dry_run"`
	Protocol           string       `json:"protocol"`
	Relay              bool         `json:"relay"`
	Mode               string       `json:"mode"`
	Reason             string       `json:"reason"`
	BootstrapSuggested bool         `json:"bootstrap_suggested"`
	Batch              BatchSummary `json:"batch"`
}

// SyncResult holds structured sync output suitable for workers.
type SyncResult struct {
	Plans              []RefPlan   `json:"plans"`
	Pushed             int         `json:"pushed"`
	Skipped            int         `json:"skipped"`
	Blocked            int         `json:"blocked"`
	Deleted            int         `json:"deleted"`
	DryRun             bool        `json:"dry_run"`
	Relay              bool        `json:"relay"`
	RelayMode          string      `json:"relay_mode"`
	RelayReason        string      `json:"relay_reason"`
	Batching           bool        `json:"batching"`
	BatchCount         int         `json:"batch_count"`
	PlannedBatchCount  int         `json:"planned_batch_count"`
	TempRefs           []string    `json:"temp_refs"`
	BootstrapSuggested bool        `json:"bootstrap_suggested"`
	Stats              Stats       `json:"stats"`
	Measurement        Measurement `json:"measurement"`
	Protocol           string      `json:"protocol"`
	Refs        []RefResult      `json:"refs"`
	Counts      SyncCounts       `json:"counts"`
	Execution   ExecutionSummary `json:"execution"`
	Stats       Stats            `json:"stats"`
	Measurement Measurement      `json:"measurement"`
}

// PlanResult is the dry-run form of SyncResult.
function fromSyncerResult(result syncer.Result) SyncResult {
out := SyncResult{
Plans:              make([]RefPlan, 0, len(result.Plans)),
Pushed:             result.Pushed,
Skipped:            result.Skipped,
Blocked:            result.Blocked,
Deleted:            result.Deleted,
DryRun:             result.DryRun,
Relay:              result.Relay,
RelayMode:          result.RelayMode,
RelayReason:        result.RelayReason,
Batching:           result.Batching,
BatchCount:         result.BatchCount,
PlannedBatchCount:  result.PlannedBatchCount,
TempRefs:           append([]string(nil), result.TempRefs...),
BootstrapSuggested: result.BootstrapSuggested,
Stats:              fromSyncerStats(result.Stats),
Measurement:        fromSyncerMeasurement(result.Measurement),
Protocol:           result.Protocol,
Refs: make([]RefResult, 0, len(result.Plans)),
Counts: SyncCounts{
Applied: result.Pushed,
Skipped: result.Skipped,
Blocked: result.Blocked,
Deleted: result.Deleted,
},
Execution: ExecutionSummary{
DryRun:             result.DryRun,
Protocol:           result.Protocol,
Relay:              result.Relay,
Mode:               result.RelayMode,
Reason:             result.RelayReason,
BootstrapSuggested: result.BootstrapSuggested,
Batch: BatchSummary{
Enabled: result.Batching,
Planned: result.PlannedBatchCount,
Done:    result.BatchCount,
},
},
Stats:       fromSyncerStats(result.Stats),
Measurement: fromSyncerMeasurement(result.Measurement),
}
for _, plan := range result.Plans {
out.Plans = append(out.Plans, RefPlan{
out.Refs = append(out.Refs, RefResult{
Branch:     plan.Branch,
SourceRef:  plan.SourceRef.String(),
TargetRef:  plan.TargetRef.String(),
}})}}
return out
}
``
