package git import ( "path/filepath" "sync" "src.dualinventive.com/go/devsim" "src.dualinventive.com/go/devsim/repository" "gopkg.in/src-d/go-git.v4/plumbing/transport" ) // Bucket is a collection of GIT repositories type Bucket struct { mx sync.Mutex authMethod transport.AuthMethod baseRepositoryDir string repositories []*Repository } // Static check var _ repository.Bucket = &Bucket{} // NewBucket creates a new GIT repository bucket. The repository uses authMethod for GIT authorization. // The repository is cloned in the baseRepositoryDir. func NewBucket(authMethod transport.AuthMethod, baseRepositoryDir string) *Bucket { return &Bucket{ authMethod: authMethod, baseRepositoryDir: baseRepositoryDir, } } // Add adds the URI to the repository bucket func (g *Bucket) Add(uri string) error { // The base dir for the repository is our base dir plus the uri of the repository. dir := filepath.Join(g.baseRepositoryDir, sanitizePathString(uri)) r, err := newRepository(uri, dir, g.authMethod) if err != nil { return err } return g.add(r) } // add adds the repository to the bucket func (g *Bucket) add(repo *Repository) error { g.mx.Lock() defer g.mx.Unlock() uri := repo.URI() if g.find(uri) != nil { return devsim.ErrAlreadyExists } g.repositories = append(g.repositories, repo) return nil } // Remove removes the URI from the repository bucket func (g *Bucket) Remove(uri string) error { g.mx.Lock() defer g.mx.Unlock() index, err := g.findIndex(uri) if err != nil { return err } g.repositories = append(g.repositories[:index], g.repositories[index+1:]...) return nil } // Poll polls all the repositories in the repository bucket. func (g *Bucket) Poll() []error { errs := make([]error, 0) for _, r := range g.List() { if err := r.Poll(); err != nil { errs = append(errs, err) } } return errs } // Find finds the repository using the URI func (g *Bucket) Find(URI string) (repository.Repository, error) { g.mx.Lock() defer g.mx.Unlock() s := g.find(URI) if s == nil { return nil, devsim.ErrNotFound } return s, nil } // findIndex returns the index of the repository. This is not thread safe. func (g *Bucket) findIndex(uri string) (int, error) { for i := range g.repositories { if g.repositories[i].URI() == uri { return i, nil } } return 0, devsim.ErrNotFound } // find returns the repository or nil when the repository is not found. func (g *Bucket) find(uri string) *Repository { for i := range g.repositories { if g.repositories[i].URI() == uri { return g.repositories[i] } } return nil } // List returns all the repositories in the repository bucket. func (g *Bucket) List() []repository.Repository { g.mx.Lock() tmp := make([]repository.Repository, len(g.repositories)) for i, repository := range g.repositories { tmp[i] = repository } g.mx.Unlock() return tmp }