func (w *Watcher) DeriveRepoFullName(partial string) (repo string) {
	return w.lister.DeriveRepoFullName(partial)
}
DeriveRepoFullName derives the full name of a repo from a partial name.
package repo
import (
	"sync"
	"time"
	"github.com/cockroachdb/errors"
	"github.com/sirupsen/logrus"
	"go.stevenxie.me/api/pkg/stream"
	"go.stevenxie.me/api/pkg/zero"
)
func NewWatcher(
	lister ListerService,
	interval time.Duration,
	opts ...func(*WatcherConfig),
) *Watcher {
	cfg := WatcherConfig{
		Logger: zero.Logger(),
	}
	for _, opt := range opts {
		opt(&cfg)
	}
	w := &Watcher{
		lister: lister,
		streamer: stream.NewPoller(
			func() (zero.Interface, error) {
				return lister.ListGoRepos()
			},
			interval,
		),
		log: cfg.Logger,
	}
	go w.run()
	return w
}
type (
	Watcher struct {
		lister   ListerService
		streamer stream.Streamer
		log      logrus.FieldLogger
		mux   sync.Mutex
		repos []string
		err   error
	}
	WatcherConfig struct {
		Logger logrus.FieldLogger
	}
)
var (
	_ ListerService    = (*Watcher)(nil)
	_ ValidatorService = (*Watcher)(nil)
)
func (w *Watcher) ListGoRepos() ([]string, error) {
	w.mux.Lock()
	defer w.mux.Unlock()
	repos := make([]string, len(w.repos))
	copy(repos, w.repos)
	return repos, w.err
}
func (w *Watcher) IsRepoValid(repo string) (bool, error) {
	repos, err := w.ListGoRepos()
	if err != nil {
		return false, errors.Wrap(err, "repo: listing Go repos")
	}
	for _, r := range repos {
		if r == repo {
			return true, nil
		}
	}
	return false, nil
}