From 61b648c04fc3f5afa760b8840583e1335cd76229 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sat, 27 Sep 2025 14:22:41 -0500 Subject: add cgit-clone --- cgit-clone/Makefile | 80 +++++++++++++++++++ cgit-clone/argv.go | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++ cgit-clone/exit.go | 22 ++++++ cgit-clone/main.go | 52 ++++++++++++ cgit-clone/structs.go | 51 ++++++++++++ 5 files changed, 418 insertions(+) create mode 100644 cgit-clone/Makefile create mode 100644 cgit-clone/argv.go create mode 100644 cgit-clone/exit.go create mode 100644 cgit-clone/main.go create mode 100644 cgit-clone/structs.go diff --git a/cgit-clone/Makefile b/cgit-clone/Makefile new file mode 100644 index 0000000..117e8c4 --- /dev/null +++ b/cgit-clone/Makefile @@ -0,0 +1,80 @@ +VERSION = $(shell git describe --tags) +BUILDTIME = $(shell date +%Y.%m.%d_%H%M) + +# 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-verbose + cgit-clone + +vet: + @GO111MODULE=off go vet + @echo this go binary package builds okay + +build: goimports vet + GO111MODULE=off go build \ + -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" + +install: goimports + GO111MODULE=off go install \ + -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" + cp -f ~/go/bin/forge ~/go/bin/last.forge # this is a hack so that go-deb can build a .deb file for forge # TODO: remove this + +install-verbose: goimports vet + GO111MODULE=off go install -v -x \ + -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" + +install-raw: goimports vet + go install \ + -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" + +GTK: clean install + forge --gui andlabs + +GTK-verbose: clean install + forge --gui andlabs --gui-verbose + +CUI: install + forge --gui gocui + +CUI-verbose: install + forge --gui gocui --gui-verbose >/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 + +clean: + -rm -f cgit-clone go.* + # -rm -f ~/go/src/repos.pb + go-mod-clean purge + +identify-protobuf: + autogenpb --identify ~/go/src/repos.pb + +devel: + forge clean devel --force --verbose + +pull: install + FORGE_URL="https://forge.grid.wit.com/" forge pull check + +# cloudflare blocks POST due to captcha checks / human detection? +# POST must be direct socket. probably for the best anyway +submit: + FORGE_URL="https://forge.grid.wit.com/" forge patch submit "forge auto commit" + +commit: + FORGE_URL="https://forge.grid.wit.com/" forge commit --all + +check: install + FORGE_URL="https://forge.grid.wit.com/" forge patch check + +doc: + echo "/*" > doc.go + forge -h >> doc.go + echo "*/" >> doc.go + echo "package main" >> doc.go diff --git a/cgit-clone/argv.go b/cgit-clone/argv.go new file mode 100644 index 0000000..524c91f --- /dev/null +++ b/cgit-clone/argv.go @@ -0,0 +1,213 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "os" + + "go.wit.com/lib/gui/prep" + "go.wit.com/log" +) + +/* + this parses the command line arguements using alex flint's go-arg +*/ + +var argv args + +type args struct { + Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch branches using 'git checkout'"` + Clean *CleanCmd `arg:"subcommand:reset" help:"reset all git repos to the original state"` + Commit *CommitCmd `arg:"subcommand:commit" help:"'git commit' but errors out if on wrong branch"` + Config *ConfigCmd `arg:"subcommand:config" help:"show your .config/forge/ settings"` + Gui *EmptyCmd `arg:"subcommand:gui" help:"open the gui"` + Merge *MergeCmd `arg:"subcommand:merge" help:"merge branches"` + Normal *NormalCmd `arg:"subcommand:normal" help:"set every repo to the default state for software development"` + Patch *PatchCmd `arg:"subcommand:patch" help:"make patchsets"` + Pull *PullCmd `arg:"subcommand:pull" help:"run 'git pull'"` + Show *ShowCmd `arg:"subcommand:show" help:"print out things"` + Dev *DevCmd `arg:"subcommand:dev" help:"features under development"` + All bool `arg:"--all" help:"git commit --all"` + Force bool `arg:"--force" help:"try to strong-arm things"` + Verbose bool `arg:"--verbose" help:"show more output"` +} + +func (args) Examples() string { + var out string + out += "forge pull --force # 'git pull' on all repos\n" + out += "forge merge --all # merge all patches to devel & master\n" + out += "forge normal fix # the defaults for 'normal' forge distributed development (makes local user branches)\n" + out += "forge reset fix # smartly restore all git repos to the upstream state (removes changes forge might have made)\n" + return out +} + +type EmptyCmd struct { +} + +type testCmd string + +type ShowCmd struct { + Dirty *EmptyCmd `arg:"subcommand:dirty" help:"show dirty git repos"` + Repo *RepoCmd `arg:"subcommand:repos" help:"print a table of the current repos"` + Tag *TagCmd `arg:"subcommand:tag" help:"show git tags"` +} + +func (ShowCmd) Examples() string { + return "forge show dirty\nforge show repos --all" +} + +type RepoCmd struct { + All bool `arg:"--all" help:"select every repo (the default)"` + Mine bool `arg:"--mine" help:"your repos as defined in the forge config"` + Favorites bool `arg:"--favorites" help:"your repos configured as favorites"` + Private bool `arg:"--private" help:"your private repos from your .config/forge/"` + User bool `arg:"--user" help:"show repos on the user branch"` + Full bool `arg:"--full" help:"show full repo names"` + // ReadOnly bool `arg:"--readonly" help:"include read-only repos"` +} + +type NormalCmd struct { + Fix *EmptyCmd `arg:"subcommand:fix" help:"try to fix problems"` + On *EmptyCmd `arg:"subcommand:on" help:"turn normal mode on"` + Off *EmptyCmd `arg:"subcommand:off" help:"turn normal mode off"` +} + +type CommitCmd struct { + // Submit bool `arg:"--submit" help:"submit the patches to forge"` + All bool `arg:"--all" help:"git commit in all dirty repos"` +} + +type DevCmd struct { + Build string `arg:"--build" help:"build a repo"` + Install string `arg:"--install" help:"install a repo"` + BuildForge bool `arg:"--forge-rebuild" help:"download and rebuild forge"` + URL string `arg:"--connect" help:"forge url"` +} + +type CleanCmd struct { + Fix *EmptyCmd `arg:"subcommand:fix" help:"try to fix problems"` + Repo string `arg:"--repo" help:"work on one specific git repository"` +} + +// matches +func (c CleanCmd) Match(partial string) []string { + // return repos here + return []string{"go.wit.com/apps/forge", "go.wit.com/apps/virtigo"} +} + +type CleanDevelCmd struct { + Force bool `arg:"--force" help:"try to strong arm things"` +} + +type PatchCmd struct { + Check *EmptyCmd `arg:"subcommand:check" help:"check the state of the patches"` + List *EmptyCmd `arg:"subcommand:list" help:"your downloaded patchsets"` + Get *EmptyCmd `arg:"subcommand:get" help:"get the new patchsets"` + Show *EmptyCmd `arg:"subcommand:show" help:"your pending commits to your code"` + Submit *SubmitCmd `arg:"subcommand:submit" help:"submit your commits"` + Repos *SubmitCmd `arg:"subcommand:repos" help:"show repos with patches"` +} + +type SubmitCmd struct { + Match string `arg:"positional"` +} + +type PullCmd struct { + Force bool `arg:"--force" help:"try to strong-arm things"` + List *EmptyCmd `arg:"subcommand:list" help:"list repo versions"` + Check *EmptyCmd `arg:"subcommand:check" help:"check for repo changes"` +} + +type TagCmd struct { + List *EmptyCmd `arg:"subcommand:list" help:"list the tags"` + Clean *EmptyCmd `arg:"subcommand:clean" help:"clean out old and duplicate tags"` + Delete string `arg:"--delete" help:"delete a tag"` +} + +type CheckoutCmd struct { + User *EmptyCmd `arg:"subcommand:user" help:"git checkout user"` + Devel *EmptyCmd `arg:"subcommand:devel" help:"git checkout devel"` + Master *EmptyCmd `arg:"subcommand:master" help:"git checkout master"` +} + +type MergeCmd struct { + All bool `arg:"--all" help:"merge all"` + Devel *EmptyCmd `arg:"subcommand:devel" help:"merge user to devel"` + Master *EmptyCmd `arg:"subcommand:master" help:"merge devel to master"` + Publish *EmptyCmd `arg:"subcommand:publish" help:"increment versions and publish master branch"` +} + +type ConfigCmd struct { + Add *ConfigAddCmd `arg:"subcommand:add" help:"add a config setting"` + Fix *EmptyCmd `arg:"subcommand:fix" help:"fix .config/forge/ and/or repos.pb protobuf file"` + List *EmptyCmd `arg:"subcommand:list" help:"list your config settings"` + Delete string `arg:"--delete" help:"delete this repo"` + Register string `arg:"--register" help:"register your git URL (foo.com/mystuff) or (github.com/foo/bar)"` +} + +type ConfigAddCmd struct { + Path string `arg:"--path" help:"absolute path of the git repo"` + GoPath string `arg:"--gopath" help:"GO path of the git repo"` + Directory bool `arg:"--directory" help:"repo is a directory to match against"` + ReadOnly bool `arg:"--readonly" help:"repo is readonly"` + Writable bool `arg:"--writable" help:"repo is writable"` + Favorite bool `arg:"--favorite" help:"forge will always go-clone or git clone this" default:"false"` + Private bool `arg:"--private" default:"false" help:"repo can not be published"` + Interesting bool `arg:"--interesting" default:"false" help:"something you decided was cool"` + DebName string `arg:"--debname" help:"the name of the debian package (or rpm, etc)"` + Master string `arg:"--master" help:"the git 'master' or 'main' branch name"` + Devel string `arg:"--devel" help:"the git devel branch name"` + User string `arg:"--user" help:"the git user branch name"` +} + +func (args) Version() string { + return ARGNAME + " " + VERSION + " Built on " + BUILDTIME +} + +// keep this small +func doHelp() { + log.Info("") + log.Info("forge -h : to see the available options") + log.Info("forge --bash : will create a bash autocomplete file") + log.Info("forge : with no arguements, forge tries to load a GO GUI plugin") + log.Info(" : there are two GUI plugins. terminal & GTK") + log.Info("") + log.Info("forge list : shows a table of all your repos") + log.Info("forge checkout : checks out all your repos to the same branch") + log.Info(" : the default is your user branch") + log.Info("forge clean : reverts all repos to the master branch") + log.Info("forge dirty : show all repos git reports as dirty") + log.Info("") +} + +func (a args) Description() string { + // doHelp() + + return ` +forge -- a tool to manage lots of git repos. forge includes a GUI and TUI. + + forge only executes the 'git' command. Everything it does, you can run by hand with 'git'. +` +} + +func ifBlank(arg string) bool { + if arg == "''" { + // if empty, the user has not typed something + return true + } + return false +} + +func (args) Appname() string { + return ARGNAME +} + +func (a args) DoAutoComplete(pb *prep.Auto) { + if pb.Cmd == "" { + pb.Autocomplete3([]string{"checkout", "reset", "commit", "config", "gui", "merge", "normal", "patch", "pull", "show"}) + } else { + pb.SubCommand(pb.Argv...) + } + os.Exit(0) +} diff --git a/cgit-clone/exit.go b/cgit-clone/exit.go new file mode 100644 index 0000000..507686d --- /dev/null +++ b/cgit-clone/exit.go @@ -0,0 +1,22 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +import ( + "os" + + "go.wit.com/log" +) + +func okExit(thing string) { + if thing != "" { + log.Info("cgit-clone exit:", thing, "ok") + } + me.forge.Exit() +} + +func badExit(err error) { + log.Info("cgit-clone failed: ", err) + os.Exit(-1) +} diff --git a/cgit-clone/main.go b/cgit-clone/main.go new file mode 100644 index 0000000..dd48ad7 --- /dev/null +++ b/cgit-clone/main.go @@ -0,0 +1,52 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +// An app to submit patches for the 30 GO GUI repos + +import ( + "os" + "path/filepath" + + "go.wit.com/lib/gui/prep" + "go.wit.com/lib/gui/shell" + "go.wit.com/lib/protobuf/forgepb" + "go.wit.com/log" +) + +// sent via -ldflags +var VERSION string +var BUILDTIME string + +// used for shell auto completion +var ARGNAME string = "cgit-clone" + +func main() { + me = new(mainType) + me.auto = prep.Bash(&argv) // adds auto complete to go-args + + // the current forge init process + me.forge = forgepb.Init() // init forge.pb + + homedir := "/var/lib/git" + if err := os.Chdir(homedir); err != nil { + badExit(err) + } + + for repo := range me.forge.Repos.IterAll() { + fulldir := filepath.Join(repo.FullPath, ".git") + cgitdir := repo.Namespace + ".git" + if shell.IsDir(filepath.Join(homedir, cgitdir)) { + // log.Info("already have", filepath.Join(homedir, cgitdir)) + continue + } else { + // log.Info("need", filepath.Join(homedir, cgitdir)) + } + + cmd := []string{"git", "clone", "--bare", fulldir, cgitdir} + log.Info(cmd) + shell.RunVerbose(cmd) + } + okExit("") +} diff --git a/cgit-clone/structs.go b/cgit-clone/structs.go new file mode 100644 index 0000000..15b17bc --- /dev/null +++ b/cgit-clone/structs.go @@ -0,0 +1,51 @@ +// 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/gui" + "go.wit.com/lib/gadgets" + "go.wit.com/lib/gui/prep" + "go.wit.com/lib/protobuf/forgepb" +) + +var me *mainType + +func (b *mainType) Disable() { + b.mainbox.Disable() +} + +func (b *mainType) Enable() { + b.mainbox.Enable() +} + +// returns the server to connect to +func myServer() string { + return me.forge.GetForgeURL() +} + +// this app's variables +type mainType struct { + // pp *arg.Parser // for parsing the command line args. Yay to alexflint! + auto *prep.Auto // more experiments for bash handling + forge *forgepb.Forge // for holding the forge protobuf files + myGui *prep.GuiPrep // for initializing the GUI toolkits + foundPaths []string // stores gopaths to act on (when doing go-clone) + configSave bool // if the config file should be saved after finishing + urlbase string // base URL + + mainWindow *gadgets.BasicWindow + mainbox *gui.Node // the main box. enable/disable this + autoDryRun *gui.Node // checkbox for --dry-run + goSrcPwd *gadgets.OneLiner // what is being used as primary directory for your work + goSrcEdit *gadgets.BasicEntry // what is being used as primary directory for your work + gitAuthor *gadgets.OneLiner // ENV GIT_AUTHOR NAME and EMAIL + + // these hold the branches that the user can switch all the repositories to them + reposWinB *gui.Node // button that opens the repos window + repoAllB *gui.Node // "all" repos button + repoDirtyB *gui.Node // "dirty" repos button + repoDevelMergeB *gui.Node // "merge to devel" repos button + repoWritableB *gui.Node // "what repos are writable" repos button +} -- cgit v1.2.3