Lazy-fetch source closure before materialized fallback · Entire
Lazy-fetch source closure before materialized fallback
c827f33→main·
Soph·2mo ago·1 file·+25 added/-7
needsLocalSourceClosure approximates which scenarios require the local store, but it can't perfectly mirror CanIncrementalRelay — for instance, when target capabilities are unknown the relay rejects even though the plans look skip/create-only. In that case the materialized fallback ran against an empty in-memory store and silently produced an insufficient pack.
Track whether the closure has been fetched and refetch on demand before materialized runs. Pure-relay paths still skip the upfront fetch (no double-trip), and the fallback regains the store it needs.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Sessions
62b6e35685a0View transcript
Changes
1
internal/syncer
Msyncer.go+25/-7
523 unmodified lines
524
525
526
527
528
529
530
527
528
529
530
531
532
533
534
535
536
536
537
538
539
540
541
542
539
543
544
545
546
547
548
549
550
551
552
553
554
555
38 unmodified lines
594
595
596
586
597
598
599
600
601
602
603
604
605
606
607
523 unmodified lines
// Normal sync: allocate in-memory repo. The source closure is fetched
// lazily — only when planning needs ancestry data (FF detection on a
// divergent branch) or the materialized fallback will run (force, prune,
// or any divergent ref). Pure skip/create plans take incremental relay
// without ever decoding source objects locally, so the upfront fetch is
// a wasted full-pack round trip.
// divergent branch) or when the materialized fallback ends up running.
// Pure skip/create plans that take incremental relay never decode
// source objects locally, so the upfront fetch would be a wasted
// full-pack round trip.
repo, err := git.Init(memory.NewStorage(), nil)
if err != nil {
return Result{}, fmt.Errorf("init in-memory repository: %w", err)
}
gpDesired := convert.DesiredRefs(desiredRefs)
if needsLocalSourceClosure(s.cfg, desiredRefs, targetRefMap) {
closureFetched := false
fetchClosure := func() error {
if closureFetched {
return nil
}
if err := sourceService.FetchToStore(ctx, repo.Storer, s.sourceConn, gpDesired, targetRefMap); err != nil {
if !errors.Is(err, git.NoErrAlreadyUpToDate) {
return Result{}, fmt.Errorf("fetch to store: %w", err)
}
}
closureFetched = true
return nil
}
if needsLocalSourceClosure(s.cfg, desiredRefs, targetRefMap) {
if err := fetchClosure(); err != nil {
return Result{}, err
}
}
plans, err := planner.BuildPlans(repo.Storer, desiredRefs, targetRefMap, managedTargets, planConfig(s.cfg))
38 unmodified lines
result.RelayMode = incResult.RelayMode
result.RelayReason = incResult.RelayReason
} else if len(pushPlans) > 0 {
// Materialized fallback
// Materialized fallback. needsLocalSourceClosure may have skipped
// the upfront fetch when relay looked eligible from the plan
// shape alone, but CanIncrementalRelay can still reject (e.g.
// when target capabilities are unknown). Fetch on demand so
// materialized doesn't run against an empty store.
if err := fetchClosure(); err != nil {
return result, err
}
if err := s.executeMaterialized(ctx, repo.Storer, desiredRefs, pushPlans); err != nil {
return result, err
}
Minternal/syncer/syncer.go+25/-7