first attempt that seems to kinda work on New()

This commit is contained in:
Jeff Carr 2024-11-27 21:40:06 -06:00
parent 8b987962ea
commit ed3eacfe75
10 changed files with 379 additions and 9 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@ go.*
*.pb.go
example/example
scanGoSrc/scanGoSrc

View File

@ -6,6 +6,7 @@
all: refs.pb.go godep.pb.go repo.pb.go vet
make -C scanGoSrc/
vet: lint
GO111MODULE=off go vet

117
godep.redoGoMod.go Normal file
View File

@ -0,0 +1,117 @@
package gitpb
// does processing on the go.mod and go.sum files
import (
"bufio"
"errors"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
// poor name perhaps. It's because in most of these
// repos you can also type "make redomod" to do the same thing
// since it's a Makefile task that is also useful to be able to run
// from the command line
func (repo *Repo) MakeRedomod() (bool, error) {
// unset the go development ENV var to generate release files
os.Unsetenv("GO111MODULE")
if ok, err := repo.strictRun([]string{"rm", "-f", "go.mod", "go.sum"}); !ok {
log.Warn("rm go.mod go.sum failed", err)
return ok, err
}
if ok, err := repo.strictRun([]string{"go", "mod", "init", repo.GoPath}); !ok {
log.Warn("go mod init failed", err)
return ok, err
}
if ok, err := repo.strictRun([]string{"go", "mod", "tidy"}); !ok {
log.Warn("go mod tidy failed", err)
return ok, err
}
log.Info("MakeRedomod() worked", repo.GoPath)
if repo.Exists("go.sum") {
// return the attempt to parse go.mod & go.sum
return repo.parseGoSum()
}
repo.GoDeps = nil
repo.GoPrimitive = false
ok, err := repo.isPrimativeGoMod()
if err != nil {
// this means this repo does not depend on any other package
log.Info("PRIMATIVE repo error:", repo.GoPath, "err =", err)
return false, err
}
if ok {
// this means the repo is primitive so there is no go.sum
repo.GoPrimitive = true
return true, nil
}
// this should never happen
return false, errors.New("MakeRedomod() logic failed")
}
// reads and parses the go.sum file
func (repo *Repo) parseGoSum() (bool, error) {
// empty out what was there before
repo.GoDeps = nil
tmp := filepath.Join(repo.FullPath, "go.sum")
gosum, err := os.Open(tmp)
if err != nil {
log.Warn("missing go.sum", repo.FullPath)
return false, err
}
defer gosum.Close()
scanner := bufio.NewScanner(gosum)
log.Info("gosum:", tmp)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
parts := strings.Split(line, " ")
if len(parts) == 3 {
godep := strings.TrimSpace(parts[0])
version := strings.TrimSpace(parts[1])
if strings.HasSuffix(version, "/go.mod") {
version = strings.TrimSuffix(version, "/go.mod")
}
new1 := GoDep{
GoPath: godep,
Version: version,
}
repo.AppendGoDep(&new1)
/*
found := repo.FindGoDepByPath(godep)
if found == nil {
currentversion, ok := deps[godep]
if ok {
// only use the first value found in the file?
// this shouldn't have been possible. this function should
// only be called from MakeRedomod()
// todo: make go things a seperate package so this function
// isn't exported?
if version != currentversion {
log.Warn("\tgo.sum ", godep, "had both", version, currentversion)
}
} else {
deps[godep] = version
log.Info("\t", godep, "=", version)
}
*/
} else {
// I've never seen this happen yet
panic(errors.New("go.sum invalid: " + line))
// return false, errors.New("go.sum invalid: " + line)
}
}
if err := scanner.Err(); err != nil {
repo.GoDeps = nil
return false, err
}
return true, nil
}

16
log.go Normal file
View File

@ -0,0 +1,16 @@
package gitpb
import (
"go.wit.com/log"
)
var GITPB *log.LogFlag
var GITPBWARN *log.LogFlag
func init() {
full := "go.wit.com/lib/protobuf/gitpb"
short := "gitpb"
GITPB = log.NewFlag("GITPB", false, full, short, "general gitpb things")
GITPBWARN = log.NewFlag("GITPBWARN", true, full, short, "gitpb warnings")
}

