Compare commits

...

12 Commits

Author SHA1 Message Date
Jeff Carr 8b199273e8 api change 2025-09-13 01:07:34 -05:00
Jeff Carr 67df8f90f9 rm GoSrc() 2025-09-11 22:21:13 -05:00
Jeff Carr bb1df07910 common forge.Init() 2025-09-11 04:46:26 -05:00
Jeff Carr d19f4a8911 new forge init() 2025-09-11 03:27:49 -05:00
Jeff Carr 54811a5bc1 work on lookup/ 2025-07-07 18:51:38 -05:00
Jeff Carr 529eb104d5 allow cloning http(s) URL's 2025-06-29 17:49:52 -05:00
Jeff Carr 21dd714514 go-mod-clean syntax change 2025-06-04 07:41:47 -05:00
Jeff Carr 4ab621a7f2 notes about 'git bug' 2025-05-23 03:27:53 -05:00
Jeff Carr 0c5183edf9 works more often now 2025-02-22 09:43:22 -06:00
Jeff Carr f078399929 tinkering 2025-02-22 08:15:29 -06:00
Jeff Carr c521620b04 fix build and cleanup old code 2025-02-22 06:52:50 -06:00
Jeff Carr cc19c8ac8e minor 2025-02-15 07:27:43 -06:00
7 changed files with 116 additions and 86 deletions

2
.gitignore vendored
View File

