// Package registry provides a global registry of package-format frontends. // // Frontends self-register via init() from their own packages, so a future // format (e.g. Gentoo ebuild, void-src) only needs a new package that imports // this one — nothing else changes. package registry import ( "fmt" "sort" "sync" ) // Options carries per-conversion settings shared by all frontends. type Options struct { Output string // directory to write converted output into Repo string // repository base URL (binary frontend) Arch string // target architecture (source frontend) } // Frontend converts one input of a specific package format to Zeta. type Frontend interface { // Name returns the frontend's CLI subcommand name. Name() string // Convert converts input into Zeta format under opts.Output. Convert(input string, opts Options) error } var ( mu sync.RWMutex frontends = make(map[string]Frontend) ) // Register adds f to the global registry. It panics if a frontend with the // same Name is already registered. func Register(f Frontend) { mu.Lock() defer mu.Unlock() name := f.Name() if name == "" { panic("registry: frontend with empty name") } if _, dup := frontends[name]; dup { panic(fmt.Sprintf("registry: duplicate frontend %q", name)) } frontends[name] = f } // List returns the names of all registered frontends, sorted. func List() []string { mu.RLock() defer mu.RUnlock() names := make([]string, 0, len(frontends)) for name := range frontends { names = append(names, name) } sort.Strings(names) return names } // Get returns the frontend registered under name. func Get(name string) (Frontend, bool) { mu.RLock() defer mu.RUnlock() f, ok := frontends[name] return f, ok }