cleanup argv handling. go-arg saves the day
This commit is contained in:
parent
7402aaded7
commit
51ec39d157
44
Makefile
44
Makefile
|
@ -1,11 +1,13 @@
|
|||
VERSION = $(shell git describe --tags)
|
||||
BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
|
||||
|
||||
info: install
|
||||
# forge dirty
|
||||
# forge examine
|
||||
# forge clean
|
||||
make andlabs
|
||||
# make build # go build using your git cloned repos (GO111MODULE=off)
|
||||
# make install # go install using your git cloned repos (GO111MODULE=off)
|
||||
# make gocui # try the ncurses gui plugin
|
||||
# make andlabs # try the andlabs gui plugin (uses GTK)
|
||||
|
||||
default: install
|
||||
forge dirty --verbose
|
||||
|
||||
vet:
|
||||
@GO111MODULE=off go vet
|
||||
|
@ -27,7 +29,6 @@ install-raw: goimports vet plugin
|
|||
go install \
|
||||
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
||||
|
||||
|
||||
plugin:
|
||||
rm -f resources/*.so
|
||||
cp ../../toolkits/gocui/gocui.so resources/
|
||||
|
@ -35,31 +36,22 @@ plugin:
|
|||
andlabs:
|
||||
forge --gui andlabs
|
||||
|
||||
gocui: install
|
||||
forge --gui gocui >/tmp/forge.log 2>&1
|
||||
|
||||
goimports:
|
||||
reset
|
||||
goimports -w *.go
|
||||
@# // to globally reset paths:
|
||||
@# // gofmt -w -r '"go.wit.com/gui/gadgets" -> "go.wit.com/lib/gadgets"' *.go
|
||||
|
||||
gocui: install
|
||||
forge --gui gocui >/tmp/forge.log 2>&1
|
||||
clean:
|
||||
-rm -f forge go.*
|
||||
# -rm -f ~/go/src/repos.pb
|
||||
go-mod-clean --purge
|
||||
|
||||
patches-make: install
|
||||
forge --patchset "from makefile 2"
|
||||
identify-protobuf:
|
||||
autogenpb --identify ~/go/src/repos.pb
|
||||
|
||||
patches-list-2233: install
|
||||
forge --list-patchset --connect "http://go.wit.com:2233/"
|
||||
|
||||
patches-list: install
|
||||
forge --list-patchset
|
||||
|
||||
patches-apply-230233: install
|
||||
forge --apply /tmp/2024.12.27.230233.submitted.pb
|
||||
|
||||
restart:
|
||||
reset
|
||||
-rm ~/go/src/repos.pb
|
||||
make private
|
||||
|
||||
identify:
|
||||
autogenpb --identify /home/jcarr/go/src/repos.pb
|
||||
devel:
|
||||
forge clean devel --force --verbose
|
||||
|
|
43
README.md
43
README.md
|
@ -1,10 +1,41 @@
|
|||
forge
|
||||
# forge
|
||||
|
||||
This can be used to maintain git repositories
|
||||
expiremental work on federated git
|
||||
|
||||
/usr/share/git-gui/lib/tools/
|
||||
.git/config settings for gitgui
|
||||
[gui]
|
||||
wmstate = normal
|
||||
geometry = 931x515+450+130 197 234
|
||||
* Scans directories looking for git repositories
|
||||
* The default behavior is to use 3 branches. 'master or main', 'devel', '<username>'
|
||||
* shows tags and dirty state
|
||||
* uses a GUI or the console(console display needs work)
|
||||
* always wrap around 'git' -- it basically just types 'git' commands really fast
|
||||
|
||||
## Notes & Goals:
|
||||
|
||||
* use a GUI that also works on the command line
|
||||
* andlabs GTK gui plugin starts breaking around 200 repos
|
||||
|
||||
## Install:
|
||||
|
||||
* go install go.wit.com/apps/forge@latest
|
||||
|
||||
## building from sources (may work Jan 2026)
|
||||
|
||||
```
|
||||
go install go.wit.com/apps/go-clone@latest # this tool makes it easier to 'git clone' repos and recursively 'git clone' the dependancies
|
||||
go install go.wit.com/apps/autogenpb@latest # this tool will generate the protobuf *pb.go files (also Marshal(), Sort(), etc.)
|
||||
|
||||
go-clone --recursive go.wit.com/apps/forge # this will 'git clone' about 20 repos into ~/go/src (or where your go.work file is)
|
||||
|
||||
cd go.wit.com/lib/protobuf/forgepb
|
||||
make # autogenpb will make .pb.go, marshal.pb.go and sort.pb.go files
|
||||
cd go.wit.com/lib/protobuf/gitpb
|
||||
make # autogenpb will make .pb.go, marshal.pb.go and sort.pb.go files
|
||||
|
||||
cd go.wit.com/apps/forge
|
||||
make # this runs GO111MODULE=off go build insuring that your using only your git sources
|
||||
|
||||
```
|
||||
|
||||
## Debian packages:
|
||||
|
||||
Instructions are on https://mirrors.wit.com/
|
||||
|
|
42
argv.go
42
argv.go
|
@ -12,26 +12,22 @@ import (
|
|||
var argv args
|
||||
|
||||
type args struct {
|
||||
Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch git branches"`
|
||||
Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch branches using 'git checkout'"`
|
||||
Clean *CleanCmd `arg:"subcommand:clean" help:"clean git branches"`
|
||||
Commit *EmptyCmd `arg:"subcommand:commit" help:"'git commit' but errors out if on wrong branch"`
|
||||
Config *ConfigCmd `arg:"subcommand:config" help:"show your .config/forge/ settings"`
|
||||
Dirty *DirtyCmd `arg:"subcommand:dirty" help:"check if your git repos are dirty"`
|
||||
GitReset *EmptyCmd `arg:"subcommand:hard-reset" help:"hard reset your user git branches"`
|
||||
List *FindCmd `arg:"subcommand:list" help:"just show a table of the current state"`
|
||||
Patch *PatchCmd `arg:"subcommand:patch" help:"examine and make patch sets"`
|
||||
GitPull *FindCmd `arg:"subcommand:pull" help:"run 'git pull'"`
|
||||
Dirty *DirtyCmd `arg:"subcommand:dirty" help:"show repos git says are dirty"`
|
||||
GitFetch *FindCmd `arg:"subcommand:fetch" help:"run 'git fetch master'"`
|
||||
Rescan *EmptyCmd `arg:"subcommand:rescan" help:"recreate the git protobuf repos.pb file"`
|
||||
Delete *EmptyCmd `arg:"subcommand:delete" help:"untrack a repo"`
|
||||
Commit *EmptyCmd `arg:"subcommand:commit" help:"smart 'git commit' (errors out if on wrong branch)"`
|
||||
Clean *CleanCmd `arg:"subcommand:clean" help:"clean out all local branches (safely)"`
|
||||
Examine *ExamineCmd `arg:"subcommand:examine" help:"examine branches"`
|
||||
URL string `arg:"--connect" help:"gowebd url"`
|
||||
List *FindCmd `arg:"subcommand:list" help:"print a table of the current repos"`
|
||||
Patch *PatchCmd `arg:"subcommand:patch" help:"make patchsets"`
|
||||
GitPull *FindCmd `arg:"subcommand:pull" help:"run 'git pull'"`
|
||||
URL string `arg:"--connect" help:"forge url"`
|
||||
All bool `arg:"--all" help:"git commit --all"`
|
||||
Show string `arg:"--show" help:"show a repo"`
|
||||
Bash bool `arg:"--bash" help:"generate bash completion"`
|
||||
BashAuto []string `arg:"--auto-complete" help:"does the actual autocompletion"`
|
||||
Force bool `arg:"--force" help:"try to strong arm things"`
|
||||
Verbose bool `arg:"--verbose" help:"show more output"`
|
||||
Bash bool `arg:"--bash" help:"generate bash completion"`
|
||||
BashAuto []string `arg:"--auto-complete" help:"todo: move this to go-arg"`
|
||||
}
|
||||
|
||||
type EmptyCmd struct {
|
||||
|
@ -46,9 +42,12 @@ type ExamineCmd struct {
|
|||
}
|
||||
|
||||
type CleanCmd struct {
|
||||
Force *EmptyCmd `arg:"subcommand:force" help:"dangerously delete things that are not pushed upstream"`
|
||||
User *EmptyCmd `arg:"subcommand:user" help:"clean the user branches"`
|
||||
Devel *CleanDevelCmd `arg:"subcommand:devel" help:"clean and verify the devel branches"`
|
||||
User *EmptyCmd `arg:"subcommand:user" help:"clean the user branches"`
|
||||
Devel *CleanDevelCmd `arg:"subcommand:devel" help:"clean and verify the devel branches"`
|
||||
Force *EmptyCmd `arg:"subcommand:force" help:"try harder to delete things. check your patchsets have been saved first."`
|
||||
Examine *ExamineCmd `arg:"subcommand:examine" help:"examine branches"`
|
||||
GitReset *EmptyCmd `arg:"subcommand:git-reset" help:"git reset --hard"`
|
||||
Delete *EmptyCmd `arg:"subcommand:delete" help:"rescan repo"`
|
||||
}
|
||||
|
||||
type CleanDevelCmd struct {
|
||||
|
@ -91,7 +90,6 @@ type CheckoutCmd struct {
|
|||
}
|
||||
|
||||
type DirtyCmd struct {
|
||||
Show bool `arg:"--show-files" help:"also list every dirty file"`
|
||||
}
|
||||
|
||||
type FindCmd struct {
|
||||
|
@ -111,8 +109,13 @@ func (args) Version() string {
|
|||
|
||||
func (a args) Description() string {
|
||||
return `
|
||||
forge -- in the spirit of things like sourceforge
|
||||
forge -- a tool to git repos at go.wit.com
|
||||
|
||||
but you can probably use it for other things
|
||||
`
|
||||
}
|
||||
|
||||
/*
|
||||
This supports GO projects so far.
|
||||
It will work from ~/go/src or where your go.work file is.
|
||||
Since I mostly use ~/go/src, that has been tested more.
|
||||
|
@ -132,6 +135,7 @@ Examples:
|
|||
|
||||
`
|
||||
}
|
||||
*/
|
||||
|
||||
func (args) doBashHelpDebug() {
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
|
|
|
@ -14,7 +14,8 @@ import (
|
|||
// var ARGNAME string = "forge" // todo: get this from $0 ?
|
||||
|
||||
func (a *EmptyCmd) deleteMatch() {
|
||||
fmt.Println("go.wit.com/lib/gui/repostatus")
|
||||
// f := forgedb.InitSimple()
|
||||
fmt.Println("go.wit.com/lib/gui/repostatus todo: need to do this")
|
||||
}
|
||||
|
||||
func (args) doBashAuto() {
|
||||
|
@ -24,15 +25,22 @@ func (args) doBashAuto() {
|
|||
usr, _ := user.Current()
|
||||
fmt.Println("user devel master " + usr.Username)
|
||||
case "clean":
|
||||
fmt.Println("devel user force")
|
||||
// me.pp.WriteHelp(os.Stderr)
|
||||
// me.pp.WriteUsageForSubcommand(os.Stderr, me.pp.SubcommandNames()...)
|
||||
// me.pp.WriteHelpForSubcommand(os.Stderr, me.pp.SubcommandNames()...)
|
||||
me.pp.WriteHelpForSubcommand(os.Stderr, "clean")
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
fmt.Fprintln(os.Stderr, "hello world")
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
fmt.Println("devel user force clean examine git-reset")
|
||||
case "commit":
|
||||
fmt.Println("--all")
|
||||
case "config":
|
||||
fmt.Println("add fix list delete")
|
||||
fmt.Println("add fix list")
|
||||
case "delete":
|
||||
argv.Delete.deleteMatch()
|
||||
argv.Clean.Delete.deleteMatch()
|
||||
case "dirty":
|
||||
fmt.Println("--show-files")
|
||||
fmt.Println("--verbose")
|
||||
case "examine":
|
||||
fmt.Println("fix")
|
||||
case "list":
|
||||
|
@ -50,7 +58,7 @@ func (args) doBashAuto() {
|
|||
default:
|
||||
if argv.BashAuto[0] == ARGNAME {
|
||||
// list the subcommands here
|
||||
fmt.Println("--bash checkout clean commit config dirty delete examine hard-reset list patch pull rescan")
|
||||
fmt.Println("--bash list checkout clean commit config dirty fetch patch pull")
|
||||
}
|
||||
}
|
||||
os.Exit(0)
|
||||
|
@ -81,8 +89,8 @@ func (args) doBash() {
|
|||
fmt.Println("")
|
||||
fmt.Println("# todo: add this to go-arg as a 'hidden' go-arg option --bash")
|
||||
fmt.Println("#")
|
||||
fmt.Println("# todo: make this output work/parse with:")
|
||||
fmt.Println("# complete -C " + ARGNAME + " --bash go")
|
||||
fmt.Println("# todo: can this output work/parse with:")
|
||||
fmt.Println("# complete -C `" + ARGNAME + " --bash` " + ARGNAME)
|
||||
fmt.Println("")
|
||||
fmt.Println("_" + ARGNAME + "_complete()")
|
||||
fmt.Println("{")
|
||||
|
|
12
doClean.go
12
doClean.go
|
@ -62,9 +62,9 @@ func doCleanDevel() error {
|
|||
// log.Info("Cleaning:", repo.GetGoPath())
|
||||
}
|
||||
total += 1
|
||||
if repo.GetCurrentBranchName() != repo.GetDevelBranchName() {
|
||||
// only process branches in devel
|
||||
// return nil
|
||||
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
||||
// repos must be in the master branch to clean the devel branch
|
||||
return nil
|
||||
}
|
||||
if repo.IsDirty() {
|
||||
return nil
|
||||
|
@ -110,7 +110,9 @@ func checkhashes(repo *gitpb.Repo, hashes []string, refpath string) ([]string, e
|
|||
func doCleanDevelRepo(repo *gitpb.Repo) error {
|
||||
var hashes []string
|
||||
devel := repo.GetDevelBranchName()
|
||||
// log.Printf("%s Start verify devel branch: %s\n", repo.GetGoPath(), devel)
|
||||
if argv.Verbose {
|
||||
log.Printf("Start clean devel branch: %s %s\n", repo.GetGoPath(), devel)
|
||||
}
|
||||
|
||||
// check if devel branch exists in remote repo
|
||||
if repo.Exists(filepath.Join(".git/refs/remotes/origin", devel)) {
|
||||
|
@ -451,7 +453,6 @@ func forceDeleteUserBranch(repo *gitpb.Repo, branch string) error {
|
|||
}
|
||||
log.Info("THIS USER REMOTE BRANCH MUST BE DELETED HERE", branch)
|
||||
if repo.Exists(filepath.Join(".git/refs/remote/origin", branch)) {
|
||||
// git push origin --delete jcarr
|
||||
cmd = []string{"git", "push", "origin", "--delete", branch}
|
||||
if _, err := repo.RunVerbose(cmd); err != nil {
|
||||
log.Info("THE GIT BRANCH DELETE ERROR IS:", err)
|
||||
|
@ -482,7 +483,6 @@ func BADforceDeleteBranch(repo *gitpb.Repo, branch string) error {
|
|||
}
|
||||
log.Info("THIS USER REMOTE BRANCH MUST BE DELETED HERE", branch)
|
||||
if repo.Exists(filepath.Join(".git/refs/remote/origin", branch)) {
|
||||
// git push origin --delete jcarr
|
||||
cmd = []string{"git", "push", "origin", "--delete", branch}
|
||||
if _, err := repo.RunVerbose(cmd); err != nil {
|
||||
log.Info("THE GIT BRANCH DELETE ERROR IS:", err)
|
||||
|
|
|
@ -13,7 +13,11 @@ func doDirty() {
|
|||
doCheckDirtyAndConfigSave()
|
||||
me.found = new(gitpb.Repos)
|
||||
findDirty()
|
||||
me.forge.PrintHumanTableDirty(me.found)
|
||||
if argv.Verbose {
|
||||
me.forge.PrintHumanTableDirty(me.found)
|
||||
} else {
|
||||
me.forge.PrintHumanTable(me.found)
|
||||
}
|
||||
}
|
||||
|
||||
func straightCheckDirty() int {
|
||||
|
|
20
doExamine.go
20
doExamine.go
|
@ -54,7 +54,7 @@ func doExamine() error {
|
|||
dur := time.Since(ctime)
|
||||
log.Printf("UNKNOWN BRANCH %-50s %s %4s %s\n", repo.GetFullPath(), tag.Hash, shell.FormatDuration(dur), tag.Refname)
|
||||
err := examineBranch(repo)
|
||||
if argv.Examine.Fix != nil {
|
||||
if argv.Clean.Examine.Fix != nil {
|
||||
if err != nil {
|
||||
badExit(err)
|
||||
}
|
||||
|
@ -112,12 +112,14 @@ func examineBranch(repo *gitpb.Repo) error {
|
|||
return fmt.Errorf("repo.CurrentTag == nil")
|
||||
}
|
||||
|
||||
if repo.CurrentTag.Refname == "jcarr" {
|
||||
return requiresGitPush(repo, "jcarr")
|
||||
userbranch := repo.GetUserBranchName()
|
||||
|
||||
if repo.CurrentTag.Refname == userbranch {
|
||||
return requiresGitPush(repo, userbranch)
|
||||
}
|
||||
|
||||
if repo.CurrentTag.Refname == "origin/jcarr" {
|
||||
return requiresGitPush(repo, "jcarr")
|
||||
if repo.CurrentTag.Refname == "origin/"+userbranch {
|
||||
return requiresGitPush(repo, userbranch)
|
||||
}
|
||||
|
||||
if len(dcount) == 0 {
|
||||
|
@ -130,7 +132,7 @@ func examineBranch(repo *gitpb.Repo) error {
|
|||
err = fmt.Errorf("examineBranch() branch differs. patch diff len == 0. PROBABLY DELETE BRANCH %s", repo.CurrentTag.Refname)
|
||||
log.Info(err)
|
||||
cmd := repo.ConstructGitDiffLog(repo.CurrentTag.Refname, repo.GetMasterBranchName())
|
||||
if argv.Examine.Fix == nil {
|
||||
if argv.Clean.Examine.Fix == nil {
|
||||
log.Info(repo.GetGoPath(), cmd)
|
||||
} else {
|
||||
if _, err := repo.RunVerbose(cmd); err != nil {
|
||||
|
@ -138,7 +140,7 @@ func examineBranch(repo *gitpb.Repo) error {
|
|||
}
|
||||
}
|
||||
cmd = repo.ConstructGitDiffLog(repo.GetMasterBranchName(), repo.CurrentTag.Refname)
|
||||
if argv.Examine.Fix == nil {
|
||||
if argv.Clean.Examine.Fix == nil {
|
||||
log.Info(repo.GetGoPath(), cmd)
|
||||
} else {
|
||||
if _, err := repo.RunVerbose(cmd); err != nil {
|
||||
|
@ -147,7 +149,7 @@ func examineBranch(repo *gitpb.Repo) error {
|
|||
}
|
||||
cmd = []string{"git", "branch", "-D", repo.CurrentTag.Refname}
|
||||
log.Info(repo.GetGoPath(), "TRY THIS:", cmd)
|
||||
if argv.Examine.Fix == nil {
|
||||
if argv.Clean.Examine.Fix == nil {
|
||||
log.Info(repo.GetGoPath(), "TODO: CHECK REMOTE BRANCH DOES NOT EXIST", repo.CurrentTag.Refname)
|
||||
repo.RunVerbose([]string{"ls", "-l", ".git/refs/remotes/origin"})
|
||||
} else {
|
||||
|
@ -266,7 +268,7 @@ func requiresGitPush(repo *gitpb.Repo, branchName string) error {
|
|||
if b1 != 0 {
|
||||
log.Info(branchName, "vs origin count b1 != 0, b2 ==", b1, b2)
|
||||
log.Info("THIS MEANS THE LOCAL BRANCH NEEDS GIT PUSH TO ORIGIN BRANCH ==", b1)
|
||||
if argv.Examine.Fix != nil {
|
||||
if argv.Clean.Examine.Fix != nil {
|
||||
return gitPushStrict(repo, branchName)
|
||||
}
|
||||
return nil
|
||||
|
|
31
main.go
31
main.go
|
@ -79,6 +79,18 @@ func main() {
|
|||
}
|
||||
|
||||
if argv.Clean != nil {
|
||||
if argv.Clean.Examine != nil {
|
||||
if err := doExamine(); err != nil {
|
||||
badExit(err)
|
||||
}
|
||||
okExit("")
|
||||
}
|
||||
if argv.Clean.GitReset != nil {
|
||||
findAll() // select all the repos
|
||||
doGitReset()
|
||||
okExit("reset")
|
||||
}
|
||||
|
||||
if err := doClean(); err != nil {
|
||||
badExit(err)
|
||||
}
|
||||
|
@ -90,18 +102,6 @@ func main() {
|
|||
okExit("")
|
||||
}
|
||||
|
||||
if argv.Examine != nil {
|
||||
if err := doExamine(); err != nil {
|
||||
badExit(err)
|
||||
}
|
||||
okExit("")
|
||||
}
|
||||
|
||||
if argv.Rescan != nil {
|
||||
me.forge.ScanGoSrc()
|
||||
okExit("")
|
||||
}
|
||||
|
||||
if argv.Show != "" {
|
||||
repo := me.forge.FindByGoPath(argv.Show)
|
||||
me.forge.HumanPrintRepo(repo)
|
||||
|
@ -131,18 +131,13 @@ func main() {
|
|||
okExit("")
|
||||
}
|
||||
|
||||
if argv.GitReset != nil {
|
||||
findAll() // select all the repos
|
||||
doGitReset()
|
||||
okExit("reset")
|
||||
}
|
||||
|
||||
if argv.List != nil {
|
||||
argv.List.findRepos()
|
||||
// print out the repos
|
||||
me.forge.PrintHumanTable(me.found)
|
||||
okExit("")
|
||||
}
|
||||
|
||||
if argv.Patch != nil {
|
||||
if argv.Patch.Submit != "" {
|
||||
doSubmit(argv.Patch.Submit)
|
||||
|
|
Loading…
Reference in New Issue