@ -3,4 +3,4 @@ go.mod
go.sum go.sum
/files/* /files/*
/work/* /work/*
go-clone go-clone*

View File

@ -1,14 +1,14 @@
VERSION = $(shell git describe --tags) VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d_%H%M) BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
run: build run: install
./go-clone --version go-clone --version
vet: vet:
@GO111MODULE=off go vet @GO111MODULE=off go vet
@echo this go binary package builds okay @echo this go binary package builds okay
no-gui: build no-gui: install build-darwin build-windows
./go-clone --no-gui ./go-clone --no-gui
build: goimports build: goimports
@ -16,11 +16,16 @@ build: goimports
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
build-darwin: build-darwin:
GOOS=darwin GOARCH=amd64 GO111MODULE=off go build -v -o go-clone-darwin \ GOOS=darwin GOARCH=amd64 GO111MODULE=off go build -v -o go-clone-darwin.x86 \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
build-darwin-arm64:
GOOS=darwin GOARCH=arm64 GO111MODULE=off go build -v -o go-clone-darwin.arm \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
build-windows: build-windows:
GOOS=windows GOARCH=amd64 GO111MODULE=off go build -v go-clone.exe \ GOOS=windows GOARCH=amd64 GO111MODULE=off go build -v -o go-clone.exe \
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" -ldflags "-X main.VERSION=v0.7.46 -X main.BUILDTIME=2025.02.22_0643 -X gui.GUIVERSION=v0.7.46"
install: goimports install: goimports
GO111MODULE=off go install \ GO111MODULE=off go install \
@ -45,7 +50,9 @@ nocui: build
./go-clone --gui nocui ./go-clone --gui nocui
clean: clean:
-rm go-clone rm -f go.*
-rm go-clone*
go-mod-clean purge
# this will test the golang.org/x -> googlesource override # this will test the golang.org/x -> googlesource override
git-clone: git-clone:

37
argv.go
View File

@ -1,5 +1,10 @@
package main package main
import (
"fmt"
"os"
)
/* /*
this parses the command line arguements this parses the command line arguements
@ -12,10 +17,9 @@ type args struct {
Repo string `arg:"positional" help:"go import path"` Repo string `arg:"positional" help:"go import path"`
AutoWork bool `arg:"--work" default:"false" help:"recreate the go.work file"` AutoWork bool `arg:"--work" default:"false" help:"recreate the go.work file"`
DryRun bool `arg:"--dry-run" help:"show what would be run"` DryRun bool `arg:"--dry-run" help:"show what would be run"`
Recursive bool `arg:"--recursive" default:"false" help:"recursively clone all dependencies"` Recursive bool `arg:"--recursive" default:"true" help:"recursively clone all dependencies"`
Pull bool `arg:"--git-pull" default:"false" help:"run 'git pull'"` Build bool `arg:"--build" help:"try to build it after clone"`
Build bool `arg:"--build" default:"true" help:"try to build it after clone"` Install bool `arg:"--install" help:"try to install it after clone"`
Install bool `arg:"--install" default:"false" help:"try to install it after clone"`
Ignore bool `arg:"--ignore" default:"false" help:"ignore weird clone errors from non-standard repos"` Ignore bool `arg:"--ignore" default:"false" help:"ignore weird clone errors from non-standard repos"`
// Fetch bool `arg:"--git-fetch" default:"false" help:"run 'git fetch' on all your repos"` // Fetch bool `arg:"--git-fetch" default:"false" help:"run 'git fetch' on all your repos"`
} }
@ -26,15 +30,24 @@ func (args) Version() string {
func (a args) Description() string { func (a args) Description() string {
return ` return `
git clone go repositories git clone go repositories recursively
Examples: Examples:
go-clone go.wit.com/apps/go-clone # simply try to git clone this go-clone go.wit.com/apps/go-clone # 'git clone' go-clone
go-clone --recursive go.wit.com/apps/go-clone # recursively clone all the dependencies
go-clone --auto-work go.wit.com/apps/go-clone # if you are using a go.work file, recreate the go.work file
go-clone --go-reset # recreate every go.mod and go.sum file
go-clone --git-pull # run 'git pull' in every repo
go-clone --build # build every binary package
go-clone --install # install every binary package
` `
} }
func (a args) DoAutoComplete(argv []string) {
switch argv[0] {
case "checkout":
fmt.Println("user devel master ")
case "--recursive":
fmt.Println("true false")
default:
if argv[0] == ARGNAME {
// list the subcommands here
fmt.Println("--dry-run --recursive --work")
}
}
os.Exit(0)
}

View File

@ -5,11 +5,59 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"go.wit.com/lib/protobuf/gitpb" "go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log" "go.wit.com/log"
) )
/*
# to support distributed 'git bug'
# create a new user:
git bug user new -e "jcarr@wit.com" -n "Jeff Carr"
git pull origin +refs/bugs/\*:refs/bugs/\*
git pull origin +refs/identities/\*:refs/identities/\*
git show-ref | grep refs/bugs/
git log refs/bugs/<some-id>
git config --add remote.origin.fetch '+refs/bugs/*:refs/bugs/*'
git config --add remote.origin.fetch '+refs/identities/*:refs/identities/*'
git config --get-all remote.origin.fetch
[remote "origin"]
url = ...
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/bugs/*:refs/bugs/*
fetch = +refs/identities/*:refs/identities/*
# remove the caches
rm -rf .git/git-bug
# rebuild the cache with any command
git bug user
*/
// CleanRepoURL removes http://, https://, and .git suffix from the given URL if present.
func CleanRepoURL(url string) string {
// Trim protocol prefix
if strings.HasPrefix(url, "http://") {
url = strings.TrimPrefix(url, "http://")
} else if strings.HasPrefix(url, "https://") {
url = strings.TrimPrefix(url, "https://")
}
// Trim trailing .git
url = strings.TrimSuffix(url, ".git")
return url
}
func clone(gopath string) (*gitpb.Repo, error) { func clone(gopath string) (*gitpb.Repo, error) {
// if the user defined a repo, attempt to download it now // if the user defined a repo, attempt to download it now
if gopath == "" { if gopath == "" {
@ -17,9 +65,10 @@ func clone(gopath string) (*gitpb.Repo, error) {
// user probably wants to --recursive on current working dir // user probably wants to --recursive on current working dir
return nil, errors.New("gopath was blank") return nil, errors.New("gopath was blank")
} }
gopath = CleanRepoURL(gopath)
os.Setenv("REPO_AUTO_CLONE", "true") os.Setenv("REPO_AUTO_CLONE", "true")
// pb, _ := forge.NewGoPath(gopath) // pb, _ := forge.NewGoPath(gopath)
check := forge.FindAnyPath(filepath.Join(forge.GetGoSrc(), gopath)) check := forge.FindAnyPath(filepath.Join(forge.Config.ReposDir, gopath))
if check != nil { if check != nil {
if check.IsValidDir() { if check.IsValidDir() {
// repo already exists and is valid // repo already exists and is valid
@ -32,6 +81,7 @@ func clone(gopath string) (*gitpb.Repo, error) {
return nil, err return nil, err
} }
autoWork()
if err := makeValidGoSum(pb); err != nil { if err := makeValidGoSum(pb); err != nil {
return nil, err return nil, err
} }
@ -53,31 +103,28 @@ func recursiveClone(check *gitpb.Repo) error {
if check == nil { if check == nil {
return errors.New("repo was nil") return errors.New("repo was nil")
} }
log.Info("STARTING RECURSIVE CLONE", check.GetGoPath()) log.Info("STARTING RECURSIVE CLONE", check.Namespace)
log.Info("STARTING RECURSIVE CLONE", check.GetGoPath()) log.Info("STARTING RECURSIVE CLONE", check.Namespace)
// if just cloned, parse the go.sum file for deps // if just cloned, parse the go.sum file for deps
if check.ParseGoSum() { if check.ParseGoSum() {
} else { } else {
makeValidGoSum(check) makeValidGoSum(check)
} }
if check.GetGoPrimitive() {
// go primitive repos are "pure" check.ReloadForce()
log.Info("repo is primitive", check.GetGoPath())
return nil
}
if check.GoDeps == nil { if check.GoDeps == nil {
log.Info("repo godeps == nil", check.GetGoPath()) log.Info("repo godeps == nil", check.Namespace)
return errors.New("go.sum is missing?") return errors.New("no go deps?")
} }
// probably this should never be 0 because GoPrimitive should have been true otherwise // probably this should never be 0 because GoPrimitive should have been true otherwise
if check.GoDeps.Len() == 0 { if check.GoDeps.Len() == 0 {
log.Info("repo len(godeps) == 0", check.GetGoPath()) log.Info("repo len(godeps) == 0", check.Namespace)
return errors.New("go.sum never parsed?") return errors.New("go.sum never parsed?")
} }
log.Info("deps for", check.GetGoPath(), "len()", check.GoDeps.Len()) log.Info("deps for", check.Namespace, "len()", check.GoDeps.Len())
deps := check.GoDeps.SortByGoPath() deps := check.GoDeps.SortByGoPath()
for deps.Scan() { for deps.Scan() {
depRepo := deps.Next() depRepo := deps.Next()
@ -110,13 +157,16 @@ func makeValidGoSum(check *gitpb.Repo) error {
// attempt to grab the notes // attempt to grab the notes
check.RunQuiet([]string{"git", "fetch", "origin", "refs/notes/*:refs/notes/*"}) check.RunQuiet([]string{"git", "fetch", "origin", "refs/notes/*:refs/notes/*"})
if check.ParseGoSum() { if err := check.RunVerbose([]string{"forge", "list"}); err != nil {
return nil log.Info("")
log.Info("Do you have go-mod-clean? Otherwise:")
log.Info(" go install go.wit.com/apps/go-mod-clean@latest")
log.Info("")
} }
log.Info("try running go-mod-clean") log.Info("try running go-mod-clean")
// update go.sum and go.mod // update go.sum and go.mod
if _, err := check.RunQuiet([]string{"go-mod-clean"}); err != nil { if err := check.RunVerbose([]string{"go-mod-clean", "lax"}); err != nil {
log.Info("") log.Info("")
log.Info("Do you have go-mod-clean? Otherwise:") log.Info("Do you have go-mod-clean? Otherwise:")
log.Info(" go install go.wit.com/apps/go-mod-clean@latest") log.Info(" go install go.wit.com/apps/go-mod-clean@latest")
@ -129,7 +179,7 @@ func makeValidGoSum(check *gitpb.Repo) error {
// if this fails, just use go mod // if this fails, just use go mod
if err := check.ValidGoSum(); err != nil { if err := check.ValidGoSum(); err != nil {
cmd := []string{"go", "mod", "init", check.GetGoPath()} cmd := []string{"go", "mod", "init", check.Namespace}
log.Info("try running", cmd) log.Info("try running", cmd)
if _, err := check.RunQuiet(cmd); err != nil { if _, err := check.RunQuiet(cmd); err != nil {
log.Info("go mod init failed", err) log.Info("go mod init failed", err)

View File

@ -1,30 +0,0 @@
package main
import (
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func gitPull() {
log.Info("Total repositories:", forge.Repos.Len())
log.Info("Going to run git pull in each one. TODO: use rill here")
pull := []string{"git", "pull"}
var trycount, errcount int
repos := forge.Repos.SortByFullPath()
for repos.Scan() {
repo := repos.Next()
if argv.DryRun {
log.Info("git pull --dry-run", repo.GetGoPath())
continue
}
log.Info("git pull:", repo.FullPath)
trycount += 1
log.Info("actually run: git pull:", repo.GetGoPath())
if result := shell.PathRunRealtime(repo.FullPath, pull); result.Error != nil {
log.Info("git pull error:", result.Error)
errcount += 1
}
}
log.Info("Total repositories:", forge.Repos.Len(), "Total attempted:", trycount, "Errors:", errcount)
}

24
main.go
View File

@ -4,6 +4,7 @@ import (
"os" "os"
"go.wit.com/dev/alexflint/arg" "go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/forgepb" "go.wit.com/lib/protobuf/forgepb"
"go.wit.com/lib/protobuf/gitpb" "go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log" "go.wit.com/log"
@ -13,6 +14,8 @@ import (
var VERSION string var VERSION string
var BUILDTIME string var BUILDTIME string
var ARGNAME string = "go-clone"
var pp *arg.Parser var pp *arg.Parser
var forge *forgepb.Forge var forge *forgepb.Forge
@ -20,19 +23,11 @@ var workingRepo *gitpb.Repo
func main() { func main() {
log.Info("go-clone version", VERSION, "built on", BUILDTIME) log.Info("go-clone version", VERSION, "built on", BUILDTIME)
// command line parsing & handling
prep.Bash(ARGNAME, argv.DoAutoComplete) // todo: make this: prep.Bash(argv)
pp = arg.MustParse(&argv) pp = arg.MustParse(&argv)
// for very new users or users unfamilar with the command line, this may help them
if argv.Repo == "help" || argv.Repo == "?" {
pp.WriteHelp(os.Stdout)
os.Exit(0)
}
if argv.Repo == "version" {
log.Info(argv.Version())
os.Exit(0)
}
// this package helps scan git repos
forge = forgepb.Init() forge = forgepb.Init()
var err error var err error
@ -77,11 +72,6 @@ func main() {
badExit(err) badExit(err)
} }
} }
if argv.Pull {
// run 'git pull' if argv --git-pull
gitPull()
}
okExit("") okExit("")
} }
@ -96,6 +86,6 @@ func okExit(thing string) {
func badExit(err error) { func badExit(err error) {
log.Info("Total repositories:", forge.Repos.Len()) log.Info("Total repositories:", forge.Repos.Len())
log.Info("Finished go-clone with error", err, forge.GetGoSrc()) log.Info("Finished go-clone with error", err, forge.Config.ReposDir)
os.Exit(-1) os.Exit(-1)
} }

View File

@ -10,10 +10,10 @@ func autoWork() {
if !argv.AutoWork { if !argv.AutoWork {
return return
} }
log.Info("About to re-create", forge.GetGoSrc()+"/go.work") log.Info("About to re-create", forge.Config.ReposDir+"/go.work")
shell.PathRun(forge.GetGoSrc(), []string{"mv", "go.work", "go.work.last"}) shell.PathRun(forge.Config.ReposDir, []string{"mv", "go.work", "go.work.last"})
forge.MakeGoWork() forge.MakeGoWork()
shell.PathRun(forge.GetGoSrc(), []string{"go", "work", "use"}) shell.PathRun(forge.Config.ReposDir, []string{"go", "work", "use"})
log.Info("") log.Info("")
log.Info("original go.work file saved as go.work.last") log.Info("original go.work file saved as go.work.last")
log.Info("") log.Info("")