package gitpb // this is becoming a standard format // todo: autogenerate this from the .proto file? import ( "fmt" "os" "sort" sync "sync" "time" ) // bad global lock until I figure out some other plan var godeplock sync.RWMutex type GoDepIterator struct { sync.RWMutex packs []*GoDep index int } // NewGoDepGoDepIterator initializes a new iterator. func NewGoDepIterator(packs []*GoDep) *GoDepIterator { return &GoDepIterator{packs: packs} } // Scan moves to the next element and returns false if there are no more packs. func (it *GoDepIterator) Scan() bool { if it.index >= len(it.packs) { return false } it.index++ return true } // GoDep returns the current repo. func (it *GoDepIterator) GoDep() *GoDep { 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.GoDep() // fmt.Println("GoDep UUID:", d.Uuid) // } func (r *GoDeps) All() *GoDepIterator { repoPointers := r.selectAllGoDeps() iterator := NewGoDepIterator(repoPointers) return iterator } func (r *GoDeps) SortByName() *GoDepIterator { packs := r.selectAllGoDeps() sort.Sort(GoDepByPath(packs)) iterator := NewGoDepIterator(packs) return iterator } // enforces no duplicate package names func (r *GoDeps) Append(newP *GoDep) bool { refslock.Lock() defer refslock.Unlock() for _, p := range r.GoDeps { if p.GoPath == newP.GoPath { return false } } r.GoDeps = append(r.GoDeps, newP) return true } // returns time.Duration since last Update() func (r *GoDep) Age(newP *GoDep) time.Duration { t := time.Since(r.Ctime.AsTime()) return t } // find a dependancy by the go path func (r *GoDeps) FindByPath(gopath string) *GoDep { refslock.RLock() defer refslock.RUnlock() for _, p := range r.GoDeps { if p.GoPath == gopath { return p } } return nil } func (r *GoDeps) Len() int { refslock.RLock() defer refslock.RUnlock() return len(r.GoDeps) } type GoDepByPath []*GoDep func (a GoDepByPath) Len() int { return len(a) } func (a GoDepByPath) Less(i, j int) bool { return a[i].GoPath < a[j].GoPath } func (a GoDepByPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // safely returns a slice of pointers to the GoDep protobufs func (r *GoDeps) selectAllGoDeps() []*GoDep { refslock.RLock() defer refslock.RUnlock() // Create a new slice to hold pointers to each GoDep var allPacks []*GoDep allPacks = make([]*GoDep, len(r.GoDeps)) for i, p := range r.GoDeps { allPacks[i] = p // Copy pointers for safe iteration } return allPacks } func (all *GoDeps) DeleteByHash(hash string) *GoDep { refslock.Lock() defer refslock.Unlock() for i, _ := range all.GoDeps { if all.GoDeps[i].Hash == hash { all.GoDeps[i] = all.GoDeps[len(all.GoDeps)-1] all.GoDeps = all.GoDeps[:len(all.GoDeps)-1] return nil } } return nil }