View File

@ -1,7 +1,13 @@
package gitpb
import (
"bufio"
"errors"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
// scans in a new git repo. If it detects the repo is a golang project,
@ -9,11 +15,19 @@ import (
// TODO: try adding python, rails, perl, rust, other language things?
// I probably will never have time to try that, but I'd take patches for anyone
// that might see this note and feel so inclined.
func (all *Repos) NewGoPath(basepath string, gopath string) *Repo {
func (all *Repos) NewGoPath(basepath string, gopath string) (*Repo, error) {
if r := all.FindByGoPath(gopath); r != nil {
// already had this gopath
return r
return r, nil
}
// if .git doesn't exist, error out here
gitpath := filepath.Join(basepath, gopath, ".git")
_, err := os.Stat(gitpath)
if err != nil {
return nil, err
}
// add a new one here
newr := Repo{
FullPath: filepath.Join(basepath, gopath),
@ -22,5 +36,39 @@ func (all *Repos) NewGoPath(basepath string, gopath string) *Repo {
newr.UpdateGit()
all.add(&newr)
return &newr
return &newr, nil
}
// Detect a 'Primative' package. Sets the isPrimative flag
// will return true if the repo is truly not dependent on _anything_ else
// like spew or lib/widget
// it assumes go mod ran init and tidy ran without error
func (repo *Repo) isPrimativeGoMod() (bool, error) {
// go mod init & go mod tidy ran without errors
log.Log(GITPB, "isPrimativeGoMod()", repo.FullPath)
tmp := filepath.Join(repo.FullPath, "go.mod")
gomod, err := os.Open(tmp)
if err != nil {
log.Log(GITPB, "missing go.mod", repo.FullPath)
repo.GoDeps = nil
return false, err
}
defer gomod.Close()
scanner := bufio.NewScanner(gomod)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
parts := strings.Split(line, " ")
log.Log(GITPB, " gomod:", parts)
if len(parts) >= 1 {
log.Log(GITPB, " gomod: part[0] =", parts[0])
if parts[0] == "require" {
log.Log(GITPB, " should return false here")
return false, errors.New("go.mod file is not primative")
}
}
}
return true, nil
}

View File

@ -11,12 +11,15 @@ import "google/protobuf/timestamp.proto"; // Import the well-known type for Time
message Repo {
string fullPath = 1; // the actual path to the .git directory: '/home/devel/golang.org/x/tools'
string goPath = 2; // the logical path as used by golang: 'go.wit.com/apps/helloworld'
bool library = 3; // if this is a golang library
repeated Ref refs = 4;
repeated GoDep GoDeps = 5;
google.protobuf.Timestamp lastPull = 6; // last time a git pull was done
repeated Ref refs = 2;
google.protobuf.Timestamp lastPull = 3; // last time a git pull was done
// things specific to golang projects
string goPath = 4; // the logical path as used by golang: 'go.wit.com/apps/helloworld'
repeated GoDep GoDeps = 6;
google.protobuf.Timestamp lastGoDep = 7; // last time go.sum was processed
bool goLibrary = 8; // if this is a golang library
bool goPrimitive = 9; // if this is a golang primitive
}
message Repos {

23
scanGoSrc/Makefile Normal file
View File

@ -0,0 +1,23 @@
VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d)
build:
GO111MODULE=off go build \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
FORGE_HOME=/tmp/forge ./scanGoSrc
install:
GO111MODULE=off go install \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
goimports:
goimports -w *.go
prep:
go get -v -t -u
run:
go run *.go
clean:
-rm -f scanGoSrc

50
scanGoSrc/argv.go Normal file
View File

@ -0,0 +1,50 @@
package main
import (
"os"
"github.com/alexflint/go-arg"
)
var argv args
type args struct {
ConfigDir string `arg:"env:FORGE_HOME" help:"defaults to ~/.config/forge/"`
List bool `arg:"--list" default:"false" help:"list repos in your config"`
Add bool `arg:"--add" default:"false" help:"add a new repo"`
Delete bool `arg:"--delete" default:"false" help:"delete a repo"`
Update bool `arg:"--update" default:"false" help:"update a repo"`
GoPath string `arg:"--gopath" help:"gopath of the repo"`
Directory bool `arg:"--directory" default:"false" help:"repo is a directory to match against"`
ReadOnly bool `arg:"--readonly" default:"false" help:"repo is readonly"`
Writable bool `arg:"--writable" default:"false" help:"repo is writable"`
Favorite bool `arg:"--favorite" default:"false" help:"forge will always go-clone or git clone this"`
Private bool `arg:"--private" default:"false" help:"repo can not be published"`
Interesting bool `arg:"--interesting" default:"false" help:"something you decided was cool"`
}
func (a args) Description() string {
return `
forgeConfig -- add entries to your config files
This is just example protobuf code to test forgepb is working
but it could be used to automagically create a config file too.
If you need to change your config file, just edit the forge.text or forge.json
files then remove the forge.pb and ConfigLoad() will attempt to load those files instead
`
}
func (args) Version() string {
return "virtigo " + VERSION
}
func init() {
var pp *arg.Parser
pp = arg.MustParse(&argv)
if pp == nil {
pp.WriteHelp(os.Stdout)
os.Exit(0)
}
}

61
scanGoSrc/main.go Normal file
View File

@ -0,0 +1,61 @@
package main
import (
"os"
"go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
// sent via ldflags
var VERSION string
func main() {
var config forgepb.ForgeConfigs
if err := config.ConfigLoad(); err != nil {
log.Warn("forgepb.ConfigLoad() failed", err)
os.Exit(-1)
}
config.PrintTable()
var repos *gitpb.Repos
repos = new(gitpb.Repos)
newr, err := repos.NewGoPath("/home/jcarr/go/src", "go.wit.com/apps/wit-package")
if err != nil {
log.Info("init failed", err)
} else {
log.Info("init worked for", newr.GoPath)
}
newr, err = repos.NewGoPath("/home/jcarr/go/src", "go.wit.com/apps/notathing")
if err != nil {
log.Info("init failed correctly:", err)
} else {
log.Info("init should have failed for", newr.GoPath)
}
/*
log.Info(forgepb.RepoHeader())
loop := repos.SortByPath() // get the list of repos
for loop.Scan() {
r := loop.Repo()
log.Info("repo:", r.GoPath)
}
*/
/*
log.Info("going to add a new repo", argv.GoPath)
new1 := forgepb.Repo{
GoPath: argv.GoPath,
Writable: argv.Writable,
ReadOnly: argv.ReadOnly,
Private: argv.Private,
Directory: argv.Directory,
Favorite: argv.Favorite,
Interesting: argv.Interesting,
}
*/
os.Exit(0)
}

51
shell.go Normal file
View File

@ -0,0 +1,51 @@
package gitpb
import (
"os"
"path/filepath"
"strings"
"github.com/go-cmd/cmd"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
// execute something with the working directory
// set to the FullPath
func (repo *Repo) Run(cmd []string) cmd.Status {
result := shell.PathRun(repo.FullPath, cmd)
output := strings.Join(result.Stdout, "\n")
if result.Error != nil {
log.Warn("cmd:", cmd)
log.Warn("ouptput:", output)
log.Warn("failed with error:", result.Error)
}
return result
}
// for now, even check cmd.Exit
func (repo *Repo) strictRun(cmd []string) (bool, error) {
result := repo.Run(cmd)
if result.Error != nil {
log.Warn("go mod init failed err:", result.Error)
return false, result.Error
}
if result.Exit != 0 {
log.Warn("go mod init exit =", result.Exit)
return false, result.Error
}
return true, nil
}
func (repo *Repo) Exists(filename string) bool {
if repo == nil {
log.Warn("repo == nil for Exists()")
panic(-1)
}
testf := filepath.Join(repo.FullPath, filename)
_, err := os.Stat(testf)
if err != nil {
return false
}
return true
}