summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--argv.go21
-rw-r--r--doReload.go263
-rw-r--r--doStats.go57
3 files changed, 305 insertions, 36 deletions
diff --git a/argv.go b/argv.go
index 4bad664..a2e80ea 100644
--- a/argv.go
+++ b/argv.go
@@ -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
+}
diff --git a/doStats.go b/doStats.go
index 1988970..e932fc1 100644
--- a/doStats.go
+++ b/doStats.go
@@ -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)