fix: enable building on Windows without CGO (#1117)

The dolt storage backend requires CGO due to its gozstd dependency.
This change makes the dolt backend optional using build tags, allowing
`go install` to work on Windows where CGO is disabled by default.

Changes:
- Add BackendFactory registration pattern to factory package
- Create factory_dolt.go with `//go:build cgo` constraint that
  registers the dolt backend only when CGO is available
- Update init.go to use factory instead of direct dolt import
- When dolt backend is requested without CGO, provide helpful error
  message directing users to pre-built binaries

The sqlite backend (default) works without CGO and covers the majority
of use cases. Users who need dolt can either:
1. Use pre-built binaries from GitHub releases
2. Enable CGO by installing a C compiler

Fixes #1116
This commit is contained in:
Bobby Johnson
2026-01-15 19:23:02 -08:00
committed by GitHub
parent c1a9dda173
commit 55e733cf62
5 changed files with 125 additions and 9 deletions

View File

@@ -9,10 +9,20 @@ import (
"github.com/steveyegge/beads/internal/configfile"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/storage/dolt"
"github.com/steveyegge/beads/internal/storage/sqlite"
)
// BackendFactory is a function that creates a storage backend
type BackendFactory func(ctx context.Context, path string, opts Options) (storage.Storage, error)
// backendRegistry holds registered backend factories
var backendRegistry = make(map[string]BackendFactory)
// RegisterBackend registers a storage backend factory
func RegisterBackend(name string, factory BackendFactory) {
backendRegistry[name] = factory
}
// Options configures how the storage backend is opened
type Options struct {
ReadOnly bool
@@ -40,9 +50,15 @@ func NewWithOptions(ctx context.Context, backend, path string, opts Options) (st
return sqlite.NewWithTimeout(ctx, path, opts.LockTimeout)
}
return sqlite.New(ctx, path)
case configfile.BackendDolt:
return dolt.New(ctx, &dolt.Config{Path: path, ReadOnly: opts.ReadOnly})
default:
// Check if backend is registered (e.g., dolt with CGO)
if factory, ok := backendRegistry[backend]; ok {
return factory(ctx, path, opts)
}
// Provide helpful error for dolt on systems without CGO
if backend == configfile.BackendDolt {
return nil, fmt.Errorf("dolt backend requires CGO (not available on this build); use sqlite backend or install from pre-built binaries")
}
return nil, fmt.Errorf("unknown storage backend: %s (supported: sqlite, dolt)", backend)
}
}

View File

@@ -0,0 +1,17 @@
//go:build cgo
package factory
import (
"context"
"github.com/steveyegge/beads/internal/configfile"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/storage/dolt"
)
func init() {
RegisterBackend(configfile.BackendDolt, func(ctx context.Context, path string, opts Options) (storage.Storage, error) {
return dolt.New(ctx, &dolt.Config{Path: path, ReadOnly: opts.ReadOnly})
})
}