package git import ( "sync" "github.com/mholt/caddy/middleware/git/gitos" ) // repoService is the service that runs in background and periodically // pull from the repository. type repoService struct { repo *Repo ticker gitos.Ticker // ticker to tick at intervals halt chan struct{} // channel to notify service to halt and stop pulling. } // Start starts a new background service to pull periodically. func Start(repo *Repo) { service := &repoService{ repo, gos.NewTicker(repo.Interval), make(chan struct{}), } go func(s *repoService) { for { select { case <-s.ticker.C(): err := repo.Pull() if err != nil { logger().Println(err) } case <-s.halt: s.ticker.Stop() return } } }(service) // add to services to make it stoppable Services.add(service) } // services stores all repoServices type services struct { services []*repoService sync.Mutex } // add adds a new service to list of services. func (s *services) add(r *repoService) { s.Lock() defer s.Unlock() s.services = append(s.services, r) } // Stop stops at most `limit` running services pulling from git repo at // repoURL. It waits until the service is terminated before returning. // If limit is less than zero, it is ignored. // TODO find better ways to identify repos func (s *services) Stop(repoURL string, limit int) { s.Lock() defer s.Unlock() // locate repos for i, j := 0, 0; i < len(s.services) && ((limit >= 0 && j < limit) || limit < 0); i++ { service := s.services[i] if service.repo.URL == repoURL { // send halt signal service.halt <- struct{}{} s.services[i] = nil j++ } } // remove them from repos list services := s.services[:0] for _, s := range s.services { if s != nil { services = append(services, s) } } s.services = services }