diff options
Diffstat (limited to 'package.sort.go')
| -rw-r--r-- | package.sort.go | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/package.sort.go b/package.sort.go new file mode 100644 index 0000000..0dead0a --- /dev/null +++ b/package.sort.go @@ -0,0 +1,196 @@ +package zoopb + +// this is becoming a standard format +// todo: autogenerate this from the .proto file? + +import ( + "fmt" + "os" + "sort" + sync "sync" + "time" + + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +// 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 +} + +// Update version and timestamp. +// returns ok (ok == true if not found) +func (r *Packages) Update(newP *Package) bool { + lock.Lock() + defer lock.Unlock() + + var found *Package + for _, p := range r.Packages { + if p.Name == newP.Name { + found = p + } + } + if found == nil { + // r.Append(newP) // update here? + return true + } + + var changed bool = false + if newP.Version != found.Version { + changed = true + found.Version = newP.Version + } + + now := time.Now() + found.Laststamp = timestamppb.New(now) + return changed +} + +// returns time.Duration since last Update() +func (r *Package) Age(newP *Package) time.Duration { + t := time.Since(r.Laststamp.AsTime()) + return t +} + +// find a package by name +func (r *Packages) FindByName(name string) *Package { + lock.RLock() + defer lock.RUnlock() + + for _, p := range r.Packages { + if p.Name == name { + return p + } + } + + return nil +} + +func (r *Packages) Len() int { + lock.RLock() + defer lock.RUnlock() + + return len(r.Packages) +} + +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 +} +*/ |
