From 6c958fb9c135c2e06322e0065bcdb8e4f5f4b0b2 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 15 Oct 2025 13:42:14 -0500 Subject: housekeeping + new user behavior --- config.common.go | 337 -------------------------------------------------- config.go | 18 ++- forgeConfig.Common.go | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++ init.go | 29 +++-- run.go | 2 +- 5 files changed, 367 insertions(+), 356 deletions(-) delete mode 100644 config.common.go create mode 100644 forgeConfig.Common.go diff --git a/config.common.go b/config.common.go deleted file mode 100644 index 8bc009d..0000000 --- a/config.common.go +++ /dev/null @@ -1,337 +0,0 @@ -package forgepb - -/* - lookup settings for a particular *gitpb.Repo or namespace string - - user settings are configured in ~/.config/forge/forge.text - - // searchs by string - Configs.IsReadOnly(path) // user can't push commits - Configs.IsWritable(path) // the opposite, but maybe different so I put both here - - IsPrivate(repo) // repo can't be published to the pkg.go.dev system - DebName() // for 'zookeeper' returns 'zookeeper-go' - - This code is practical, not perfect -*/ - -import ( - "path/filepath" - "strings" - - "go.wit.com/lib/protobuf/gitpb" -) - -// move away from IsReadOnly. Only use repo.Namespace -func (f *Forge) IsWritable(repo *gitpb.Repo) bool { - if f.Config.IsWritable(repo.Namespace) { - return true - } - // if f.Config.IsWritable(repo.FullPath) { - // return true - // } - // if !f.Config.IsWritable(repo.GetNamespace()) { - // return true - // } - return false -} - -// returns true if namespace is readonly() -// will attempt to match IsWritable("foo") against anything ending in "foo" -func (fc *ForgeConfigs) IsReadOnly(namespace string) bool { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == namespace { - // exact namespace match - if r.Writable { - return false - } - if r.ReadOnly { - return true - } - // private is assumed to be r/w unless above is specifically set - if r.Private { - return false - } - } - // if namespace == "foo" will return false if "go.wit.com/apps/foo" is Writable - base := filepath.Base(r.Namespace) - if base == namespace { - if r.Writable { - return false - } - } - // search for potential dir matches - if r.Directory { - // test the dir - if strings.HasPrefix(namespace, r.Namespace) { - match = r - } - } - } - - if match == nil { - // log.Info("did not match in IsReadOnly()", namespace) - return true - } - - // take the settings from the directory match - if match.Writable { - return false - } - if match.ReadOnly { - return true - } - // private is assumed to be r/w unless above is specifically set - if match.Private { - return false - } - - // always assume readonly - return true -} - -// returns the deb package name -// this let's you check a git tag version against a package .deb version -// allows namespace's to not need to match the .deb name -// this is important in lots of cases! It is normal and happens often enough. -func (fc *ForgeConfigs) DebName(namespace string) string { - // get "zookeeper" from "go.wit.com/apps/zookeeper" - normalBase := filepath.Base(namespace) - - all := fc.All() - for all.Scan() { - r := all.Next() - if r.Namespace == namespace { - // returns "zookeeper-go" for "go.wit.com/apps/zookeeper" - if r.DebName != "" { - // log.Info("FOUND DebName", r.DebName) - return r.DebName - } else { - return normalBase - } - } - } - return normalBase -} - -// a work in progress -func (f *Forge) IsPrivate(repo *gitpb.Repo) bool { - namespace := repo.GetNamespace() - if namespace == "" { - // assume true - return true - } - - return f.Config.IsPrivate(namespace) -} - -// is this a non-publishable repo? -// matches package names from apt -// -// IsPrivate("foo") will match anything in the config file ending in "foo" -// -// IsPrivate("go.foo.com/jcarr/foo") returns true if private -// IsPrivate("foo") also returns true if "go.bar.com/jcarr/foo" is private -func (fc *ForgeConfigs) IsPrivate(thing string) bool { - var match *ForgeConfig - - // sort by path means the simple 'match' logic - // here works in the sense the last directory match - // is the one that is used - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - // if private is set here, then ok, otherwise - // still check if a Directory match exists - if r.Private { - return true - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.Private { - return true - } - } - // check to see if IsPrivate("foo") - // search for potential dir matches - if r.Directory { - // test the dir - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - // log.Info("did not match in IsPrivate()", thing) - return false - } - - // otherwise, assume not private - return match.Private -} - -// IsFavorite() -- fun option for the config -// file that lets you set things as favorites -// so you can just go-clone a bunch of common things -// on a new box or after you reset/delete your ~/go/src dir -func (fc *ForgeConfigs) IsFavorite(thing string) bool { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - if r.Favorite { - return true - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.Favorite { - return true - } - } - if r.Directory { - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - return false - } - - return match.Favorite -} - -// IsWritable() checks your .config/forge/ settings -// looks for an exact match, then -// looks for a directory match -func (fc *ForgeConfigs) IsWritable(thing string) bool { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - if r.Writable { - return true - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.Writable { - return true - } - } - if r.Directory { - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - return false - } - - return match.Writable -} - -// allows custom user branch names in the forge config -func (fc *ForgeConfigs) FindUserBranch(thing string) string { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - if r.UserBranchName != "" { - return r.UserBranchName - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.UserBranchName != "" { - return r.UserBranchName - } - } - if r.Directory { - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - return "" - } - - return match.UserBranchName -} - -// allows custom devel branch names in the forge config -func (fc *ForgeConfigs) FindDevelBranch(thing string) string { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - if r.DevelBranchName != "" { - return r.DevelBranchName - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.DevelBranchName != "" { - return r.DevelBranchName - } - } - if r.Directory { - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - return "" - } - - return match.DevelBranchName -} - -// allows custom devel branch names in the forge config -func (fc *ForgeConfigs) FindMasterBranch(thing string) string { - var match *ForgeConfig - - all := fc.All() // get the list of repos - for all.Scan() { - r := all.Next() - if r.Namespace == thing { - if r.MasterBranchName != "" { - return r.MasterBranchName - } - } - base := filepath.Base(r.Namespace) - if base == thing { - if r.MasterBranchName != "" { - return r.MasterBranchName - } - } - if r.Directory { - if strings.HasPrefix(thing, r.Namespace) { - match = r - } - } - } - if match == nil { - return "" - } - - return match.MasterBranchName -} diff --git a/config.go b/config.go index 600becd..5bdc770 100644 --- a/config.go +++ b/config.go @@ -135,14 +135,16 @@ func loadStdConfig() *ForgeConfigs { homeDir, _ := os.UserHomeDir() cfgdir := filepath.Join(homeDir, ".config/forge") - os.MkdirAll(cfgdir, os.ModePerm) - cfg.HomeDir = cfgdir - cfg.ReposDir = filepath.Join(homeDir, "go/src") // todo: check working directory + os.MkdirAll(cfgdir, 0755) + cfg.ReposPB = filepath.Join(cfgdir, "repos.pb") cfg.PatchPB = filepath.Join(cfgdir, "patches.pb") cfg.ForgeURL = "http://forge.wit.com/" + cfg.ReposDir = filepath.Join(homeDir, "go/src") // todo: check working directory + os.MkdirAll(cfg.ReposDir, 0755) + cfg.addSampleConfigs() cfg.DumpENV() config.SetChanged("forge", true) @@ -153,6 +155,9 @@ func loadStdConfig() *ForgeConfigs { log.Info("config save error:", err) os.Exit(-1) } + log.Info("---- ----") + log.Info("---- Welcome to forge!!! ----") + log.Info("---- ----") return cfg } @@ -170,11 +175,4 @@ func (cfg *ForgeConfigs) addSampleConfigs() { newc.Private = true newc.Directory = true cfg.Append(newc) - - newc = new(ForgeConfig) - newc.GoPath = "priv.wit.com/corp" - newc.Writable = true - newc.Private = true - newc.Directory = true - cfg.Append(newc) } diff --git a/forgeConfig.Common.go b/forgeConfig.Common.go new file mode 100644 index 0000000..8bc009d --- /dev/null +++ b/forgeConfig.Common.go @@ -0,0 +1,337 @@ +package forgepb + +/* + lookup settings for a particular *gitpb.Repo or namespace string + + user settings are configured in ~/.config/forge/forge.text + + // searchs by string + Configs.IsReadOnly(path) // user can't push commits + Configs.IsWritable(path) // the opposite, but maybe different so I put both here + + IsPrivate(repo) // repo can't be published to the pkg.go.dev system + DebName() // for 'zookeeper' returns 'zookeeper-go' + + This code is practical, not perfect +*/ + +import ( + "path/filepath" + "strings" + + "go.wit.com/lib/protobuf/gitpb" +) + +// move away from IsReadOnly. Only use repo.Namespace +func (f *Forge) IsWritable(repo *gitpb.Repo) bool { + if f.Config.IsWritable(repo.Namespace) { + return true + } + // if f.Config.IsWritable(repo.FullPath) { + // return true + // } + // if !f.Config.IsWritable(repo.GetNamespace()) { + // return true + // } + return false +} + +// returns true if namespace is readonly() +// will attempt to match IsWritable("foo") against anything ending in "foo" +func (fc *ForgeConfigs) IsReadOnly(namespace string) bool { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == namespace { + // exact namespace match + if r.Writable { + return false + } + if r.ReadOnly { + return true + } + // private is assumed to be r/w unless above is specifically set + if r.Private { + return false + } + } + // if namespace == "foo" will return false if "go.wit.com/apps/foo" is Writable + base := filepath.Base(r.Namespace) + if base == namespace { + if r.Writable { + return false + } + } + // search for potential dir matches + if r.Directory { + // test the dir + if strings.HasPrefix(namespace, r.Namespace) { + match = r + } + } + } + + if match == nil { + // log.Info("did not match in IsReadOnly()", namespace) + return true + } + + // take the settings from the directory match + if match.Writable { + return false + } + if match.ReadOnly { + return true + } + // private is assumed to be r/w unless above is specifically set + if match.Private { + return false + } + + // always assume readonly + return true +} + +// returns the deb package name +// this let's you check a git tag version against a package .deb version +// allows namespace's to not need to match the .deb name +// this is important in lots of cases! It is normal and happens often enough. +func (fc *ForgeConfigs) DebName(namespace string) string { + // get "zookeeper" from "go.wit.com/apps/zookeeper" + normalBase := filepath.Base(namespace) + + all := fc.All() + for all.Scan() { + r := all.Next() + if r.Namespace == namespace { + // returns "zookeeper-go" for "go.wit.com/apps/zookeeper" + if r.DebName != "" { + // log.Info("FOUND DebName", r.DebName) + return r.DebName + } else { + return normalBase + } + } + } + return normalBase +} + +// a work in progress +func (f *Forge) IsPrivate(repo *gitpb.Repo) bool { + namespace := repo.GetNamespace() + if namespace == "" { + // assume true + return true + } + + return f.Config.IsPrivate(namespace) +} + +// is this a non-publishable repo? +// matches package names from apt +// +// IsPrivate("foo") will match anything in the config file ending in "foo" +// +// IsPrivate("go.foo.com/jcarr/foo") returns true if private +// IsPrivate("foo") also returns true if "go.bar.com/jcarr/foo" is private +func (fc *ForgeConfigs) IsPrivate(thing string) bool { + var match *ForgeConfig + + // sort by path means the simple 'match' logic + // here works in the sense the last directory match + // is the one that is used + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + // if private is set here, then ok, otherwise + // still check if a Directory match exists + if r.Private { + return true + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.Private { + return true + } + } + // check to see if IsPrivate("foo") + // search for potential dir matches + if r.Directory { + // test the dir + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + // log.Info("did not match in IsPrivate()", thing) + return false + } + + // otherwise, assume not private + return match.Private +} + +// IsFavorite() -- fun option for the config +// file that lets you set things as favorites +// so you can just go-clone a bunch of common things +// on a new box or after you reset/delete your ~/go/src dir +func (fc *ForgeConfigs) IsFavorite(thing string) bool { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + if r.Favorite { + return true + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.Favorite { + return true + } + } + if r.Directory { + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + return false + } + + return match.Favorite +} + +// IsWritable() checks your .config/forge/ settings +// looks for an exact match, then +// looks for a directory match +func (fc *ForgeConfigs) IsWritable(thing string) bool { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + if r.Writable { + return true + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.Writable { + return true + } + } + if r.Directory { + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + return false + } + + return match.Writable +} + +// allows custom user branch names in the forge config +func (fc *ForgeConfigs) FindUserBranch(thing string) string { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + if r.UserBranchName != "" { + return r.UserBranchName + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.UserBranchName != "" { + return r.UserBranchName + } + } + if r.Directory { + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + return "" + } + + return match.UserBranchName +} + +// allows custom devel branch names in the forge config +func (fc *ForgeConfigs) FindDevelBranch(thing string) string { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + if r.DevelBranchName != "" { + return r.DevelBranchName + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.DevelBranchName != "" { + return r.DevelBranchName + } + } + if r.Directory { + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + return "" + } + + return match.DevelBranchName +} + +// allows custom devel branch names in the forge config +func (fc *ForgeConfigs) FindMasterBranch(thing string) string { + var match *ForgeConfig + + all := fc.All() // get the list of repos + for all.Scan() { + r := all.Next() + if r.Namespace == thing { + if r.MasterBranchName != "" { + return r.MasterBranchName + } + } + base := filepath.Base(r.Namespace) + if base == thing { + if r.MasterBranchName != "" { + return r.MasterBranchName + } + } + if r.Directory { + if strings.HasPrefix(thing, r.Namespace) { + match = r + } + } + } + if match == nil { + return "" + } + + return match.MasterBranchName +} diff --git a/init.go b/init.go index 7f1ebbe..80c9ca1 100644 --- a/init.go +++ b/init.go @@ -8,6 +8,7 @@ import ( "path/filepath" "go.wit.com/lib/config" + "go.wit.com/lib/gui/shell" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" ) @@ -66,6 +67,26 @@ func initFromConfig(cfg *ForgeConfigs) *Forge { os.Exit(-1) } + // todo: play with these / determine good values based on user's machine + if f.Config.RillX == 0 { + f.Config.RillX = 10 + } + if f.Config.RillY == 0 { + f.Config.RillY = 20 + } + + if !shell.Exists(f.Config.ReposPB) { + if f.Config.Mode == ForgeMode_NEWUSER { + // new user. drop back to main() for an introduction + return f + } + // create an initial repos.pb file + // panic() here? // warning? // (probably not. it's just the repos.pb cache file + f.Repos = gitpb.NewRepos() + f.Repos.Filename = f.Config.ReposPB + f.Repos.Save() + } + f.Repos = gitpb.NewRepos() f.Repos.ConfigLoad(f.Config.ReposPB) @@ -83,14 +104,6 @@ func initFromConfig(cfg *ForgeConfigs) *Forge { } } } - - // todo: play with these / determine good values based on user's machine - if f.Config.RillX == 0 { - f.Config.RillX = 10 - } - if f.Config.RillY == 0 { - f.Config.RillY = 20 - } return f } diff --git a/run.go b/run.go index 2f2e57f..8a9b304 100644 --- a/run.go +++ b/run.go @@ -19,7 +19,7 @@ func RunGitClone(newdir, basedir, giturl string) error { log.Info("runGitClone() basedir =", basedir) log.Info("runGitClone() giturl =", giturl) if !shell.IsDir(basedir) { - os.MkdirAll(basedir, os.ModePerm) + os.MkdirAll(basedir, 0755) } err := os.Chdir(basedir) if err != nil { -- cgit v1.2.3