diff options
| -rw-r--r-- | argv.go | 21 | ||||
| -rw-r--r-- | doReload.go | 263 | ||||
| -rw-r--r-- | doStats.go | 57 |
3 files changed, 305 insertions, 36 deletions
@@ -65,16 +65,17 @@ type VerifyCmd struct { } type StatsCmd struct { - All bool `arg:"--all" help:"update all stats"` - CheckRefs bool `arg:"--check-refs" help:"load & check refs"` - CheckRemote bool `arg:"--check-remote" help:"load & check remote log"` - CheckRemoteRefs bool `arg:"--check-remote-refs" help:"load & check remote refs"` - UpdateRefs bool `arg:"--update" help:"update refs"` - UpdateRemote bool `arg:"--update-remote" help:"update remote log"` - UpdateRemoteRefs bool `arg:"--update-remote-refs" help:"update remote refs"` - Sizes bool `arg:"--sizes" help:"show sizes"` - List bool `arg:"--list" help:"list all stats"` - Repo string `arg:"--repo" help:"lookup this repo namespace"` + All *EmptyCmd `arg:"subcommand:all" help:"run on all the repos"` + Reload bool `arg:"--reload" help:"reload refs"` + CheckRefs bool `arg:"--check-refs" help:"load & check refs"` + CheckRemote bool `arg:"--check-remote" help:"load & check remote log"` + CheckRemoteRefs bool `arg:"--check-remote-refs" help:"load & check remote refs"` + UpdateRefs bool `arg:"--update-refs" help:"update refs"` + UpdateRemote bool `arg:"--update-remote" help:"update remote log"` + UpdateRemoteRefs bool `arg:"--update-remote-refs" help:"update remote refs"` + Sizes bool `arg:"--sizes" help:"show sizes"` + List bool `arg:"--list" help:"list all stats"` + Repo string `arg:"--repo" help:"lookup this repo namespace"` } func (ShowCmd) Examples() string { diff --git a/doReload.go b/doReload.go new file mode 100644 index 0000000..ac57d3c --- /dev/null +++ b/doReload.go @@ -0,0 +1,263 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "errors" + "path/filepath" + "slices" + "strings" + + "go.wit.com/lib/env" + "go.wit.com/lib/protobuf/gitpb" + "go.wit.com/log" +) + +func searchRemote(remote *gitpb.Stats, ref *gitpb.Stat) *gitpb.Stat { + n, found := slices.BinarySearchFunc(remote.Stats, ref, func(a, b *gitpb.Stat) int { + return strings.Compare(a.Hash, b.Hash) + }) + + if found { + foundref := remote.Stats[n] + if ref.Hash != foundref.Hash { + log.Info("Something went wrong", ref.Hash, foundref.Hash) + return nil + } + return foundref + } + log.Printf("searchRemote(nil) len(%d) NOT FOUND: %v\n", remote.Len(), ref) + for remoteref := range remote.IterAll() { + if remoteref.Hash == ref.Hash { + log.Printf("searchRemote(nil) len(%d) FOUND: %v\n", remote.Len(), remoteref) + return remoteref + } + if remoteref.TreeHash == ref.Hash { + log.Printf("searchRemote(nil) len(%d) FOUND: %v\n", remote.Len(), remoteref) + return remoteref + } + if remoteref.TagHash == ref.Hash { + log.Printf("searchRemote(nil) len(%d) FOUND: %v\n", remote.Len(), remoteref) + return remoteref + } + // log.Printf("searchRemote(nil) len(%d) NO MATCH: %s %s %s\n", remote.Len(), remoteref.Hash, remoteref.TreeHash, "nope") + } + log.Printf("searchRemote(nil) len(%d) NOT FOUND: %v\n", remote.Len(), ref) + return nil +} + +// processes stats.Tags in the remote refs .pb +// tries to find the tags in the local refs.pb file +func doMapTags(r *gitpb.Repo) (*gitpb.Stats, error) { + var allerr error + stats, err := r.LoadRefs() + if err != nil { + return stats, err + } + + var worked bool + // look through the Tags + for _, rmote := range r.Config.Remotes { + remotestats, err := r.LoadRemote(rmote.Name) + if err != nil { + return stats, err + } + if remotestats.Len() == 0 { + // need to init remote stats + return stats, errors.New("run dev stats --update-remote") + } + for ref := range remotestats.IterAll() { + if ref.Tags == "" { + continue + } + line := strings.TrimSpace(ref.Tags) + line = strings.TrimPrefix(line, "(") + line = strings.TrimSuffix(line, ")") + for _, part := range strings.Split(line, ",") { + var found bool + var tag string + part = strings.TrimSpace(part) + parts := strings.Split(part, " ") + if (len(parts) == 2) && (parts[0] == "tag:") { + tag = filepath.Join("refs/tags", parts[1]) + } else if len(parts) == 1 { + tag = parts[0] + if strings.HasPrefix(tag, rmote.Name+"/") { + tag = filepath.Join("refs/remotes", tag) + } else { + tag = filepath.Join("refs/heads", tag) + } + } else if len(parts) == 3 { + if parts[0] == "HEAD" { + tag = filepath.Join("refs/heads", parts[2]) + } + } else { + log.Printf("hash(%s) could not find tag: (%v)\n", ref.Hash, parts) + } + for tagref := range stats.IterAll() { + if tagref.Name == tag { + found = true + if tagref.Hash == "" { + log.Printf("Found taghash(%s) hash(%s) has tags: %s (%s)\n", tagref.TagHash, ref.Hash, part, tag) + tagref.Hash = ref.Hash + worked = true + } else { + if tagref.Hash != ref.Hash { + log.Printf("EVEN WEIRDER ERROR: taghash(%s) hash(%s) has tags: %s (%s)\n", tagref.TagHash, ref.Hash, part, tag) + } + } + } + } + if !found { + s := log.Sprintf("ref.hash(%s) could not find tag(%s) in remote. part=(%s)", ref.Hash, tag, part) + log.Info(s) + allerr = errors.New(s) + } + } + } + } + if worked { + stats.Save() + return stats, errors.New("New tags found!") + } + return stats, allerr +} + +func remoteDups(all *gitpb.Stats) error { + var dups []*gitpb.Stat + last := new(gitpb.Stat) + for ref := range all.IterAll() { + if ref.Hash == last.Hash { + dups = append(dups, ref) + } else { + last = ref + } + } + s := log.Sprintf("found %d dups", len(dups)) + log.Info(s, dups) + if len(dups) == 0 { + return nil + } + return errors.New(s) +} + +func makeAllGitStats(r *gitpb.Repo) error { + var err error + + // make all the remote files before the local files + for _, rmote := range r.Config.Remotes { + morestats, err := r.MakeRemote(rmote.Name) + if err != nil { + return errors.Join(err, errors.New("MakeRemote() failed")) + } + if env.True("resort") { + morestats.SaveByHash() + return errors.New("stats should have been resorted and saved") + } + + remoterefs, err := r.MakeRemoteRefs(rmote.Name) + if err != nil { + return errors.Join(err, errors.New("MakeRemoteRefs() failed")) + } + if env.True("resort") { + remoterefs.SaveByHash() + return errors.New("stats should have been resorted and saved") + } + } + + // make the local refs pb + stats, err := r.LoadRefs() + if err != nil { + return errors.Join(err, errors.New("r.LoadRefs() failed")) + } + + if env.True("resort") { + stats.SaveByHash() + log.Info("stats should have been resorted and saved") + return nil + } + + err = r.UpdateRefs(stats) + if err != nil { + return errors.Join(err, errors.New("r.UpdateRefs() failed")) + } + return nil +} + +func doReload(r *gitpb.Repo) error { + err := makeAllGitStats(r) + if err != nil { + return err + } + + stats, err := doMapTags(r) + if err != nil { + return errors.Join(err, errors.New("doMapTags() failed")) + } + + // * remotes duplicates + // * sets fields that might have not been set before + // this probably should go away once the other code works + for _, rmote := range r.Config.Remotes { + remotestats, err := r.LoadRemote(rmote.Name) + if err != nil { + return err + } + var save bool + remoteDups(remotestats) + for ref := range stats.IterAll() { + found := searchRemote(remotestats, ref) + if found == nil { + log.Printf("len(%d) NOT FOUND: %v\n", remotestats.Len(), ref) + return nil + } + if ref.SanitizedSubject != found.SanitizedSubject { + log.Info("subject", ref.SanitizedSubject, found.SanitizedSubject) + ref.SanitizedSubject = found.SanitizedSubject + save = true + } + if (ref.AuthorTime == nil) || (ref.AuthorTime.AsTime() != found.AuthorTime.AsTime()) { + log.Info("author time", ref.AuthorTime, found.AuthorTime) + ref.AuthorTime = found.AuthorTime + save = true + } + if (ref.CommitTime == nil) || (ref.CommitTime.AsTime() != found.CommitTime.AsTime()) { + log.Info("commit time", ref.CommitTime, found.CommitTime) + ref.CommitTime = found.CommitTime + save = true + } + } + if save { + stats.Save() + return errors.New("some things were updated") + } + } + + /* + sort.Slice(stats, func(i, j int) bool { + return gitpb. + }) + */ + + // sorts refs by version. tries, but the sort doesn't quite work yet for some reason + // saves the sorted file + wasSorted := stats.SortVersion() + if !wasSorted { + newstats := gitpb.NewStats() + for _, ref := range stats.Stats { + newstats.Clone(ref) + } + newstats.Filename = stats.Filename + newstats.Save() + } + footer := stats.PrintTableLimit(2) + log.Info("doReload() footer:", footer) + + /* + footer := stats.PrintTable() + log.Info("doReload() footer:", footer) + */ + + return nil +} @@ -21,6 +21,19 @@ import ( // c09c90d0a931888862262a6ed3753eed0af4ddca refs/pull/8/head func doStats(cmd *StatsCmd) (string, error) { + if cmd.All != nil { + fixed := me.forge.RunOnRepos(me.forge.Repos, doReload) + 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 + } + repo := workingDirToRepo() if repo == nil { return "no repo", errors.New("working dir isn't a repo I know about") @@ -46,6 +59,11 @@ func doStats(cmd *StatsCmd) (string, error) { return "remote refs table", nil } + if cmd.Reload { + err := doReload(repo) + return "doReload()", err + } + if cmd.CheckRefs { err := doCheckRefs(repo) return "checked refs", err @@ -79,19 +97,6 @@ func doStats(cmd *StatsCmd) (string, error) { if cmd.List { } - if cmd.All { - fixed := me.forge.RunOnRepos(me.forge.Repos, doUpdateRefs) - 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 - } - return "do what?", nil } @@ -111,19 +116,6 @@ func doCheckRefs(r *gitpb.Repo) error { return nil } -func doUpdateRefs(r *gitpb.Repo) error { - stats, err := r.LoadRefs() - if err != nil { - return err - } - - footer := stats.PrintTableLimit(2) - log.Info("stats footer:", footer) - - err = r.UpdateRefs(stats) - return err -} - func doCheckRemote(r *gitpb.Repo) error { for _, rmote := range r.Config.Remotes { morestats, err := r.MakeRemote(rmote.Name) @@ -158,6 +150,19 @@ func doCheckRemoteRefs(r *gitpb.Repo) error { return nil } +func doUpdateRefs(r *gitpb.Repo) error { + stats, err := r.LoadRefs() + if err != nil { + return err + } + + footer := stats.PrintTableLimit(2) + log.Info("stats footer:", footer) + + err = r.UpdateRefs(stats) + return err +} + func doUpdateRemote(r *gitpb.Repo) error { for _, rmote := range r.Config.Remotes { err := r.UpdateRemote(rmote.Name) |
