package forgepb import ( "errors" "fmt" "os" "path/filepath" "sort" "strings" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) // This will recreate your go.sum and go.mod files // checks to see if every 'master' git branch version // matches the go.sum file func (f *Forge) CleanGoDepsCheckOk(check *gitpb.Repo) error { if check == nil { log.Info("boo, check == nil") return errors.New("*repo == nil") } // re-create go.sum and go.mod if _, err := check.RedoGoMod(); err != nil { return err } // if go.mod still does not exist. maybe this isn't a golang repo? if !check.Exists("go.mod") { return errors.New("go.mod can not be created in " + check.GoPath) } check.GoDeps = nil // this assumes that go mod init and go mod tidy worked // if they did, then the go.mod file might be the only // file here. if so, this is called a 'primitive' golang package here // this means, it's totally self contained and requires only the language go // the name 'primitive' doesn't mean they are simple; these packages are usually awesome! if ok, _ := check.IsPrimitive(); ok { return nil } // parse the go.sum file if ok, err := check.ParseGoSum(); !ok { log.Info("CleanGoDepsCheckOk() error", err) return err } // this probably shouldn't happen and this check should be removed or logged if check.GoDepsLen() == 0 { // this is a primitive go lang library (or an interesting binary?) check.GoPrimitive = true return nil } // simple trim if err := f.TrimGoSum(check); err != nil { return err } var err error = nil log.Printf("current repo %s go dependancy count: %d", check.GetGoPath(), check.GoDepsLen()) deps := check.GoDeps.SortByGoPath() for deps.Scan() { depRepo := deps.Next() found := f.Repos.FindByGoPath(depRepo.GetGoPath()) if found == nil { if f.checkOverride(depRepo.GetGoPath()) { // skip this gopath because it's probably broken forever continue } log.Info("not found:", depRepo.GetGoPath()) err = errors.New("not found: " + depRepo.GetGoPath()) continue } // log.Info("found dep", depRepo.GetGoPath()) if depRepo.GetVersion() != found.GetMasterVersion() { check := f.Repos.FindByGoPath(depRepo.GoPath) var ends string if check.CheckDirty() { ends = "(dirty) " } if f.Config.IsReadOnly(check.GoPath) { ends += "(ignoring read-only) " log.Printf("%-48s ok error .%s. vs .%s. %s", depRepo.GetGoPath(), depRepo.GetVersion(), found.GetMasterVersion(), ends) } else { if f.checkOverride(depRepo.GetGoPath()) { ends += "(override) " log.Printf("%-48s ok error .%s. vs .%s. %s", depRepo.GetGoPath(), depRepo.GetVersion(), found.GetMasterVersion(), ends) // skip this gopath because it's probably broken forever continue } else { log.Printf("%-48s error %10s vs %10s %s", depRepo.GetGoPath(), depRepo.GetVersion(), found.GetMasterVersion(), ends) errs := fmt.Sprintf("%s error %s vs %s %s", depRepo.GetGoPath(), depRepo.GetVersion(), found.GetMasterVersion(), ends) err = errors.New(errs) } } } } return err } func (f *Forge) TrimGoSum(check *gitpb.Repo) error { var stuff map[string]string stuff = make(map[string]string) var modver map[string]string modver = make(map[string]string) var good map[string]bool good = make(map[string]bool) if check == nil { log.Info("boo, check == nil") return errors.New("*repo == nil") } filename := filepath.Join(filepath.Join(check.FullPath, "go.sum")) data, err := os.ReadFile(filename) if err != nil { return err } for _, line := range strings.Split(string(data), "\n") { parts := strings.Fields(line) if len(parts) < 3 { log.Info("BAD:", line) continue } gopath := parts[0] version := parts[1] hash := parts[2] if strings.HasSuffix(version, "/go.mod") { if _, ok := stuff[gopath]; ok { log.Info("MATCHED: gopath:", gopath, "version:", version) modver[gopath] = version + " " + hash good[gopath] = true } else { log.Info("GARBAGE: gopath:", gopath, "version:", version) } } else { log.Info("GOOD : gopath:", gopath, "version:", version) stuff[gopath] = version + " " + hash } } keys := make([]string, 0, len(stuff)) for k := range stuff { keys = append(keys, k) } // rewrite the go.sum file newfilename := filepath.Join(filepath.Join(check.FullPath, "go.sum")) newf, err := os.OpenFile(newfilename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return err } defer newf.Close() sort.Strings(keys) for _, gopath := range keys { if good[gopath] { fmt.Fprintf(newf, "%s %s\n", gopath, stuff[gopath]) fmt.Fprintf(newf, "%s %s\n", gopath, modver[gopath]) check := f.Repos.FindByGoPath(gopath) if check == nil { log.Info("gopath does not really exist:", gopath) } } } // fmt.Fprintln(newf, "test") return nil }