From 34ac2291bc0d9321b078cf70f81684fc4d14e7e8 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 7 Oct 2025 20:43:43 -0500 Subject: make "Fix" subcommand --- argv.go | 7 ++- doAdd.go | 1 + doDev.go | 42 ------------- doFind.go | 197 ---------------------------------------------------------- doFix.go | 64 +++++++++++++++++++ doFix.urls.go | 89 ++++++++++++++++++++++++++ doPull.go | 79 +---------------------- find.go | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 360 insertions(+), 316 deletions(-) delete mode 100644 doFind.go create mode 100644 doFix.go create mode 100644 doFix.urls.go create mode 100644 find.go diff --git a/argv.go b/argv.go index 2979185..07a09f9 100644 --- a/argv.go +++ b/argv.go @@ -28,6 +28,7 @@ type args struct { Show *ShowCmd `arg:"subcommand:show" help:"print out things"` Dev *DevCmd `arg:"subcommand:dev" help:"features under development"` Add *EmptyCmd `arg:"subcommand:add" help:"Scan directores for git repos"` + Fixer *FixCmd `arg:"subcommand:fixer" help:"like in the movie"` All bool `arg:"--all" help:"whatever you are doing, do it all over"` Force bool `arg:"--force" help:"try to strong-arm things"` Verbose bool `arg:"--verbose" help:"show more output than usual"` @@ -58,6 +59,11 @@ type ShowCmd struct { Tag *TagCmd `arg:"subcommand:tag" help:"show git tags"` } +type FixCmd struct { + Urls bool `arg:"--urls" help:"check for changes in repo urls"` + Untracked bool `arg:"--untracked" help:"git untracked file list"` +} + func (ShowCmd) Examples() string { return "forge show dirty\nforge show repos --all" } @@ -93,7 +99,6 @@ type DevCmd struct { DeleteUser bool `arg:"--delete-user" help:"delete all user branches (checks for safety)"` BuildForge bool `arg:"--forge-rebuild" help:"download all the forge sources and rebuild forge"` URL string `arg:"--connect" help:"forge url"` - Untracked bool `arg:"--untracked" help:"git untracked file list"` Prune bool `arg:"--prune" help:"'git fetch --prune' everywhere"` } diff --git a/doAdd.go b/doAdd.go index ce819f5..49b4db6 100644 --- a/doAdd.go +++ b/doAdd.go @@ -21,6 +21,7 @@ func doAdd() error { } if found.Len() > 0 { + log.Info("This directory is already in a known repository") me.forge.PrintDefaultTB(found) return nil } diff --git a/doDev.go b/doDev.go index b828b9d..ba96466 100644 --- a/doDev.go +++ b/doDev.go @@ -6,7 +6,6 @@ package main import ( "errors" "fmt" - "path/filepath" "strings" "go.wit.com/lib/protobuf/forgepb" @@ -31,47 +30,6 @@ func doDev() (string, error) { return "go generate done", nil } - if argv.Dev.Untracked { - // show untracked files - // git ls-files --others - // git ls-files --others --exclude-standard - // git ls-files --others --ignored --exclude-standard - var count int - var filelist []string - found := gitpb.NewRepos() - for repo := range me.forge.Repos.IterByNamespace() { - var err error - r, err := repo.RunQuiet([]string{"git", "ls-files", "--others"}) - if err != nil { - continue - } - if len(r.Stdout) == 0 { - continue - } - count += len(r.Stdout) - for _, fname := range r.Stdout { - filelist = append(filelist, filepath.Join(repo.FullPath, fname)) - } - repo.State = log.Sprintf("%d files", len(r.Stdout)) - found.Append(repo) - } - me.forge.PrintHumanTable(found) - log.Info("") - log.Info("You have %d files that are untracked excluded git files. They are probably junk.", count) - log.Info("") - log.Info("You can remove these files with '--fix' or list them all with '--verbose'") - log.Info("") - if argv.Fix { - log.Info("todo: unlink them") - } - if argv.Verbose { - for _, fname := range filelist { - log.Info(fname) - } - } - return "", nil - - } if argv.Dev.Prune { // git fetch --prune for repo := range me.forge.Repos.IterByNamespace() { diff --git a/doFind.go b/doFind.go deleted file mode 100644 index f6fbbba..0000000 --- a/doFind.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2017-2025 WIT.COM Inc. All rights reserved. -// Use of this source code is governed by the GPL 3.0 - -package main - -import ( - "go.wit.com/lib/protobuf/gitpb" -) - -// this populates a slice of protobuf records representing each git repo -// var found []*gitpb.Repo -// -// so, it makes a subset of repos that are then used performing actions on -// -// by default, it adds every repo - -func doFind() *gitpb.Repos { - if argv.Show == nil { - return findAll() - } - - if argv.Show.Repo.Mine { - return findMine() - } - - if argv.Show.Dirty != nil { - return me.forge.FindDirty() - } - - return findAll() -} - -func findRepos() *gitpb.Repos { - if argv.Show == nil { - return findMine() - } - - if argv.Show.Dirty != nil { - return me.forge.FindDirty() - } - - if argv.Show.Repo == nil { - return findAll() - } - - if argv.Show.Repo.All { - return findAll() - } - - if argv.Show.Repo.Private { - return findPrivate() - } - - if argv.Show.Repo.Mine { - return findMine() - } - - if argv.Show.Repo.Favorites { - return findFavorites() - } - - if argv.Show.Repo.User { - return findUser() - } - - return findAll() -} - -func findPrivate() *gitpb.Repos { - found := gitpb.NewRepos() - for repo := range me.forge.Repos.IterByFullPath() { - if me.forge.Config.IsPrivate(repo.Namespace) { - found.AppendByFullPath(repo) - } - } - - return found -} - -// finds repos that are writable -func findMine() *gitpb.Repos { - found := gitpb.NewRepos() - - // log.Printf("get mine %s\n", me.forge.GetGoSrc()) - for repo := range me.forge.Repos.IterByFullPath() { - - if me.forge.Config.IsWritable(repo.Namespace) { - found.AppendByFullPath(repo) - } - } - return found -} - -// finds repos the user has marked as favorites in the forge .config -func findFavorites() *gitpb.Repos { - found := gitpb.NewRepos() - - // log.Printf("get favorites %s\n", me.forge.GetGoSrc()) - for repo := range me.forge.Repos.IterByFullPath() { - - if me.forge.Config.IsFavorite(repo.Namespace) { - found.AppendByFullPath(repo) - } - } - return found -} - -func findAll() *gitpb.Repos { - found := gitpb.NewRepos() - for repo := range me.forge.Repos.IterByFullPath() { - found.AppendByFullPath(repo) - } - return found -} - -func find50() *gitpb.Repos { - count := 0 - found := gitpb.NewRepos() - for repo := range me.forge.Repos.IterByFullPath() { - found.AppendByFullPath(repo) - if count > 50 { - return found - } - count += 1 - } - return found -} - -func findUser() *gitpb.Repos { - found := gitpb.NewRepos() - - for repo := range me.forge.Repos.IterByFullPath() { - if repo.GetCurrentBranchName() == repo.GetUserBranchName() { - found.AppendByFullPath(repo) - } - } - return found -} - -func findPublishable() *gitpb.Repos { - found := gitpb.NewRepos() - - for repo := range me.forge.Repos.IterByFullPath() { - if repo.GetTargetVersion() == "" { - continue - } - found.AppendByFullPath(repo) - } - return found -} - -func findReposWithPatches() *gitpb.Repos { - found := gitpb.NewRepos() - - for repo := range me.forge.Repos.IterByFullPath() { - if repo.IsDirty() { - // always add dirty branches - found.AppendByFullPath(repo) - continue - } - if repo.GetUserVersion() == "" || repo.GetUserVersion() == "uerr" { - // skip anything without a user branch - continue - } - if repo.GetUserVersion() != repo.GetDevelVersion() { - found.AppendByFullPath(repo) - continue - } - - // ignore read-only repos for checks below here - if me.forge.Config.IsReadOnly(repo.Namespace) { - continue - } - - // show anything that differs between 'devel' & 'master' branches - if repo.GetDevelVersion() != repo.GetMasterVersion() { - // this repo.State code isn't great, but it got me here quickly - // I'll defend my code by saying it's faster for me if I do dumb things - // sometimes and fix them later. Probably some employee will have to - // fix this. if that is the case I owe you lunch. or stock options - if repo.State == "DEVEL behind MASTER" { - // log.Info("repo state", repo.FullPath, repo.State) - continue - } - found.AppendByFullPath(repo) - continue - } - - // this is an old test to see if the current 'last tag' is accurate and should be removed - if repo.GetLastTag() != repo.GetMasterVersion() { - found.AppendByFullPath(repo) - repo.FindLastTag() - continue - } - } - return found -} diff --git a/doFix.go b/doFix.go new file mode 100644 index 0000000..eb9df32 --- /dev/null +++ b/doFix.go @@ -0,0 +1,64 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "path/filepath" + + "go.wit.com/lib/protobuf/gitpb" + "go.wit.com/log" +) + +// is every repo on the devel branch? +func doFix() (string, error) { + if argv.Fixer.Urls { + err := doFixUrls() + return "", err + } + if argv.Fixer.Untracked { + return doRemoveUntrackedFiles() + } + return "", nil +} + +func doRemoveUntrackedFiles() (string, error) { + // show untracked files + // git ls-files --others + // git ls-files --others --exclude-standard + // git ls-files --others --ignored --exclude-standard + var count int + var filelist []string + found := gitpb.NewRepos() + for repo := range me.forge.Repos.IterByNamespace() { + var err error + r, err := repo.RunQuiet([]string{"git", "ls-files", "--others"}) + if err != nil { + continue + } + if len(r.Stdout) == 0 { + continue + } + count += len(r.Stdout) + for _, fname := range r.Stdout { + filelist = append(filelist, filepath.Join(repo.FullPath, fname)) + } + repo.State = log.Sprintf("%d files", len(r.Stdout)) + found.Append(repo) + } + me.forge.PrintHumanTable(found) + log.Info("") + log.Info("You have %d files that are untracked excluded git files. They are probably junk.", count) + log.Info("") + log.Info("You can remove these files with '--fix' or list them all with '--verbose'") + log.Info("") + if argv.Force { + log.Info("todo: unlink them") + } + if argv.Verbose { + for _, fname := range filelist { + log.Info(fname) + } + } + return "use --force to actually remove them", nil +} diff --git a/doFix.urls.go b/doFix.urls.go new file mode 100644 index 0000000..e516107 --- /dev/null +++ b/doFix.urls.go @@ -0,0 +1,89 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "strings" + + "go.wit.com/lib/protobuf/gitpb" + "go.wit.com/log" +) + +func updateURL(repo *gitpb.Repo) bool { + found := me.forge.Repos.FindByNamespace(repo.Namespace) + if found == nil { + return false + } + if repo.URL == found.URL { + return false + } + cmd := []string{"git", "remote", "set-url", "origin", repo.URL} + found.URL = repo.URL + if argv.Fix { + log.Infof("%s update URL to %v\n", found.URL, cmd) + found.Run(cmd) + return true + } + log.Infof("add --fix to update %s with %v\n", found.URL, cmd) + return true +} + +func doFixUrls() error { + submit := me.forge.PrepareCheckRepos() + updatepb, regPB, err := submit.HttpPost(myServer(), "check") + if err != nil { + log.Info("err =", err) + } + if regPB == nil { + log.Info("regPB==nil") + } + if updatepb == nil { + log.Info("server sent nil back") + return err + } + var count int + // log.Infof("pull check %s pb.Len()=%d client.Len()=%d server.Len()=%d err=%v\n", regPB.URL, updatepb.Len(), regPB.ClientDataLen, regPB.ServerDataLen, err) + log.Infof("pull check pb.Len()=%d\n", updatepb.Len()) + updatecheck := gitpb.NewRepos() + for repo := range updatepb.IterAll() { + if updateURL(repo) { + count += 1 + } + if repo.Namespace == "" { + log.Info("forge sent back empty namespace", repo) + continue + } + found := me.forge.Repos.FindByNamespace(repo.Namespace) + if found == nil { + log.Info("you don't have namespace?", repo.Namespace) + continue + } + if !strings.HasPrefix(found.Namespace, "go.wit.com") { + continue + } + updatecheck.Append(repo) + // spew.Dump(repo) + // me.sh.GoodExit("") + /* + found, _ := needToUpdateRepo(repo) + if found == nil { + continue + } + if !argv.Force { + continue + } + // found.RunVerbose([]string{"git", "pull", "origin", found.GetMasterBranchName()}) + found.CheckoutMaster() + found.GitPull() + found.ReloadCheck() + found.GitPull() + if count > 10 { + break + } + count += 1 + */ + } + me.forge.PrintPullTable(updatecheck) + return nil +} diff --git a/doPull.go b/doPull.go index 17328fe..dd837b9 100644 --- a/doPull.go +++ b/doPull.go @@ -4,7 +4,6 @@ package main import ( - "strings" "time" "go.wit.com/lib/config" @@ -14,25 +13,6 @@ import ( "go.wit.com/log" ) -func updateURL(repo *gitpb.Repo) bool { - found := me.forge.Repos.FindByNamespace(repo.Namespace) - if found == nil { - return false - } - if repo.URL == found.URL { - return false - } - cmd := []string{"git", "remote", "set-url", "origin", repo.URL} - found.URL = repo.URL - if argv.Fix { - log.Infof("%s update URL to %v\n", found.URL, cmd) - found.Run(cmd) - return true - } - log.Infof("add --fix to update %s with %v\n", found.URL, cmd) - return true -} - // returns true if 'git pull' should be run func needToUpdateRepo(repo *gitpb.Repo) (*gitpb.Repo, error) { if repo.Tags == nil { @@ -88,62 +68,8 @@ func doPull() error { return nil } if argv.Pull.Check != nil { - submit := me.forge.PrepareCheckRepos() - updatepb, regPB, err := submit.HttpPost(myServer(), "check") - if err != nil { - log.Info("err =", err) - } - if regPB == nil { - log.Info("regPB==nil") - } - if updatepb == nil { - log.Info("server sent nil back") - return err - } - var count int - // log.Infof("pull check %s pb.Len()=%d client.Len()=%d server.Len()=%d err=%v\n", regPB.URL, updatepb.Len(), regPB.ClientDataLen, regPB.ServerDataLen, err) - log.Infof("pull check pb.Len()=%d\n", updatepb.Len()) - updatecheck := gitpb.NewRepos() - for repo := range updatepb.IterAll() { - if updateURL(repo) { - count += 1 - } - if repo.Namespace == "" { - log.Info("forge sent back empty namespace", repo) - continue - } - found := me.forge.Repos.FindByNamespace(repo.Namespace) - if found == nil { - log.Info("you don't have namespace?", repo.Namespace) - continue - } - if !strings.HasPrefix(found.Namespace, "go.wit.com") { - continue - } - updatecheck.Append(repo) - // spew.Dump(repo) - // me.sh.GoodExit("") - /* - found, _ := needToUpdateRepo(repo) - if found == nil { - continue - } - if !argv.Force { - continue - } - // found.RunVerbose([]string{"git", "pull", "origin", found.GetMasterBranchName()}) - found.CheckoutMaster() - found.GitPull() - found.ReloadCheck() - found.GitPull() - if count > 10 { - break - } - count += 1 - */ - } - me.forge.PrintPullTable(updatecheck) - return nil + err := doFixUrls() + return err } if argv.Pull.List != nil { found := gitpb.NewRepos() @@ -190,6 +116,7 @@ func doPull() error { } } me.forge.PrintPullTable(repoerr) + me.forge.PrintForgedTable(repoerr) me.sh.GoodExit("git pull done") } diff --git a/find.go b/find.go new file mode 100644 index 0000000..f6fbbba --- /dev/null +++ b/find.go @@ -0,0 +1,197 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "go.wit.com/lib/protobuf/gitpb" +) + +// this populates a slice of protobuf records representing each git repo +// var found []*gitpb.Repo +// +// so, it makes a subset of repos that are then used performing actions on +// +// by default, it adds every repo + +func doFind() *gitpb.Repos { + if argv.Show == nil { + return findAll() + } + + if argv.Show.Repo.Mine { + return findMine() + } + + if argv.Show.Dirty != nil { + return me.forge.FindDirty() + } + + return findAll() +} + +func findRepos() *gitpb.Repos { + if argv.Show == nil { + return findMine() + } + + if argv.Show.Dirty != nil { + return me.forge.FindDirty() + } + + if argv.Show.Repo == nil { + return findAll() + } + + if argv.Show.Repo.All { + return findAll() + } + + if argv.Show.Repo.Private { + return findPrivate() + } + + if argv.Show.Repo.Mine { + return findMine() + } + + if argv.Show.Repo.Favorites { + return findFavorites() + } + + if argv.Show.Repo.User { + return findUser() + } + + return findAll() +} + +func findPrivate() *gitpb.Repos { + found := gitpb.NewRepos() + for repo := range me.forge.Repos.IterByFullPath() { + if me.forge.Config.IsPrivate(repo.Namespace) { + found.AppendByFullPath(repo) + } + } + + return found +} + +// finds repos that are writable +func findMine() *gitpb.Repos { + found := gitpb.NewRepos() + + // log.Printf("get mine %s\n", me.forge.GetGoSrc()) + for repo := range me.forge.Repos.IterByFullPath() { + + if me.forge.Config.IsWritable(repo.Namespace) { + found.AppendByFullPath(repo) + } + } + return found +} + +// finds repos the user has marked as favorites in the forge .config +func findFavorites() *gitpb.Repos { + found := gitpb.NewRepos() + + // log.Printf("get favorites %s\n", me.forge.GetGoSrc()) + for repo := range me.forge.Repos.IterByFullPath() { + + if me.forge.Config.IsFavorite(repo.Namespace) { + found.AppendByFullPath(repo) + } + } + return found +} + +func findAll() *gitpb.Repos { + found := gitpb.NewRepos() + for repo := range me.forge.Repos.IterByFullPath() { + found.AppendByFullPath(repo) + } + return found +} + +func find50() *gitpb.Repos { + count := 0 + found := gitpb.NewRepos() + for repo := range me.forge.Repos.IterByFullPath() { + found.AppendByFullPath(repo) + if count > 50 { + return found + } + count += 1 + } + return found +} + +func findUser() *gitpb.Repos { + found := gitpb.NewRepos() + + for repo := range me.forge.Repos.IterByFullPath() { + if repo.GetCurrentBranchName() == repo.GetUserBranchName() { + found.AppendByFullPath(repo) + } + } + return found +} + +func findPublishable() *gitpb.Repos { + found := gitpb.NewRepos() + + for repo := range me.forge.Repos.IterByFullPath() { + if repo.GetTargetVersion() == "" { + continue + } + found.AppendByFullPath(repo) + } + return found +} + +func findReposWithPatches() *gitpb.Repos { + found := gitpb.NewRepos() + + for repo := range me.forge.Repos.IterByFullPath() { + if repo.IsDirty() { + // always add dirty branches + found.AppendByFullPath(repo) + continue + } + if repo.GetUserVersion() == "" || repo.GetUserVersion() == "uerr" { + // skip anything without a user branch + continue + } + if repo.GetUserVersion() != repo.GetDevelVersion() { + found.AppendByFullPath(repo) + continue + } + + // ignore read-only repos for checks below here + if me.forge.Config.IsReadOnly(repo.Namespace) { + continue + } + + // show anything that differs between 'devel' & 'master' branches + if repo.GetDevelVersion() != repo.GetMasterVersion() { + // this repo.State code isn't great, but it got me here quickly + // I'll defend my code by saying it's faster for me if I do dumb things + // sometimes and fix them later. Probably some employee will have to + // fix this. if that is the case I owe you lunch. or stock options + if repo.State == "DEVEL behind MASTER" { + // log.Info("repo state", repo.FullPath, repo.State) + continue + } + found.AppendByFullPath(repo) + continue + } + + // this is an old test to see if the current 'last tag' is accurate and should be removed + if repo.GetLastTag() != repo.GetMasterVersion() { + found.AppendByFullPath(repo) + repo.FindLastTag() + continue + } + } + return found +} -- cgit v1.2.3