package gitpb import ( "errors" "fmt" "path/filepath" "slices" "strings" "go.wit.com/lib/config" "go.wit.com/lib/env" "go.wit.com/log" ) // returns err if anything changes or anything is wrong (todo: should these be different?) func (r *Repo) LoadRemoteRefs(remoteName string) (*Stats, error) { fullname := filepath.Join(r.FullPath, ".git", remoteName+".refs.pb") stats := NewStats() stats.Filename = fullname err := config.ForceCreatePB(stats) return stats, err } // returns err if anything changes or anything is wrong (todo: should these be different?) func (r *Repo) MakeRemoteRefs(remoteName string) (*Stats, error) { stats, err := r.LoadRemoteRefs(remoteName) if err != nil { return stats, err } if stats.Len() != 0 { return stats, errors.New("refs file was already created") } cmd := []string{"git", "ls-remote", remoteName} // must use 'master' as queried from the git server // GO has 250k remote refs if env.True("stats") { log.Info("STATS VERBOSE Run:", cmd) } cmdout := r.Run(cmd) if len(cmdout.Stdout) == 0 { return stats, errors.New("got nothing from git ls-remote") } var counter int for _, line := range cmdout.Stdout { line = strings.TrimSpace(line) parts := strings.Fields(line) if len(parts) != 2 { log.Printf("Repo: %s\n", r.FullPath) log.Printf("CMD: %v\n", cmd) log.Printf("LINE:%s\n", line) return stats, errors.New(line) } if env.True("stats") { log.Printf("LINE:%v %d %s\n", parts, counter, r.FullPath) } counter += 1 newstat := new(Stat) newstat.Hash = parts[0] stats.Append(newstat) } if counter > 0 { stats.SaveByHash() } return stats, nil } func (x *Stats) SaveByHash() error { newx := NewStats() all := x.SortByHash() for all.Scan() { r := all.Next() newx.Clone(r) } newx.Filename = x.Filename err := newx.Save() return err } // returns err if anything changes or anything is wrong (todo: should these be different?) func (r *Repo) UpdateRemoteRefs(remoteName string) error { stats, err := r.LoadRemoteRefs(remoteName) if err != nil { return err } if stats.Len() == 0 { return errors.New("need to make file instead") } cmd := []string{"git", "ls-remote", remoteName} // must use 'master' as queried from the git server // GO has 250k remote refs if env.True("stats") { log.Info("STATS VERBOSE Run:", cmd) } cmdout := r.Run(cmd) if len(cmdout.Stdout) == 0 { return errors.New("got nothing back") } var ticker int var counter int var allnew []*Stat for _, line := range cmdout.Stdout { line = strings.TrimSpace(line) parts := strings.Fields(line) if len(parts) != 2 { log.Printf("Repo: %s\n", r.FullPath) log.Printf("CMD: %v\n", cmd) log.Printf("LINE:%s\n", line) return errors.New(line) } if env.True("stats") { log.Printf("LINE:%v %d %s\n", parts, ticker, r.FullPath) } // refpath := filepath.Join("refs/remote", remoteName) // if strings.HasPrefix(parts[1], refpath) { // this ref is not from the remote // continue // } counter += 1 newstat := new(Stat) newstat.Hash = parts[0] n, found := slices.BinarySearchFunc(stats.Stats, newstat, func(a, b *Stat) int { return strings.Compare(a.Hash, b.Hash) }) _ = n if found { // log.Info("found", n) continue } ticker += 1 log.Info("not found", newstat) allnew = append(allnew, newstat) } if ticker > 0 { stats.Stats = append(stats.Stats, allnew...) stats.SaveByHash() return errors.New(fmt.Sprintf("len(%d), ticker(%d) counter(%d) refs changed", stats.Len(), ticker, counter)) } return nil }