package gitpb // this is becoming a standard format // todo: autogenerate this from the .proto file? import ( "fmt" "os" "sort" sync "sync" ) // bad global lock until I figure out some other plan var repolock sync.RWMutex type RepoIterator struct { sync.RWMutex packs []*Repo index int } // NewRepoIterator initializes a new iterator. func NewRepoIterator(packs []*Repo) *RepoIterator { return &RepoIterator{packs: packs} } // Scan moves to the next element and returns false if there are no more packs. func (it *RepoIterator) Scan() bool { if it.index >= len(it.packs) { return false } it.index++ return true } // Repo returns the current repo. func (it *RepoIterator) Repo() *Repo { if it.packs[it.index-1] == nil { for i, d := range it.packs { fmt.Println("i =", i, d) } fmt.Println("len =", len(it.packs)) fmt.Println("repo == nil", it.index, it.index-1) os.Exit(-1) } return it.packs[it.index-1] } // Use Scan() in a loop, similar to a while loop // // for iterator.Scan() { // d := iterator.Repo() // fmt.Println("Repo UUID:", d.Uuid) // } func (r *Repos) All() *RepoIterator { repoPointers := r.selectAllRepo() iterator := NewRepoIterator(repoPointers) return iterator } func (r *Repos) SortByName() *RepoIterator { packs := r.selectAllRepo() sort.Sort(RepoByName(packs)) iterator := NewRepoIterator(packs) return iterator } func (all *Repos) Len() int { repolock.RLock() defer repolock.RUnlock() return len(all.Repos) } type RepoByName []*Repo func (a RepoByName) Len() int { return len(a) } func (a RepoByName) Less(i, j int) bool { return a[i].GoPath < a[j].GoPath } func (a RepoByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // safely returns a slice of pointers to the Repo protobufs func (all *Repos) selectAllRepo() []*Repo { repolock.RLock() defer repolock.RUnlock() // Create a new slice to hold pointers to each Repo var aRepos []*Repo aRepos = make([]*Repo, len(all.Repos)) for i, p := range all.Repos { aRepos[i] = p // Copy pointers for safe iteration } return aRepos }