package zoopb // 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 lock sync.RWMutex type PackageIterator struct { sync.RWMutex packs []*Package index int } // NewPackageIterator initializes a new iterator. func NewPackageIterator(packs []*Package) *PackageIterator { return &PackageIterator{packs: packs} } // Scan moves to the next element and returns false if there are no more packs. func (it *PackageIterator) Scan() bool { if it.index >= len(it.packs) { return false } it.index++ return true } // Package returns the current repo. func (it *PackageIterator) Package() *Package { 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.Package() // fmt.Println("Package UUID:", d.Uuid) // } func (r *Packages) All() *PackageIterator { repoPointers := r.selectAllPackages() iterator := NewPackageIterator(repoPointers) return iterator } func (r *Packages) SortByName() *PackageIterator { packs := r.selectAllPackages() sort.Sort(ByName(packs)) iterator := NewPackageIterator(packs) return iterator } // enforces no duplicate package names func (r *Packages) Append(newP *Package) bool { lock.Lock() defer lock.Unlock() for _, p := range r.Packages { if p.Name == newP.Name { return false } } r.Packages = append(r.Packages, newP) return true } // find a package by name func (r *Packages) FindByName(name string) *Package { lock.Lock() defer lock.Unlock() for _, p := range r.Packages { if p.Name == name { return p } } return nil } type ByName []*Package func (a ByName) Len() int { return len(a) } func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name } func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // safely returns a slice of pointers to the Package protobufs func (r *Packages) selectAllPackages() []*Package { lock.RLock() defer lock.RUnlock() // Create a new slice to hold pointers to each Package var allPacks []*Package allPacks = make([]*Package, len(r.Packages)) for i, p := range r.Packages { allPacks[i] = p // Copy pointers for safe iteration } return allPacks } /* func (r *Packages) UnmergedPackageRepos() *PackageRepoIterator { repoPointers := r.selectUnmergedPackageRepos() sort.Sort(ByName(repoPointers)) iterator := NewPackageRepoIterator(repoPointers) return iterator } */ /* // this sort doesn't really work. I think it forgets to sort the last two // todo: sort this out. literally // SelectPackagePointers safely returns a slice of pointers to Package records. func (r *Packages) selectUnmergedPackages() []*PackageRow { r.RLock() defer r.RUnlock() // Create a new slice to hold pointers to each Package // repoPointers := make([]*Package, len(c.E.Packages)) var repoPointers []*PackageRow for _, repo := range me.allrepos { repoPointers = append(repoPointers, repo) // Copy pointers for safe iteration } return repoPointers } */