diff options
| -rw-r--r-- | argv.go | 1 | ||||
| -rw-r--r-- | doDev.go | 39 | ||||
| -rw-r--r-- | doStats.go | 197 | ||||
| -rw-r--r-- | doVerifyNamespace.go | 35 |
4 files changed, 259 insertions, 13 deletions
@@ -106,6 +106,7 @@ type DevCmd struct { URL string `arg:"--connect" help:"forge url"` Stats *StatsCmd `arg:"subcommand:stats" help:"generate origin.pb"` Namespace *EmptyCmd `arg:"subcommand:namespace" help:"check the namespaces"` + GitConfig *EmptyCmd `arg:"subcommand:gitconfig" help:"check the .git/config files"` } type GenerateCmd struct { @@ -3,7 +3,10 @@ package main -import "go.wit.com/lib/env" +import ( + "go.wit.com/lib/env" + "go.wit.com/log" +) // so don't delete them func doDev() (string, error) { @@ -25,10 +28,34 @@ func doDev() (string, error) { s, err = doStats(argv.Dev.Stats) return s, err } + if argv.Dev.Namespace != nil { - s, err = doVerifyNamespace() - return s, err + fixed := me.forge.RunOnRepos(me.forge.Repos, doCleanNamespace) + if fixed.Len() == 0 { + return "no namespaces changed", nil + } + + // show the changed repos & save cache .pb file + fixed = fixed.SortActual() + footer := me.forge.PrintDefaultTB(fixed) + me.forge.Repos.SaveVerbose() + return "changed namespaces: " + footer, nil } + + if argv.Dev.GitConfig != nil { + // me.forge.ConfigRill(1, 1) + fixed := me.forge.RunOnRepos(me.forge.Repos, doGitConfig) + if fixed.Len() == 0 { + return "no git config changes", nil + } + + // show the changed repos & save cache .pb file + fixed = fixed.SortActual() + footer := me.forge.PrintErrorsTB(fixed) + me.forge.Repos.SaveVerbose() + return ".git/config problems: " + footer, nil + } + if argv.Dev.GoWork != nil { s, err = doGoWork() return s, err @@ -48,5 +75,11 @@ func doDev() (string, error) { return "build ok", nil } + if env.True("stats") { + log.Info("STATS VERBOSE") + } else { + log.Info("STATS not VERBOSE") + } + return "no dev subcommand", nil } @@ -5,9 +5,14 @@ package main import ( "errors" + "fmt" + "os" + "path/filepath" + "slices" "strings" "go.wit.com/lib/cobol" + "go.wit.com/lib/config" "go.wit.com/lib/env" "go.wit.com/lib/protobuf/argvpb" "go.wit.com/lib/protobuf/gitpb" @@ -59,7 +64,7 @@ func doStats(cmd *StatsCmd) (string, error) { func doStatsRepo(r *gitpb.Repo) (string, error) { var allerr error - pb, err := r.LoadStats() + pb, err := r.LoadStats("origin") if err == nil { log.Info("LoadStats() ok", pb.Filename) } else { @@ -242,3 +247,193 @@ func safeDelete(r *gitpb.Repo, deleteHash string, keepHash string) error { return log.Errorf("NOT SAFE") } + +// /tmp/go-nsupdate$ git ls-remote +// From [email protected]:SpComb/go-nsupdate.git +// d65f28d10991354b3af0168001a4beea6b8242f9 HEAD +// d65f28d10991354b3af0168001a4beea6b8242f9 refs/heads/master +// fb04ebe13a16c01e1a7eb3892a0aca8c6db96fa0 refs/pull/3/head +// d774220311b2d44c770e7431ec663c8875488a1e refs/pull/6/head +// fefb9ea80745893a2203576bdc2872d33e539064 refs/pull/7/head +// c09c90d0a931888862262a6ed3753eed0af4ddca refs/pull/8/head + +// the correct syntax for +// git log -n 8 --format=%H%00%ae%00%as%00%s origin/HEAD +func updateStats(r *gitpb.Repo, pb *gitpb.Stats, remoteName string) (int, error) { + var allerr error + var counter int + cmd := []string{"git", "log", "-n", "100", makeFmts(), remoteName} // must use 'master' as queried from the git server + // cmd := []string{"git", "log", "-n", "100", makeFmts(), "origin/HEAD"} // HEAD is _NOT_ always set + if env.True("stats") { + log.Info("Run:", cmd) + } + cmdout := r.Run(cmd) + for i, line := range cmdout.Stdout { + parts := strings.Split(line, standardSeperator) + hash := parts[0] + if len(parts) < 2 { + log.Printf("Repo: %s\n", r.FullPath) + log.Printf("CMD: %v\n", cmd) + log.Printf("LINE:%8.8s %2d %v\n", hash, i, parts[1:]) + } + if env.True("stats") { + log.Printf("LINE:%8.8s %2d %v\n", hash, i, parts[1:]) + } + found := pb.FindByHash(hash) + if found != nil { + // already have this hash + continue + } + counter += 1 + astat := new(gitpb.Stat) + astat.Hash = hash + ctime, err := cobol.GetTime(parts[2]) + allerr = errors.Join(allerr, err) + astat.Ctime = timestamppb.New(*ctime) + astat.Subject = parts[4] + astat.Type = gitpb.Stat_REMOTE + pb.Append(astat) + } + return counter, allerr +} + +/* +func lookupRefs(r *gitpb.Repo, remoteRefs *gitpb.Stats) error { + rname := remoteRefs.Name() + for stat := range remoteRefs.IterAll() { + log.Info("remote", rname, stat.Name) + } +} +*/ + +// returns err if anything changes or anything is wrong (todo: should these be different?) +func makeRefs(r *gitpb.Repo, remoteName string) error { + var counter int // inc if anything changes + fullname := filepath.Join(r.FullPath, ".git", remoteName+".refs.pb") + stats := gitpb.NewStats() + stats.Filename = fullname + err := config.ForceCreatePB(stats) + if err != nil { + return err + } + + var last *gitpb.Stat + for stat := range stats.IterAll() { + if last == nil { + last = stat + continue + } + if strings.Compare(stat.Hash, last.Hash) > 0 { + log.Info("Compare worked", stat.Hash, last.Hash, r.FullPath) + } else { + log.Info("Compare failed", stat.Hash, last.Hash, r.FullPath) + os.Remove(stats.Filename) + return errors.New("out of order") + } + if strings.Compare(stat.Hash, last.Hash) == 0 { + panic("was match") + } + last = stat + } + + // cmd := []string{"git", "show-ref"} // must use 'master' as queried from the git server + cmd := []string{"git", "ls-remote", remoteName} // must use 'master' as queried from the git server // GO has 250k remote refs + // cmd := []string{"git", "log", "-n", "100", makeFmts(), "origin/HEAD"} // HEAD is _NOT_ always set + 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 done int + var allnew []*gitpb.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(gitpb.Stat) + newstat.Type = gitpb.Stat_REMOTE + newstat.Hash = parts[0] + newstat.Name = parts[1] + if stats.Len() == 0 { + stats.Append(newstat) + continue + } + n, found := slices.BinarySearchFunc(stats.Stats, newstat, func(a, b *gitpb.Stat) int { + return strings.Compare(a.Hash, b.Hash) + }) + _ = n + + if n > stats.Len() { + log.Info("WTF n,len =", n, stats.Len()) + stats.Append(newstat) + continue + } + if n-1 < 0 { + log.Info("WTF n,len =", n, stats.Len()) + continue + } + + testfind := stats.Stats[n-1] + if testfind.Hash == newstat.Hash { + done += 1 + log.Info(counter, ticker, "N WAS RIGHT", n, found, newstat.Hash, "HASH", testfind.Hash) + panic("fucknuts") + } + if found { + done += 1 + teststat := stats.FindByHash(newstat.Hash) + if teststat == nil { + // log.Info(counter, ticker, "FOUND TEST STAT:", n, found, "HASH", newstat) + log.Printf("FOUND:%v %d/%d/%d %s %v\n", parts, done, counter, len(cmdout.Stdout), r.FullPath, teststat) + panic("fucknuts") + } + continue + } else { + teststat := stats.FindByHash(newstat.Hash) + if teststat != nil { + log.Printf("NOT FOUND:%v %d/%d/%d %s %v\n", parts, done, counter, len(cmdout.Stdout), r.FullPath, teststat) + // log.Info(counter, ticker, "NOT FOUND TEST STAT:", n, found, teststat, "HASH", newstat) + panic("fucknuts") + } + } + allnew = append(allnew, newstat) + + ticker += 1 + if ticker > 1000 { + log.Printf("TICKER:%v %d/%d/%d %s\n", parts, done, counter, len(cmdout.Stdout), r.FullPath) + ticker = 0 + break + /* + stats.Stats = append(stats.Stats, allnew...) + stats.SortByHash() + stats.Save() + log.Printf("TICKER:%v %d/%d/%d %s\n", parts, done, counter, len(cmdout.Stdout), r.FullPath) + return nil + */ + } + } + if counter > 0 { + stats.Stats = append(stats.Stats, allnew...) + stats.SortByHash() + stats.Save() + return errors.New(fmt.Sprintf("len(%d), ticker(%d) counter(%d) refs changed", stats.Len(), ticker, counter)) + } + return nil +} diff --git a/doVerifyNamespace.go b/doVerifyNamespace.go index cc42108..7f1d57f 100644 --- a/doVerifyNamespace.go +++ b/doVerifyNamespace.go @@ -13,6 +13,18 @@ import ( "go.wit.com/log" ) +// checks to see if the r.Namespace seems right +func doVerifyNamespace() (string, error) { + fixed := me.forge.RunOnRepos(me.forge.Repos, doCleanNamespace) + if fixed.Len() != 0 { + fixed = fixed.SortActual() + footer := me.forge.PrintDefaultTB(fixed) + me.forge.Repos.SaveVerbose() + return "changed namespaces: " + footer, nil + } + return "no namespaces changed", nil +} + func doCleanNamespace(r *gitpb.Repo) error { // check for GO repos gowork := env.Get("gopath") @@ -33,14 +45,19 @@ func doCleanNamespace(r *gitpb.Repo) error { return errors.Join(errors.New(s), err) } -// checks to see if the r.Namespace seems right -func doVerifyNamespace() (string, error) { - fixed := me.forge.RunOnRepos(me.forge.Repos, doCleanNamespace) - if fixed.Len() != 0 { - fixed = fixed.SortActual() - footer := me.forge.PrintDefaultTB(fixed) - me.forge.Repos.SaveVerbose() - return "changed namespaces: " + footer, nil +func doGitConfig(r *gitpb.Repo) error { + if r.Config == nil { + return errors.New(".git/config is nil") } - return "no namespaces changed", nil + + for _, rmote := range r.Config.Remotes { + if err := makeRefs(r, rmote.Name); err != nil { + return err + } + } + + // err = errors.New("namepace changed") + // s := fmt.Sprintf("old(%s), new(%s)", r.Namespace, newpath) + // return errors.Join(errors.New(s), err) + return nil } |
