Compare commits
59 Commits
Author | SHA1 | Date |
---|---|---|
|
e0520ca96d | |
|
6d7d74feb4 | |
|
9c87e1a040 | |
|
bda5fb4fbe | |
|
1e3f4a3b9f | |
|
e300719241 | |
|
a9c4b21b35 | |
|
37aebd9d73 | |
|
5a54f9c0b2 | |
|
31db2f96f6 | |
|
3a967eac13 | |
|
17a62eb8da | |
|
ba2f156c3d | |
|
3c922f1277 | |
|
ac16ef7127 | |
|
2ce32a0f2f | |
|
4d4dcf31cb | |
|
19479f312f | |
|
58ce9ca53c | |
|
62e8d457f1 | |
|
f936a17bc0 | |
|
9bc6d030e5 | |
|
b8252f5caa | |
|
ce0fd10064 | |
|
ae2cbf1886 | |
|
29f2084e25 | |
|
02d34d3e55 | |
|
e14f7b93d1 | |
|
7fdd7075fd | |
|
179c19147e | |
|
0aafe6bb86 | |
|
03b8e58451 | |
|
5637809f5c | |
|
86306aa887 | |
|
30ee1fcdf7 | |
|
9cdfface3c | |
|
c463ec70f0 | |
|
f4d60d1fb9 | |
|
72d728d4e7 | |
|
20fe78266c | |
|
da0fc653ae | |
|
405ddb6994 | |
|
b5df8f2dad | |
|
7c520aae88 | |
|
96a8f66138 | |
|
bd951e4817 | |
|
fa3e6c3cd5 | |
|
101e9bd0d2 | |
|
40db2d84ef | |
|
f44aef8926 | |
|
0785f0e97f | |
|
363460290d | |
|
309fcffc86 | |
|
2471b1ea4c | |
|
efb966b3f8 | |
|
b30ecc89fb | |
|
7ab21831a0 | |
|
1b9e9c7518 | |
|
602e1fc4ae |
6
Makefile
6
Makefile
|
@ -6,8 +6,10 @@ BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
|
||||||
# make gocui # try the ncurses gui plugin
|
# make gocui # try the ncurses gui plugin
|
||||||
# make andlabs # try the andlabs gui plugin (uses GTK)
|
# make andlabs # try the andlabs gui plugin (uses GTK)
|
||||||
|
|
||||||
default: install-verbose
|
default: install-verbose tag
|
||||||
forge patch list
|
|
||||||
|
tag:
|
||||||
|
forge tag list
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
@GO111MODULE=off go vet
|
@GO111MODULE=off go vet
|
||||||
|
|
|
@ -12,39 +12,6 @@ func savePatchset(pset *forgepb.Patchset) error {
|
||||||
log.Info("savePatches() GIT_AUTHOR_EMAIL", pset.GetGitAuthorEmail())
|
log.Info("savePatches() GIT_AUTHOR_EMAIL", pset.GetGitAuthorEmail())
|
||||||
log.Info("savePatches() Branch Name", pset.GetStartBranchName())
|
log.Info("savePatches() Branch Name", pset.GetStartBranchName())
|
||||||
log.Info("savePatches() Start Hash", pset.GetStartBranchHash())
|
log.Info("savePatches() Start Hash", pset.GetStartBranchHash())
|
||||||
|
|
||||||
var count int
|
|
||||||
var bad int
|
|
||||||
var lasterr error
|
|
||||||
all := pset.Patches.SortByFilename()
|
|
||||||
for all.Scan() {
|
|
||||||
p := all.Next()
|
|
||||||
basedir := filepath.Join(os.Getenv("FORGE_CONFIG"), "currentpatches")
|
|
||||||
if fullname, err := savePatchFile(p, basedir); err != nil {
|
|
||||||
log.Info(fullname, "save failed", err)
|
|
||||||
bad += 1
|
|
||||||
lasterr = err
|
|
||||||
}
|
|
||||||
count += 1
|
|
||||||
}
|
|
||||||
log.Info("pset has", count, "total patches, ", bad, "bad save patches")
|
|
||||||
if bad == 0 {
|
|
||||||
return lasterr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// re-run git CheckDirty() on everything
|
|
||||||
func IsAnythingDirty() bool {
|
|
||||||
doCheckDirtyAndConfigSave()
|
|
||||||
found := me.forge.FindDirty()
|
|
||||||
if found.Len() == 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -62,43 +29,6 @@ func countCurrentPatches(repo *gitpb.Repo) int {
|
||||||
return len(result.Stdout)
|
return len(result.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func savePatchFile(p *forgepb.Patch, basedir string) (string, error) {
|
|
||||||
basepath, filename := filepath.Split(p.Filename)
|
|
||||||
fulldir := filepath.Join(basedir, basepath)
|
|
||||||
err := os.MkdirAll(fulldir, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("applyPathces() MkdirAll failed for", fulldir)
|
|
||||||
log.Info("applyPathces() MkdirAll failed err", err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
tmpname := filepath.Join(fulldir, filename)
|
|
||||||
log.Info("pset filename FILENAME IS REAL?", tmpname)
|
|
||||||
raw, _ := os.OpenFile(tmpname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
||||||
raw.Write(p.Data)
|
|
||||||
raw.Close()
|
|
||||||
return tmpname, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func readPatchFile(pbfile string) (*forgepb.Patchset, error) {
|
|
||||||
bytes, err := os.ReadFile(pbfile)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("readfile error", pbfile, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return handleBytes(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleBytes(bytes []byte) (*forgepb.Patchset, error) {
|
|
||||||
var pset *forgepb.Patchset
|
|
||||||
pset = new(forgepb.Patchset)
|
|
||||||
err := pset.Unmarshal(bytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Unmarshal failed", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return pset, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func doRegister(newurl string) error {
|
func doRegister(newurl string) error {
|
||||||
var url string
|
var url string
|
||||||
url = me.urlbase + "/register?url=" + newurl
|
url = me.urlbase + "/register?url=" + newurl
|
||||||
|
|
85
argv.go
85
argv.go
|
@ -6,6 +6,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/prep"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -20,7 +22,6 @@ type args struct {
|
||||||
Clean *CleanCmd `arg:"subcommand:clean" help:"start over at the beginning"`
|
Clean *CleanCmd `arg:"subcommand:clean" help:"start over at the beginning"`
|
||||||
Commit *CommitCmd `arg:"subcommand:commit" help:"'git commit' but errors out if on wrong branch"`
|
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"`
|
Config *ConfigCmd `arg:"subcommand:config" help:"show your .config/forge/ settings"`
|
||||||
Debug *EmptyCmd `arg:"subcommand:debug" help:"debug forge"`
|
|
||||||
Dirty *DirtyCmd `arg:"subcommand:dirty" help:"show dirty git repos"`
|
Dirty *DirtyCmd `arg:"subcommand:dirty" help:"show dirty git repos"`
|
||||||
GitFetch *FindCmd `arg:"subcommand:fetch" help:"run 'git fetch master'"`
|
GitFetch *FindCmd `arg:"subcommand:fetch" help:"run 'git fetch master'"`
|
||||||
Gui *EmptyCmd `arg:"subcommand:gui" help:"open the gui"`
|
Gui *EmptyCmd `arg:"subcommand:gui" help:"open the gui"`
|
||||||
|
@ -29,6 +30,7 @@ type args struct {
|
||||||
Normal *NormalCmd `arg:"subcommand:normal" help:"set every repo to the default state for software development"`
|
Normal *NormalCmd `arg:"subcommand:normal" help:"set every repo to the default state for software development"`
|
||||||
Patch *PatchCmd `arg:"subcommand:patch" help:"make patchsets"`
|
Patch *PatchCmd `arg:"subcommand:patch" help:"make patchsets"`
|
||||||
Pull *PullCmd `arg:"subcommand:pull" help:"run 'git pull'"`
|
Pull *PullCmd `arg:"subcommand:pull" help:"run 'git pull'"`
|
||||||
|
Tag *TagCmd `arg:"subcommand:tag" help:"manage git tags"`
|
||||||
URL string `arg:"--connect" help:"forge url"`
|
URL string `arg:"--connect" help:"forge url"`
|
||||||
All bool `arg:"--all" help:"git commit --all"`
|
All bool `arg:"--all" help:"git commit --all"`
|
||||||
Build string `arg:"--build" help:"build a repo"`
|
Build string `arg:"--build" help:"build a repo"`
|
||||||
|
@ -53,13 +55,8 @@ type CommitCmd struct {
|
||||||
type testCmd string
|
type testCmd string
|
||||||
|
|
||||||
type CleanCmd struct {
|
type CleanCmd struct {
|
||||||
Delete *EmptyCmd `arg:"subcommand:delete" help:"rescan repo"`
|
Verify *EmptyCmd `arg:"subcommand:verify" help:"rescan repo"`
|
||||||
Devel *CleanDevelCmd `arg:"subcommand:devel" help:"clean and verify the devel branches"`
|
Repo string `arg:"--repo" help:"which repo to look at"`
|
||||||
Force *EmptyCmd `arg:"subcommand:force" help:"do destructive stuff"`
|
|
||||||
GitReset *EmptyCmd `arg:"subcommand:git-reset" help:"git reset --hard"`
|
|
||||||
Pub *EmptyCmd `arg:"subcommand:pub" help:"clean target version numbers"`
|
|
||||||
User *EmptyCmd `arg:"subcommand:user" help:"clean the user branches"`
|
|
||||||
Repo string `arg:"--repo" help:"which repo to look at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CleanDevelCmd struct {
|
type CleanDevelCmd struct {
|
||||||
|
@ -85,6 +82,12 @@ type PullCmd struct {
|
||||||
Patches *EmptyCmd `arg:"subcommand:patches" help:"only check repos with patches"`
|
Patches *EmptyCmd `arg:"subcommand:patches" help:"only check repos with patches"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 ConfigAddCmd struct {
|
type ConfigAddCmd struct {
|
||||||
Path string `arg:"--path" help:"absolute path of the git repo"`
|
Path string `arg:"--path" help:"absolute path of the git repo"`
|
||||||
GoPath string `arg:"--gopath" help:"GO path of the git repo"`
|
GoPath string `arg:"--gopath" help:"GO path of the git repo"`
|
||||||
|
@ -146,63 +149,49 @@ forge -- a tool to manage lots of git repos. forge includes a GUI and TUI.
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// handles shell autocomplete
|
||||||
// handles shell autocomplete
|
func DoAutoComplete(pb *prep.Auto) {
|
||||||
//
|
switch pb.Cmd {
|
||||||
|
|
||||||
func DoAutoComplete(argv []string) {
|
|
||||||
// fmt.Fprintln(os.Stderr, "") // these are for debugging
|
|
||||||
// fmt.Fprintln(os.Stderr, "in autocomplete:", argv) // these are for debugging
|
|
||||||
switch argv[0] {
|
|
||||||
case "checkout":
|
case "checkout":
|
||||||
fmt.Println("devel master user")
|
pb.Autocomplete2("devel master user")
|
||||||
case "clean":
|
case "clean":
|
||||||
// me.pp.WriteHelp(os.Stderr)
|
pb.Autocomplete2("")
|
||||||
// me.pp.WriteUsageForSubcommand(os.Stderr, me.pp.SubcommandNames()...)
|
|
||||||
// me.pp.WriteHelpForSubcommand(os.Stderr, me.pp.SubcommandNames()...)
|
|
||||||
// me.pp.WriteHelpForSubcommand(os.Stderr, "clean")
|
|
||||||
fmt.Println("--force")
|
|
||||||
case "commit":
|
case "commit":
|
||||||
fmt.Println("--all")
|
pb.Autocomplete2("--all")
|
||||||
case "config":
|
case "config":
|
||||||
fmt.Println("add fix list debug")
|
fmt.Println("add fix list")
|
||||||
case "dirty":
|
case "dirty":
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
case "gui":
|
case "gui":
|
||||||
if ifBlank(argv[1]) {
|
fmt.Println("")
|
||||||
fmt.Fprintln(os.Stderr, "")
|
case "--gui":
|
||||||
fmt.Fprintln(os.Stderr, "CUI: terminal interface using 'gocui'")
|
pb.Autocomplete2("andlabs gocui")
|
||||||
fmt.Fprintln(os.Stderr, "GUI: linux and macos GUI using GTK")
|
|
||||||
} else {
|
|
||||||
fmt.Println("CUI GUI")
|
|
||||||
}
|
|
||||||
case "list":
|
case "list":
|
||||||
fmt.Println("--full")
|
pb.Autocomplete2("--mine --favorites --dirty")
|
||||||
case "merge":
|
case "merge":
|
||||||
fmt.Println("devel master")
|
pb.Autocomplete2("devel master --all")
|
||||||
case "normal":
|
case "normal":
|
||||||
fmt.Println("on off")
|
pb.Autocomplete2("on off")
|
||||||
case "pull":
|
case "pull":
|
||||||
fmt.Println("--force check")
|
pb.Autocomplete2("--force check")
|
||||||
case "patch":
|
case "patch":
|
||||||
fmt.Println("check get list repos submit show")
|
fmt.Println("check get list repos submit show")
|
||||||
case "user":
|
case "tag":
|
||||||
fmt.Println("--force")
|
fmt.Println("list --delete clean")
|
||||||
case "devel":
|
|
||||||
fmt.Println("--force")
|
|
||||||
case "master":
|
|
||||||
fmt.Println("")
|
|
||||||
case "verify":
|
|
||||||
fmt.Println("user devel master")
|
|
||||||
default:
|
default:
|
||||||
if argv[0] == ARGNAME {
|
if pb.Cmd == "" {
|
||||||
// list the subcommands here
|
pb.Autocomplete2("help list checkout clean commit dirty fetch gui normal merge patch pull tag --gui")
|
||||||
fmt.Println("help list checkout clean commit dirty debug fetch gui normal merge patch pull")
|
} else {
|
||||||
|
pb.Autocomplete2("list checkout clean commit dirty normal merge tag")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (args) Appname() string {
|
||||||
|
return ARGNAME
|
||||||
|
}
|
||||||
|
|
||||||
func ifBlank(arg string) bool {
|
func ifBlank(arg string) bool {
|
||||||
if arg == "''" {
|
if arg == "''" {
|
||||||
// if empty, the user has not typed something
|
// if empty, the user has not typed something
|
||||||
|
@ -211,6 +200,6 @@ func ifBlank(arg string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a args) DoAutoComplete(argv []string) {
|
func (a args) DoAutoComplete(autoArgv *prep.Auto) {
|
||||||
DoAutoComplete(argv)
|
DoAutoComplete(autoArgv)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// functions to import and export the protobuf
|
||||||
|
// data to and from config files
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func forgeConfigSave() error {
|
||||||
|
return me.forge.Config.ConfigSave()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setForgeMode(fmode forgepb.ForgeMode) {
|
||||||
|
if me.forge.Config.Mode == fmode {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Info("changing mode", me.forge.Config.Mode, fmode)
|
||||||
|
me.forge.Config.Mode = fmode
|
||||||
|
config.SetChanged("forge", true)
|
||||||
|
me.forge.Config.ConfigSave()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sampleConfig(all *forgepb.ForgeConfigs) {
|
||||||
|
new1 := new(forgepb.ForgeConfig)
|
||||||
|
new1.GoPath = "go.wit.com"
|
||||||
|
new1.Writable = true
|
||||||
|
new1.Directory = true
|
||||||
|
all.Append(new1)
|
||||||
|
|
||||||
|
fmt.Println("first time user. adding an example config file with", len(all.ForgeConfigs), "repos")
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ func doCheckout() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Checkout.Devel != nil {
|
if argv.Checkout.Devel != nil {
|
||||||
|
// setForgeMode(forgepb.ForgeMode_DEVEL)
|
||||||
if err := me.forge.DoAllCheckoutDevelNew(argv.Force); err != nil {
|
if err := me.forge.DoAllCheckoutDevelNew(argv.Force); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
@ -33,6 +35,8 @@ func doCheckout() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Checkout.Master != nil {
|
if argv.Checkout.Master != nil {
|
||||||
|
setForgeMode(forgepb.ForgeMode_MASTER) // disable "normal" mode if set
|
||||||
|
|
||||||
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
|
38
doClean.go
38
doClean.go
|
@ -6,14 +6,50 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func checkRemoteBranches(repo *gitpb.Repo) error {
|
||||||
|
if err := repo.ReloadCheck(); err != nil {
|
||||||
|
log.Info("need to reload", repo.FullPath)
|
||||||
|
}
|
||||||
|
if repo.VerifyRemoteAndLocalBranches(repo.GetDevelBranchName()) {
|
||||||
|
} else {
|
||||||
|
return log.Errorf("remote devel is out of sync with local: todo: git pull or git fetch")
|
||||||
|
}
|
||||||
|
if repo.VerifyRemoteAndLocalBranches(repo.GetMasterBranchName()) {
|
||||||
|
} else {
|
||||||
|
return log.Errorf("remote master is out of sync with local: todo: git pull or git fetch")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// reverts all repos back to the original master branches
|
// reverts all repos back to the original master branches
|
||||||
// automatically deletes local devel and user branches
|
// automatically deletes local devel and user branches
|
||||||
func doClean() error {
|
func doClean() error {
|
||||||
|
setForgeMode(forgepb.ForgeMode_CLEAN)
|
||||||
|
|
||||||
|
if argv.Clean.Verify != nil {
|
||||||
|
stats := me.forge.RillRepos(checkRemoteBranches)
|
||||||
|
for path, stat := range stats {
|
||||||
|
if stat.Err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dur := stat.End.Sub(stat.Start)
|
||||||
|
if dur > time.Second {
|
||||||
|
log.Infof("%s checkRemoteBranches() took a long time (%s) (err=%v)\n", path, shell.FormatDuration(dur), stat.Err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// log.Infof("%-60s, %-60s %v %s\n", stat.Start, stat.End.String(), dur, path)
|
||||||
|
// log.Infof("%-30v %s %v\n", dur, path, stat.Err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// fix this to work, then delete all the other options for "forge clean'
|
// fix this to work, then delete all the other options for "forge clean'
|
||||||
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
||||||
// badExit(err)
|
// badExit(err)
|
||||||
|
@ -213,7 +249,7 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd := []string{"git", "merge something somehow"}
|
cmd := []string{"git", "merge something somehow"}
|
||||||
log.Info("DEVEL LOCAL NEEDS GIT MERGE TO MASTER", repo.GetGoPath(), cmd, b1)
|
log.Info("devel local, remote and master branches are wrong", repo.GetGoPath(), cmd, b1)
|
||||||
// _, err := repo.RunVerbose(cmd)
|
// _, err := repo.RunVerbose(cmd)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
13
doCommit.go
13
doCommit.go
|
@ -6,6 +6,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
"go.wit.com/lib/gui/shell"
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
|
@ -21,22 +22,16 @@ func doCommit() error {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
newpatches = true
|
newpatches = true
|
||||||
}
|
repo.CheckDirty()
|
||||||
if !argv.Commit.Submit {
|
|
||||||
okExit("")
|
|
||||||
}
|
}
|
||||||
if newpatches {
|
if newpatches {
|
||||||
|
config.SetChanged("repos", true)
|
||||||
return doPatchSubmit()
|
return doPatchSubmit()
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
pwd, _ := os.Getwd()
|
repo := findCurrentPwdRepoOrDie()
|
||||||
repo := me.forge.Repos.FindByFullPath(pwd)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("todo: forge doesn't know how to work here yet")
|
|
||||||
okExit("")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !repo.CheckDirty() {
|
if !repo.CheckDirty() {
|
||||||
okExit(log.Sprintf("this repo %s is not dirty.\n\n--all # commit all changes in all repos", repo.GetFullPath()))
|
okExit(log.Sprintf("this repo %s is not dirty.\n\n--all # commit all changes in all repos", repo.GetFullPath()))
|
||||||
|
|
|
@ -55,7 +55,6 @@ func doConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("config.PathLock =", me.forge.Config.PathLock)
|
log.Info("config.PathLock =", me.forge.Config.PathLock)
|
||||||
log.Info("config.GoSrc =", me.forge.Config.GoSrc)
|
|
||||||
|
|
||||||
me.forge.ConfigPrintTable()
|
me.forge.ConfigPrintTable()
|
||||||
okExit("")
|
okExit("")
|
||||||
|
|
168
doDebug.go
168
doDebug.go
|
@ -1,168 +0,0 @@
|
||||||
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the GPL 3.0
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"go.wit.com/lib/protobuf/bugpb"
|
|
||||||
"go.wit.com/lib/protobuf/forgepb"
|
|
||||||
"golang.org/x/text/encoding/charmap"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func doDebug() {
|
|
||||||
me.forge = forgepb.InitPB()
|
|
||||||
me.forge.ScanGoSrc()
|
|
||||||
if err := me.forge.ConfigSave(); err != nil {
|
|
||||||
if err := me.forge.Repos.ConfigSave(); err != nil {
|
|
||||||
err := ValidateProtoUTF8(me.forge.Repos)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Protobuf UTF-8 validation failed: %v\n", err)
|
|
||||||
}
|
|
||||||
if err := bugpb.SanitizeProtoUTF8(me.forge.Repos); err != nil {
|
|
||||||
log.Fatalf("Sanitization failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// badExit(err)
|
|
||||||
}
|
|
||||||
me.forge.SetConfigSave(true)
|
|
||||||
me.forge.Exit()
|
|
||||||
okExit("this never runs")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateProtoUTF8 checks all string fields in a proto.Message recursively.
|
|
||||||
func ValidateProtoUTF8(msg proto.Message) error {
|
|
||||||
return validateValue(reflect.ValueOf(msg), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateValue(val reflect.Value, path string) error {
|
|
||||||
if !val.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr {
|
|
||||||
if val.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return validateValue(val.Elem(), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
for i := 0; i < val.NumField(); i++ {
|
|
||||||
field := val.Field(i)
|
|
||||||
fieldType := val.Type().Field(i)
|
|
||||||
fieldPath := fmt.Sprintf("%s.%s", path, fieldType.Name)
|
|
||||||
if err := validateValue(field, fieldPath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
s := val.String()
|
|
||||||
if !utf8.ValidString(s) {
|
|
||||||
return fmt.Errorf("invalid UTF-8 string at %s: %q", path, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
if val.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
return nil // skip []byte
|
|
||||||
}
|
|
||||||
for i := 0; i < val.Len(); i++ {
|
|
||||||
if err := validateValue(val.Index(i), fmt.Sprintf("%s[%d]", path, i)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
for _, key := range val.MapKeys() {
|
|
||||||
valItem := val.MapIndex(key)
|
|
||||||
if err := validateValue(valItem, fmt.Sprintf("%s[%v]", path, key)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SanitizeProtoUTF8 fixes all invalid UTF-8 strings in a proto.Message recursively.
|
|
||||||
func SanitizeProtoUTF8(msg proto.Message) error {
|
|
||||||
return sanitizeValue(reflect.ValueOf(msg), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func sanitizeValue(val reflect.Value, path string) error {
|
|
||||||
if !val.IsValid() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr {
|
|
||||||
if val.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return sanitizeValue(val.Elem(), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch val.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
for i := 0; i < val.NumField(); i++ {
|
|
||||||
field := val.Field(i)
|
|
||||||
fieldType := val.Type().Field(i)
|
|
||||||
if !field.CanSet() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := sanitizeValue(field, fmt.Sprintf("%s.%s", path, fieldType.Name)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
s := val.String()
|
|
||||||
if !utf8.ValidString(s) {
|
|
||||||
utf8Str, err := latin1ToUTF8(s)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to convert %s to UTF-8: %v", path, err)
|
|
||||||
}
|
|
||||||
val.SetString(utf8Str)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
if val.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
return nil // skip []byte
|
|
||||||
}
|
|
||||||
for i := 0; i < val.Len(); i++ {
|
|
||||||
if err := sanitizeValue(val.Index(i), fmt.Sprintf("%s[%d]", path, i)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
for _, key := range val.MapKeys() {
|
|
||||||
valItem := val.MapIndex(key)
|
|
||||||
newItem := reflect.New(valItem.Type()).Elem()
|
|
||||||
newItem.Set(valItem)
|
|
||||||
if err := sanitizeValue(newItem, fmt.Sprintf("%s[%v]", path, key)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
val.SetMapIndex(key, newItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func latin1ToUTF8(input string) (string, error) {
|
|
||||||
reader := charmap.ISO8859_1.NewDecoder().Reader(bytes.NewReader([]byte(input)))
|
|
||||||
result, err := io.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(result), nil
|
|
||||||
}
|
|
18
doGui.go
18
doGui.go
|
@ -28,10 +28,10 @@ func doGui() {
|
||||||
grid := win.Group.RawGrid()
|
grid := win.Group.RawGrid()
|
||||||
if me.forge.Config.GetPathLock() {
|
if me.forge.Config.GetPathLock() {
|
||||||
me.goSrcPwd = gadgets.NewOneLiner(grid, "Working Directory")
|
me.goSrcPwd = gadgets.NewOneLiner(grid, "Working Directory")
|
||||||
me.goSrcPwd.SetText(me.forge.GetGoSrc())
|
me.goSrcPwd.SetText(me.forge.Config.ReposDir)
|
||||||
} else {
|
} else {
|
||||||
me.goSrcEdit = gadgets.NewBasicEntry(grid, "Working Directory")
|
me.goSrcEdit = gadgets.NewBasicEntry(grid, "Working Directory")
|
||||||
me.goSrcEdit.SetText(me.forge.GetGoSrc())
|
me.goSrcEdit.SetText(me.forge.Config.ReposDir)
|
||||||
me.goSrcEdit.Custom = func() {
|
me.goSrcEdit.Custom = func() {
|
||||||
log.Info("updating text to", me.goSrcEdit.String())
|
log.Info("updating text to", me.goSrcEdit.String())
|
||||||
}
|
}
|
||||||
|
@ -132,13 +132,13 @@ func makeStandardReposGrid(pb *gitpb.Repos) *gitpb.ReposTable {
|
||||||
t := pb.NewTable("testDirty")
|
t := pb.NewTable("testDirty")
|
||||||
t.NewUuid()
|
t.NewUuid()
|
||||||
sf := t.AddStringFunc("repo", func(r *gitpb.Repo) string {
|
sf := t.AddStringFunc("repo", func(r *gitpb.Repo) string {
|
||||||
return r.GetGoPath()
|
return r.GetNamespace()
|
||||||
})
|
})
|
||||||
// t.Custom = func() {
|
// t.Custom = func() {
|
||||||
// log.Info("close grid?")
|
// log.Info("close grid?")
|
||||||
// }
|
// }
|
||||||
sf.Custom = func(r *gitpb.Repo) {
|
sf.Custom = func(r *gitpb.Repo) {
|
||||||
log.Info("do button click on", r.GetGoPath())
|
log.Info("do button click on", r.GetNamespace())
|
||||||
}
|
}
|
||||||
t.AddTimeFunc("age", func(repo *gitpb.Repo) time.Time {
|
t.AddTimeFunc("age", func(repo *gitpb.Repo) time.Time {
|
||||||
return repo.NewestTime()
|
return repo.NewestTime()
|
||||||
|
@ -197,7 +197,7 @@ func findMergeToMaster() *gitpb.Repos {
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
|
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
if me.forge.Config.IsReadOnly(repo.GetNamespace()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -215,7 +215,7 @@ func findMergeToMaster() *gitpb.Repos {
|
||||||
// everything is normal
|
// everything is normal
|
||||||
} else {
|
} else {
|
||||||
repo.State = "DEVEL < MASTER"
|
repo.State = "DEVEL < MASTER"
|
||||||
log.Info("SERIOUS ERROR. DEVEL BRANCH IS BEHIND MASTER", repo.GetGoPath())
|
log.Info("SERIOUS ERROR. DEVEL BRANCH IS BEHIND MASTER", repo.GetNamespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
// this sees if devel has patches for master. If it does, add it to me.found
|
// this sees if devel has patches for master. If it does, add it to me.found
|
||||||
|
@ -247,7 +247,7 @@ func mergeDevelToMaster(doit bool) {
|
||||||
all := found.SortByFullPath()
|
all := found.SortByFullPath()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
log.Info("repo:", repo.GetGoPath())
|
log.Info("repo:", repo.GetNamespace())
|
||||||
if result, err := repo.MergeToMaster(); err == nil {
|
if result, err := repo.MergeToMaster(); err == nil {
|
||||||
log.Warn("THINGS SEEM OK", repo.GetFullPath())
|
log.Warn("THINGS SEEM OK", repo.GetFullPath())
|
||||||
for _, line := range result.Stdout {
|
for _, line := range result.Stdout {
|
||||||
|
@ -298,10 +298,10 @@ func mergeUserToDevel(doit bool) {
|
||||||
|
|
||||||
b1 := repo.CountDiffObjects(bruser, brdevel) // should be zero
|
b1 := repo.CountDiffObjects(bruser, brdevel) // should be zero
|
||||||
if b1 == 0 {
|
if b1 == 0 {
|
||||||
// log.Info("User is already merged into Devel", repo.GetGoPath(), cmd)
|
// log.Info("User is already merged into Devel", repo.GetNamespace(), cmd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("merging user into devel repo:", repo.GetGoPath())
|
log.Info("merging user into devel repo:", repo.GetNamespace())
|
||||||
if result, err := repo.MergeToDevel(); err == nil {
|
if result, err := repo.MergeToDevel(); err == nil {
|
||||||
log.Warn("THINGS SEEM OK", repo.GetFullPath())
|
log.Warn("THINGS SEEM OK", repo.GetFullPath())
|
||||||
for _, line := range result.Stdout {
|
for _, line := range result.Stdout {
|
||||||
|
|
92
doMerge.go
92
doMerge.go
|
@ -4,11 +4,61 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func doMerge() error {
|
||||||
|
if argv.All == true {
|
||||||
|
start := time.Now()
|
||||||
|
repos, err := doMergeDevel()
|
||||||
|
dur := time.Since(start)
|
||||||
|
if err != nil {
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
log.Printf("Merged %d devel branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
||||||
|
|
||||||
|
start = time.Now()
|
||||||
|
repos, err = doMergeMaster()
|
||||||
|
dur = time.Since(start)
|
||||||
|
if err != nil {
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
log.Printf("Merged %d master branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
if argv.Merge.Devel != nil {
|
||||||
|
start := time.Now()
|
||||||
|
repos, err := doMergeDevel()
|
||||||
|
dur := time.Since(start)
|
||||||
|
if err != nil {
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
log.Printf("Merged %d devel branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
if argv.Merge.Master != nil {
|
||||||
|
start := time.Now()
|
||||||
|
repos, err := doMergeMaster()
|
||||||
|
dur := time.Since(start)
|
||||||
|
if err != nil {
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
log.Printf("Merged %d master branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
repo := findCurrentPwdRepoOrDie()
|
||||||
|
if err := repoMergeToDevel(repo); err != nil {
|
||||||
|
badRepoExit(repo, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func doMergeReport() *forgepb.Patches {
|
func doMergeReport() *forgepb.Patches {
|
||||||
found := forgepb.NewPatches()
|
found := forgepb.NewPatches()
|
||||||
for repo := range me.forge.Repos.IterAll() {
|
for repo := range me.forge.Repos.IterAll() {
|
||||||
|
@ -31,14 +81,14 @@ func doMergeDevel() (*gitpb.Repos, error) {
|
||||||
found := findMergeToDevel()
|
found := findMergeToDevel()
|
||||||
for repo := range found.IterAll() {
|
for repo := range found.IterAll() {
|
||||||
if repo.CheckDirty() {
|
if repo.CheckDirty() {
|
||||||
log.Info("repo is dirty", repo.GetGoPath())
|
log.Info("repo is dirty", repo.GetFullPath())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Infof("%s starting git merge\n", repo.FullPath)
|
log.Infof("%s starting git merge\n", repo.FullPath)
|
||||||
if repo.CheckoutDevel() {
|
if repo.CheckoutDevel() {
|
||||||
log.Info("checkout devel failed", repo.GetGoPath())
|
log.Info("checkout devel failed", repo.GetGoPath())
|
||||||
err = log.Errorf("checkout devel failed")
|
err = log.Errorf("checkout devel failed")
|
||||||
break
|
badExit(err)
|
||||||
}
|
}
|
||||||
// hash differences when merging user into devel branch
|
// hash differences when merging user into devel branch
|
||||||
out := repo.GetBranchDifferences(repo.GetDevelBranchName(), repo.GetUserBranchName())
|
out := repo.GetBranchDifferences(repo.GetDevelBranchName(), repo.GetUserBranchName())
|
||||||
|
@ -50,17 +100,44 @@ func doMergeDevel() (*gitpb.Repos, error) {
|
||||||
err = log.Errorf("merge from user failed")
|
err = log.Errorf("merge from user failed")
|
||||||
// log.Info(strings.Join(r.Stdout, "\n"))
|
// log.Info(strings.Join(r.Stdout, "\n"))
|
||||||
// log.Info(strings.Join(r.Stderr, "\n"))
|
// log.Info(strings.Join(r.Stderr, "\n"))
|
||||||
break
|
badExit(err)
|
||||||
}
|
}
|
||||||
done.Append(repo)
|
done.Append(repo)
|
||||||
|
config.SetChanged("repos", true)
|
||||||
}
|
}
|
||||||
return done, err
|
return done, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func repoMergeToDevel(repo *gitpb.Repo) error {
|
||||||
|
if repo.CheckDirty() {
|
||||||
|
return log.Errorf("can not merge. repo is dirty")
|
||||||
|
}
|
||||||
|
log.Infof("%s starting git merge\n", repo.FullPath)
|
||||||
|
if repo.CheckoutDevel() {
|
||||||
|
log.Info("checkout devel failed", repo.GetGoPath())
|
||||||
|
err := log.Errorf("checkout devel failed")
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
// hash differences when merging user into devel branch
|
||||||
|
out := repo.GetBranchDifferences(repo.GetDevelBranchName(), repo.GetUserBranchName())
|
||||||
|
for i, hash := range out {
|
||||||
|
log.Info("MERGE HASH FROM USER TO DEVEL", i, hash)
|
||||||
|
}
|
||||||
|
if _, err := repo.MergeToDevel(); err != nil {
|
||||||
|
log.Info("merge from user failed", repo.GetGoPath(), err)
|
||||||
|
// err := log.Errorf("merge from user failed")
|
||||||
|
// log.Info(strings.Join(r.Stdout, "\n"))
|
||||||
|
// log.Info(strings.Join(r.Stderr, "\n"))
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
config.SetChanged("repos", true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func doMergeMaster() (*gitpb.Repos, error) {
|
func doMergeMaster() (*gitpb.Repos, error) {
|
||||||
var err error
|
var err error
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_MASTER // disable "normal" mode if set
|
setForgeMode(forgepb.ForgeMode_MASTER)
|
||||||
configSave = true
|
|
||||||
done := gitpb.NewRepos()
|
done := gitpb.NewRepos()
|
||||||
found := findMergeToMaster()
|
found := findMergeToMaster()
|
||||||
for repo := range found.IterAll() {
|
for repo := range found.IterAll() {
|
||||||
|
@ -73,7 +150,7 @@ func doMergeMaster() (*gitpb.Repos, error) {
|
||||||
if repo.CheckoutMaster() {
|
if repo.CheckoutMaster() {
|
||||||
log.Info("checkout devel failed", repo.GetGoPath())
|
log.Info("checkout devel failed", repo.GetGoPath())
|
||||||
err = log.Errorf("checkout devel failed")
|
err = log.Errorf("checkout devel failed")
|
||||||
break
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := repo.MergeToMaster(); err != nil {
|
if _, err := repo.MergeToMaster(); err != nil {
|
||||||
|
@ -81,10 +158,11 @@ func doMergeMaster() (*gitpb.Repos, error) {
|
||||||
err = log.Errorf("merge from user failed")
|
err = log.Errorf("merge from user failed")
|
||||||
// log.Info(strings.Join(r.Stdout, "\n"))
|
// log.Info(strings.Join(r.Stdout, "\n"))
|
||||||
// log.Info(strings.Join(r.Stderr, "\n"))
|
// log.Info(strings.Join(r.Stderr, "\n"))
|
||||||
break
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
done.Append(repo)
|
done.Append(repo)
|
||||||
|
config.SetChanged("repos", true)
|
||||||
}
|
}
|
||||||
return done, err
|
return done, err
|
||||||
}
|
}
|
||||||
|
|
58
doNormal.go
58
doNormal.go
|
@ -6,8 +6,11 @@ package main
|
||||||
// checks that repos are in a "normal" state
|
// checks that repos are in a "normal" state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
"go.wit.com/lib/gui/shell"
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
|
@ -35,7 +38,7 @@ func doNormal() bool {
|
||||||
log.Info("Some repos are not in a 'normal' state. error count =", count)
|
log.Info("Some repos are not in a 'normal' state. error count =", count)
|
||||||
log.Info("TODO: list the repos here. forge patch repos?")
|
log.Info("TODO: list the repos here. forge patch repos?")
|
||||||
dumpWorkRepos()
|
dumpWorkRepos()
|
||||||
configSave = true
|
config.SetChanged("repos", true)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -47,28 +50,63 @@ func doNormal() bool {
|
||||||
// this needs to run each time in case repos were added manually by the user
|
// this needs to run each time in case repos were added manually by the user
|
||||||
// this also verifies that
|
// this also verifies that
|
||||||
func checkNormalRepoState(repo *gitpb.Repo) error {
|
func checkNormalRepoState(repo *gitpb.Repo) error {
|
||||||
|
var err error
|
||||||
|
tmp := filepath.Join(me.forge.Config.ReposDir, repo.GetNamespace())
|
||||||
|
if tmp != repo.FullPath {
|
||||||
|
log.Infof("%s != %s\n", repo.FullPath, tmp)
|
||||||
|
if strings.HasPrefix(repo.FullPath, me.forge.Config.ReposDir) {
|
||||||
|
tmp = strings.TrimPrefix(repo.FullPath, me.forge.Config.ReposDir)
|
||||||
|
tmp = strings.Trim(tmp, "/")
|
||||||
|
repo.Namespace = tmp
|
||||||
|
err = log.Errorf("namespace set to filepath")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log.Infof("%s == %s\n", repo.FullPath, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = strings.Trim(repo.Namespace, "/")
|
||||||
|
if tmp != repo.Namespace {
|
||||||
|
err = log.Errorf("junk in ns %s", repo.Namespace)
|
||||||
|
repo.Namespace = tmp
|
||||||
|
}
|
||||||
|
|
||||||
if repo.GetMasterBranchName() == "" {
|
if repo.GetMasterBranchName() == "" {
|
||||||
me.forge.VerifyBranchNames(repo)
|
me.forge.VerifyBranchNames(repo)
|
||||||
configSave = true
|
|
||||||
log.Info("ABNORMAL: master branch name was blank in", repo.GetFullPath())
|
log.Info("ABNORMAL: master branch name was blank in", repo.GetFullPath())
|
||||||
}
|
}
|
||||||
if repo.GetMasterBranchName() == "" {
|
if repo.GetMasterBranchName() == "" {
|
||||||
return log.Errorf("master branch name blank")
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
err = log.Errorf("master branch name blank")
|
||||||
}
|
}
|
||||||
if repo.GetDevelBranchName() == "" {
|
if repo.GetDevelBranchName() == "" {
|
||||||
return log.Errorf("devel branch name blank")
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
err = log.Errorf("devel branch name blank")
|
||||||
}
|
}
|
||||||
if repo.GetUserBranchName() == "" {
|
if repo.GetUserBranchName() == "" {
|
||||||
return log.Errorf("user branch name blank")
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
err = log.Errorf("user branch name blank")
|
||||||
|
}
|
||||||
|
if repo.GetGoPath() == repo.GetNamespace() {
|
||||||
|
// log.Info(repo.FullPath, "gopath == namespace", repo.GetGoPath(), repo.GetNamespace())
|
||||||
|
} else {
|
||||||
|
log.Info(repo.FullPath, "gopath != namespace", repo.GetGoPath(), repo.GetNamespace())
|
||||||
}
|
}
|
||||||
repo.MakeLocalDevelBranch()
|
repo.MakeLocalDevelBranch()
|
||||||
|
|
||||||
|
repo.VerifyRemoteAndLocalBranches(repo.GetDevelBranchName())
|
||||||
|
repo.VerifyRemoteAndLocalBranches(repo.GetMasterBranchName())
|
||||||
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
||||||
configSave = true
|
log.Infof("changing to user(%s) branch: %s\n", repo.GetUserBranchName(), repo.FullPath)
|
||||||
log.Info("changing to user branch", repo.FullPath)
|
|
||||||
repo.CheckoutUser()
|
repo.CheckoutUser()
|
||||||
repo.Reload()
|
repo.ReloadCheck()
|
||||||
return log.Errorf("now on user branch")
|
err = log.Errorf("now on user branch")
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
if me.forge.Config.IsReadOnly(repo.GetGoPath()) != repo.GetReadOnly() {
|
||||||
|
repo.ReadOnly = me.forge.Config.IsReadOnly(repo.GetGoPath())
|
||||||
|
log.Info("damnit", repo.FullPath)
|
||||||
|
err = log.Errorf("readonly bit wrong")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
123
doPatch.go
123
doPatch.go
|
@ -45,7 +45,16 @@ func doPatchSubmit() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, _, err = pset.Patches.HttpPostVerbose(myServer(), "new")
|
if pset.Patches == nil {
|
||||||
|
log.Info("pset.Patches == nil")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pset.Patches.Len() == 0 {
|
||||||
|
log.Info("did not find any patches")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
pset.PrintTable()
|
||||||
|
_, _, err = pset.HttpPost(myServer(), "new")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +73,7 @@ func doPatch() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Patch.Get != nil {
|
if argv.Patch.Get != nil {
|
||||||
psets := forgepb.NewPatchsets()
|
psets := forgepb.NewSets()
|
||||||
newpb, _, _ := psets.HttpPostVerbose(myServer(), "get")
|
newpb, _, _ := psets.HttpPostVerbose(myServer(), "get")
|
||||||
newpb.PrintTable()
|
newpb.PrintTable()
|
||||||
me.forge.Patchsets = newpb
|
me.forge.Patchsets = newpb
|
||||||
|
@ -92,66 +101,80 @@ func doPatch() error {
|
||||||
|
|
||||||
if argv.Patch.List != nil {
|
if argv.Patch.List != nil {
|
||||||
var changed bool
|
var changed bool
|
||||||
newpatches := forgepb.NewPatches()
|
newpatches := new(forgepb.Set)
|
||||||
|
newpatches.Patches = forgepb.NewPatches()
|
||||||
for pset := range me.forge.Patchsets.IterAll() {
|
for pset := range me.forge.Patchsets.IterAll() {
|
||||||
log.Info(pset.Uuid)
|
pset.PrintTable()
|
||||||
for patch := range pset.Patches.IterAll() {
|
for patch := range pset.Patches.IterAll() {
|
||||||
if setNewCommitHash(patch) {
|
changed = true
|
||||||
changed = true
|
if patch.NewHash == "" || patch.NewHash == "na" {
|
||||||
}
|
if newpatches.Patches.AppendByPatchId(patch) {
|
||||||
if patch.NewHash == "na" {
|
log.Info("patchId added here", patch.PatchId)
|
||||||
newpatches.Append(patch)
|
} else {
|
||||||
log.Info("apply this patch?")
|
log.Info("patchId already here", patch.PatchId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := setNewCommitHash(patch); err != nil {
|
||||||
|
log.Infof("%s bad check on patch failure %v\n", patch.Filename, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("newhash set already here", patch.PatchId, patch.NewHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
for patch := range pset.Patches.IterAll() {
|
|
||||||
if repo, ok := me.forge.IsPatchApplied(patch); ok {
|
|
||||||
log.Info("\tfound patch in repo", repo.Namespace, patch.Filename)
|
|
||||||
} else {
|
|
||||||
log.Info("\tdid not find patch", patch.CommitHash, patch.NewHash, patch.Filename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
if changed {
|
if changed {
|
||||||
if err := me.forge.SavePatchsets(); err != nil {
|
if err := me.forge.SavePatchsets(); err != nil {
|
||||||
log.Warn("savePatchsets() failed", err)
|
log.Warn("savePatchsets() failed", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
me.forge.Patchsets.PrintTable()
|
log.Info("NEW PATCHES TABLE")
|
||||||
if newpatches.Len() != 0 {
|
newpatches.PrintTable()
|
||||||
for patch := range newpatches.IterAll() {
|
for patch := range newpatches.Patches.IterAll() {
|
||||||
log.Info("new patch:", patch.CommitHash, patch.NewHash, patch.Filename)
|
if err := setNewCommitHash(patch); err == nil {
|
||||||
repo := me.forge.FindByGoPath(patch.Namespace)
|
log.Info("newhash set already here", patch.PatchId, patch.NewHash)
|
||||||
if repo == nil {
|
continue
|
||||||
log.Info("\tCould not find namespace:", patch.Namespace)
|
}
|
||||||
continue
|
log.Infof("%s is new\n", patch.Filename)
|
||||||
}
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
if fhelp.QuestionUser("apply this patch?") {
|
if repo == nil {
|
||||||
newhash, err := applyAndTrackPatch(repo, patch)
|
log.Info("\tCould not find namespace:", patch.Namespace)
|
||||||
log.Info("apply results:", newhash, err)
|
continue
|
||||||
}
|
}
|
||||||
|
if fhelp.QuestionUser("apply this patch?") {
|
||||||
|
newhash, err := applyAndTrackPatch(repo, patch)
|
||||||
|
log.Info("apply results:", newhash, err)
|
||||||
}
|
}
|
||||||
return log.Errorf("patches need to be applied")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return doPatchList()
|
|
||||||
applied := findApplied()
|
|
||||||
if applied == nil || applied.Len() == 0 {
|
|
||||||
log.Info("no patches have been appled to the devel branch yet")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// for patch := range applied.IterAll() {
|
|
||||||
// log.Info("SEND APPLIED: newhash:", patch.NewHash, "commithash:", patch.CommitHash, "patch", patch.Namespace)
|
|
||||||
// }
|
|
||||||
newpb, _, err := applied.HttpPostVerbose(myServer(), "applied")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
newpb.PrintTable()
|
|
||||||
return nil
|
return nil
|
||||||
|
/*
|
||||||
|
if newpatches.Len() != 0 {
|
||||||
|
for patch := range newpatches.IterAll() {
|
||||||
|
log.Info("new patch:", patch.CommitHash, patch.NewHash, patch.Filename)
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("\tCould not find namespace:", patch.Namespace)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return log.Errorf("patches need to be applied")
|
||||||
|
}
|
||||||
|
|
||||||
|
// return doPatchList()
|
||||||
|
applied := findApplied()
|
||||||
|
if applied == nil || applied.Len() == 0 {
|
||||||
|
log.Info("no patches have been appled to the devel branch yet")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// for patch := range applied.IterAll() {
|
||||||
|
// log.Info("SEND APPLIED: newhash:", patch.NewHash, "commithash:", patch.CommitHash, "patch", patch.Namespace)
|
||||||
|
// }
|
||||||
|
newpb, _, err := applied.HttpPostVerbose(myServer(), "applied")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newpb.PrintTable()
|
||||||
|
return nil
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing, show patches & dirty repos
|
// if nothing, show patches & dirty repos
|
||||||
|
@ -184,7 +207,7 @@ func dumpWorkRepos() bool {
|
||||||
|
|
||||||
// returns bad if patches can not be applied
|
// returns bad if patches can not be applied
|
||||||
// logic is not great here but it was a first pass
|
// logic is not great here but it was a first pass
|
||||||
func dumpPatchset(pset *forgepb.Patchset) bool {
|
func dumpPatchset(pset *forgepb.Set) bool {
|
||||||
// don't even bother to continue if we already know it's broken
|
// don't even bother to continue if we already know it's broken
|
||||||
if pset.State == "BROKEN" {
|
if pset.State == "BROKEN" {
|
||||||
log.Printf("Patchset Name: %-24s Author: %s <%s> IS BAD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail())
|
log.Printf("Patchset Name: %-24s Author: %s <%s> IS BAD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail())
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the GPL 3.0
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// checks that repos are in a "normal" state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/fhelp"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FindRepoByFullPath(wd string) *gitpb.Repo {
|
||||||
|
for repo := range me.forge.Repos.IterAll() {
|
||||||
|
if repo.FullPath == wd {
|
||||||
|
return repo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findCurrentPwdRepoOrDie() *gitpb.Repo {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
repo := FindRepoByFullPath(wd)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("Could not find repo:", wd)
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
return repo
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTag() error {
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
if argv.Tag.List != nil {
|
||||||
|
repo := findCurrentPwdRepoOrDie()
|
||||||
|
|
||||||
|
tagTablePB := makeTagTablePB(repo, repo.Tags)
|
||||||
|
// tbox := win.Bottom.Box().SetProgName("TBOX")
|
||||||
|
// t.SetParent(tbox)
|
||||||
|
tagTablePB.MakeTable()
|
||||||
|
tagTablePB.PrintTable()
|
||||||
|
log.Info("list tags here", repo.Namespace)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if argv.Tag.Delete != "" {
|
||||||
|
repo := FindRepoByFullPath(wd)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("Could not find repo:", wd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the git tag already exists somehow
|
||||||
|
/*
|
||||||
|
if !repo.LocalTagExists(testtag) {
|
||||||
|
log.Info("Tag", testtag, "does not exist")
|
||||||
|
return log.Errorf("%s TAG DOES NOT EXIST %s", repo.FullPath, testtag)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
testtag := argv.Tag.Delete
|
||||||
|
if !argv.Force {
|
||||||
|
if !fhelp.QuestionUser(log.Sprintf("delete tag '%s'?", testtag)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("Delete tag here", testtag)
|
||||||
|
|
||||||
|
// delete local and remote tag
|
||||||
|
repo.RunVerbose([]string{"git", "tag", "--delete", testtag})
|
||||||
|
repo.RunVerbose([]string{"git", "push", "--delete", "origin", testtag})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("do other tag stuff here")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTagTablePB(repo *gitpb.Repo, pb *gitpb.GitTags) *gitpb.GitTagsTable {
|
||||||
|
t := pb.NewTable("tagList")
|
||||||
|
t.NewUuid()
|
||||||
|
|
||||||
|
col := t.AddHash()
|
||||||
|
col.Width = 12
|
||||||
|
|
||||||
|
col = t.AddStringFunc("bashash", func(tag *gitpb.GitTag) string {
|
||||||
|
_, base := filepath.Split(tag.Refname)
|
||||||
|
cmd, err := repo.RunStrict([]string{"git", "log", "-1", base, "--format=%H"})
|
||||||
|
if err != nil {
|
||||||
|
return "err"
|
||||||
|
}
|
||||||
|
if len(cmd.Stdout) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return cmd.Stdout[0]
|
||||||
|
})
|
||||||
|
col.Width = 12
|
||||||
|
|
||||||
|
col = t.AddTimeFunc("ctime", func(tag *gitpb.GitTag) time.Time {
|
||||||
|
// todo
|
||||||
|
return tag.Creatordate.AsTime()
|
||||||
|
})
|
||||||
|
col.Width = 4
|
||||||
|
|
||||||
|
col = t.AddTimeFunc("age", func(repo *gitpb.GitTag) time.Time {
|
||||||
|
// todo
|
||||||
|
return time.Now()
|
||||||
|
})
|
||||||
|
col.Width = 4
|
||||||
|
|
||||||
|
col = t.AddStringFunc("Ref Name", func(r *gitpb.GitTag) string {
|
||||||
|
_, ref := filepath.Split(r.GetRefname())
|
||||||
|
return ref
|
||||||
|
})
|
||||||
|
col.Width = 16
|
||||||
|
|
||||||
|
col = t.AddSubject()
|
||||||
|
col.Width = -1
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
19
doc.go
19
doc.go
|
@ -3,20 +3,14 @@ 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'.
|
forge only executes the 'git' command. Everything it does, you can run by hand with 'git'.
|
||||||
|
|
||||||
forge v0.22.138-6-gaea7f16 Built on 2025.09.03_1935
|
|
||||||
Usage: forge [--debugger] [--logger] [--no-gui] [--gui GUI] [--gui-file GUI-FILE] [--gui-build] [--gui-verbose] [--gui-check-plugin GUI-CHECK-PLUGIN] [--connect CONNECT] [--all] [--build BUILD] [--install INSTALL] [--forge-rebuild] [--force] [--verbose] [--bash] [--auto-complete AUTO-COMPLETE] <command> [<args>]
|
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
--debugger open the debugger window
|
--debugger open the debugger window
|
||||||
--logger open the log.* control window
|
--logger open the log.* control window
|
||||||
--no-gui ignore all these gui problems
|
--gui GUI select the plugin (andlabs,gocui,etc)
|
||||||
--gui GUI Use this gui toolkit [andlabs,gocui,nocui,stdin]
|
|
||||||
--gui-file GUI-FILE Use a specific plugin.so file
|
|
||||||
--gui-build attempt to build the GUI plugins
|
|
||||||
--gui-verbose enable all logging
|
--gui-verbose enable all logging
|
||||||
--gui-check-plugin GUI-CHECK-PLUGIN
|
--bash generate bash completion
|
||||||
hack to verify GO plugins load
|
--bash generate bash completion
|
||||||
--connect CONNECT forge url
|
--connect CONNECT forge url
|
||||||
--all git commit --all
|
--all git commit --all
|
||||||
--build BUILD build a repo
|
--build BUILD build a repo
|
||||||
|
@ -24,25 +18,24 @@ Options:
|
||||||
--forge-rebuild download and rebuild forge
|
--forge-rebuild download and rebuild forge
|
||||||
--force try to strong arm things
|
--force try to strong arm things
|
||||||
--verbose show more output
|
--verbose show more output
|
||||||
--bash generate bash completion
|
|
||||||
--auto-complete AUTO-COMPLETE
|
|
||||||
todo: move this to go-arg
|
|
||||||
--help, -h display this help and exit
|
--help, -h display this help and exit
|
||||||
--version display version and exit
|
--version display version and exit
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
|
|
||||||
|
help New to forge? This is for you.'
|
||||||
checkout switch branches using 'git checkout'
|
checkout switch branches using 'git checkout'
|
||||||
clean start over at the beginning
|
clean start over at the beginning
|
||||||
commit 'git commit' but errors out if on wrong branch
|
commit 'git commit' but errors out if on wrong branch
|
||||||
config show your .config/forge/ settings
|
config show your .config/forge/ settings
|
||||||
debug debug forge
|
|
||||||
dirty show dirty git repos
|
dirty show dirty git repos
|
||||||
fetch run 'git fetch master'
|
fetch run 'git fetch master'
|
||||||
|
gui open the gui
|
||||||
list print a table of the current repos
|
list print a table of the current repos
|
||||||
merge merge branches
|
merge merge branches
|
||||||
normal set every repo to the default state for software development
|
normal set every repo to the default state for software development
|
||||||
patch make patchsets
|
patch make patchsets
|
||||||
pull run 'git pull'
|
pull run 'git pull'
|
||||||
|
tag manage git tags
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
4
exit.go
4
exit.go
|
@ -23,11 +23,11 @@ func okExit(thing string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func badExit(err error) {
|
func badExit(err error) {
|
||||||
log.Info("forge failed: ", err, me.forge.GetGoSrc())
|
log.Info("forge failed: ", err, me.forge.Config.ReposDir)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func badRepoExit(repo *gitpb.Repo, err error) {
|
func badRepoExit(repo *gitpb.Repo, err error) {
|
||||||
log.Printf("forge failed on %s with %v\n", repo.GetGoPath(), err)
|
log.Printf("%s FAILED: %v\n", repo.GetNamespace(), err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,33 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.wit.com/lib/protobuf/forgepb"
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func makeReposTablePB(pb *gitpb.Repos) *gitpb.ReposTable {
|
||||||
|
t := pb.NewTable("quickListRepos")
|
||||||
|
t.NewUuid()
|
||||||
|
|
||||||
|
sf := t.AddStringFunc("Namespace", func(r *gitpb.Repo) string {
|
||||||
|
return r.GetNamespace()
|
||||||
|
})
|
||||||
|
sf.Width = 16
|
||||||
|
|
||||||
|
userVer := t.AddStringFunc("user", func(repo *gitpb.Repo) string {
|
||||||
|
ver := repo.GetUserVersion()
|
||||||
|
return ver
|
||||||
|
})
|
||||||
|
userVer.Width = 4
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
type stdPatchsetTableWin struct {
|
type stdPatchsetTableWin struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
win *gadgets.GenericWindow // the machines gui window
|
win *gadgets.GenericWindow // the machines gui window
|
||||||
box *gui.Node // the machines gui parent box widget
|
box *gui.Node // the machines gui parent box widget
|
||||||
TB *forgepb.PatchsetsTable // the gui table buffer
|
TB *forgepb.SetsTable // the gui table buffer
|
||||||
update bool // if the window should be updated
|
update bool // if the window should be updated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +54,7 @@ func (w *stdPatchsetTableWin) Toggle() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
etimef := func(e *forgepb.Patchset) string {
|
etimef := func(e *forgepb.Set) string {
|
||||||
etime := e.Etime.AsTime()
|
etime := e.Etime.AsTime()
|
||||||
s := etime.Format("2006/01/02 15:04")
|
s := etime.Format("2006/01/02 15:04")
|
||||||
if strings.HasPrefix(s, "1970/") {
|
if strings.HasPrefix(s, "1970/") {
|
||||||
|
@ -49,14 +67,14 @@ func (w *stdPatchsetTableWin) Toggle() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ctimef := func(p *forgepb.Patchset) string {
|
ctimef := func(p *forgepb.Set) string {
|
||||||
ctime := p.Ctime.AsTime()
|
ctime := p.Ctime.AsTime()
|
||||||
return ctime.Format("2006/01/02 15:04")
|
return ctime.Format("2006/01/02 15:04")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func setPatchsetState(p *forgepb.Patchset) {
|
func setPatchsetState(p *forgepb.Set) {
|
||||||
var bad bool
|
var bad bool
|
||||||
var good bool
|
var good bool
|
||||||
var done bool = true
|
var done bool = true
|
||||||
|
@ -155,53 +173,33 @@ func findCommitBySubject(subject string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if PB changed
|
// returns true if PB changed
|
||||||
func setNewCommitHash(patch *forgepb.Patch) bool {
|
func setNewCommitHash(patch *forgepb.Patch) error {
|
||||||
// parts := strings.Fields(patch.Comment)
|
|
||||||
|
|
||||||
repo := me.forge.FindByGoPath(patch.Namespace)
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
if repo == nil {
|
if repo == nil {
|
||||||
log.Info("could not find repo", patch.Namespace)
|
return log.Errorf("could not find repo %s", patch.Namespace)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comment := cleanSubject(patch.Comment)
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
if patch.NewHash == "" {
|
|
||||||
log.Info("init() new patch to 'na' ", patch.NewHash, "commithash:", patch.CommitHash, patch.Namespace, comment)
|
|
||||||
patch.NewHash = "na"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
os.Chdir(repo.GetFullPath())
|
os.Chdir(repo.GetFullPath())
|
||||||
newhash, err := findCommitBySubject(comment)
|
newhash, err := findCommitBySubject(comment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("patch: not found hash:", patch.CommitHash, patch.Namespace, comment, newhash, err)
|
return log.Errorf("patch: not found hash: %s %s %s %s %v", patch.CommitHash, patch.Namespace, comment, newhash, err)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if patch.NewHash == newhash {
|
|
||||||
// patch was already set
|
patchId, err := repo.FindPatchId(newhash)
|
||||||
return false
|
if err != nil {
|
||||||
}
|
return err
|
||||||
if patch.NewHash != "na" {
|
|
||||||
log.Infof("patch: hash MISMATCH %s old=%s new=%s name=%s\n", patch.Namespace, patch.NewHash, newhash, comment)
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
patch.PatchId = patchId
|
||||||
patch.NewHash = newhash
|
patch.NewHash = newhash
|
||||||
|
|
||||||
log.Info("patch: found hash:", patch.CommitHash, newhash, patch.Namespace, comment)
|
log.Info("patch: found hash:", patch.CommitHash, newhash, patch.Namespace, comment)
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func AddAllPatches(notdone *forgepb.Patches, pset *forgepb.Set, full bool) {
|
||||||
func setNewCommitHashLoop(p *forgepb.Patchset) bool {
|
|
||||||
var done bool = true
|
|
||||||
for patch := range p.Patches.IterAll() {
|
|
||||||
setNewCommitHashLoop(patch)
|
|
||||||
}
|
|
||||||
|
|
||||||
return done
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func AddAllPatches(notdone *forgepb.Patches, pset *forgepb.Patchset, full bool) {
|
|
||||||
for patch := range pset.Patches.IterAll() {
|
for patch := range pset.Patches.IterAll() {
|
||||||
comment := cleanSubject(patch.Comment)
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
@ -215,7 +213,7 @@ func AddAllPatches(notdone *forgepb.Patches, pset *forgepb.Patchset, full bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddNotDonePatches(notdone *forgepb.Patches, pset *forgepb.Patchset, full bool) {
|
func AddNotDonePatches(notdone *forgepb.Patches, pset *forgepb.Set, full bool) {
|
||||||
for patch := range pset.Patches.IterAll() {
|
for patch := range pset.Patches.IterAll() {
|
||||||
comment := cleanSubject(patch.Comment)
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
@ -233,7 +231,7 @@ func AddNotDonePatches(notdone *forgepb.Patches, pset *forgepb.Patchset, full bo
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if patch.NewHash != "na" {
|
if patch.NewHash != "" {
|
||||||
log.Info("already applied patch", patch.Namespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
log.Info("already applied patch", patch.Namespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -283,7 +281,7 @@ func findExpired() *forgepb.Patches {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if patch.NewHash != "na" {
|
if patch.NewHash != "" {
|
||||||
log.Info("already applied patch", patch.Namespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
log.Info("already applied patch", patch.Namespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
||||||
found.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
found.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
continue
|
continue
|
||||||
|
|
95
main.go
95
main.go
|
@ -7,14 +7,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.wit.com/dev/alexflint/arg"
|
|
||||||
"go.wit.com/lib/gui/prep"
|
"go.wit.com/lib/gui/prep"
|
||||||
"go.wit.com/lib/gui/shell"
|
|
||||||
"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"
|
||||||
|
@ -46,41 +41,15 @@ func getVersion(repo *gitpb.Repo, name string) string {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
me = new(mainType)
|
me = new(mainType)
|
||||||
prep.Bash(ARGNAME, argv.DoAutoComplete) // this line should be: prep.Bash(argv)
|
me.myGui = prep.Gui() // prepares the GUI package for go-args
|
||||||
me.myGui = prep.Gui() // prepares the GUI package for go-args
|
me.auto = prep.Bash3(&argv) // this line should be: prep.Bash(&argv)
|
||||||
me.pp = arg.MustParse(&argv)
|
|
||||||
|
|
||||||
/*
|
// me.auto = prep.Bash3(argv.DoAutoComplete, &argv) // this line should be: prep.Bash(&argv)
|
||||||
if argv.Bash {
|
// arg.MustParse(&argv) // these three lines are becoming terrible syntax
|
||||||
fhelp.DoBash(ARGNAME)
|
// me.auto = prep.MustParse(&argv) // try to make this work?
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
if len(argv.BashAuto) != 0 {
|
|
||||||
argv.doBashAuto()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
me.urlbase = argv.URL
|
|
||||||
if me.urlbase == "" {
|
|
||||||
me.urlbase = "https://go.wit.com/"
|
|
||||||
}
|
|
||||||
if os.Getenv("FORGE_URL") != "" {
|
|
||||||
me.urlbase = os.Getenv("FORGE_URL")
|
|
||||||
log.Info("got forge url", me.urlbase)
|
|
||||||
}
|
|
||||||
me.urlbase = strings.Trim(me.urlbase, "/") // track down why trailing '/' makes http POST not work
|
|
||||||
|
|
||||||
// internally debugging can be triggered here before Init()
|
me.forge = forgepb.Init() // init forge.pb
|
||||||
if argv.Debug != nil {
|
me.forge.ScanRepoDir() // looks for new dirs, checks existing repos for changes
|
||||||
doDebug()
|
|
||||||
okExit("")
|
|
||||||
}
|
|
||||||
|
|
||||||
if forgepb.FirstTimeUser() {
|
|
||||||
log.Info("You are running forge for the first time here")
|
|
||||||
}
|
|
||||||
// load the ~/.config/forge/ config
|
|
||||||
me.forge = forgepb.Init()
|
|
||||||
|
|
||||||
// initialize patches
|
// initialize patches
|
||||||
doPatchInit()
|
doPatchInit()
|
||||||
|
@ -102,7 +71,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Checkout != nil {
|
if argv.Checkout != nil {
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_MASTER
|
|
||||||
if err := doCheckout(); err != nil {
|
if err := doCheckout(); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
@ -124,17 +92,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Clean != nil {
|
if argv.Clean != nil {
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_CLEAN
|
|
||||||
if argv.Clean.Repo != "" {
|
|
||||||
log.Info("only looking at repo:", argv.Clean.Repo)
|
|
||||||
okExit("")
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Clean.GitReset != nil {
|
|
||||||
doGitReset()
|
|
||||||
okExit("reset")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := doClean(); err != nil {
|
if err := doClean(); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
@ -152,14 +109,18 @@ func main() {
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if argv.Tag != nil {
|
||||||
|
doTag()
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
if argv.Normal != nil {
|
if argv.Normal != nil {
|
||||||
if argv.Normal.On != nil {
|
if argv.Normal.On != nil {
|
||||||
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
||||||
log.Info("you are already in the normal state")
|
log.Info("you are already in the normal state")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_NORMAL
|
setForgeMode(forgepb.ForgeMode_NORMAL)
|
||||||
me.forge.Config.ConfigSave()
|
|
||||||
log.Info("normal mode on")
|
log.Info("normal mode on")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
@ -169,8 +130,7 @@ func main() {
|
||||||
log.Info("you were aleady not in the normal state")
|
log.Info("you were aleady not in the normal state")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_MASTER
|
setForgeMode(forgepb.ForgeMode_DEVEL)
|
||||||
me.forge.Config.ConfigSave()
|
|
||||||
log.Info("normal mode off")
|
log.Info("normal mode off")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
@ -179,8 +139,7 @@ func main() {
|
||||||
log.Infof("all %d repos are on your user branch. It is safe to write code now.\n", me.forge.Repos.Len())
|
log.Infof("all %d repos are on your user branch. It is safe to write code now.\n", me.forge.Repos.Len())
|
||||||
if me.forge.Config.Mode != forgepb.ForgeMode_NORMAL {
|
if me.forge.Config.Mode != forgepb.ForgeMode_NORMAL {
|
||||||
log.Infof("Forge has set the mode to 'Normal'\n")
|
log.Infof("Forge has set the mode to 'Normal'\n")
|
||||||
me.forge.Config.Mode = forgepb.ForgeMode_NORMAL
|
setForgeMode(forgepb.ForgeMode_NORMAL)
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
@ -196,28 +155,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Merge != nil {
|
if argv.Merge != nil {
|
||||||
if argv.Merge.Devel != nil {
|
if err := doMerge(); err != nil {
|
||||||
start := time.Now()
|
badExit(err)
|
||||||
repos, err := doMergeDevel()
|
|
||||||
dur := time.Since(start)
|
|
||||||
if err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
log.Printf("Merged %d devel branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
|
||||||
okExit("")
|
|
||||||
}
|
}
|
||||||
|
okExit("")
|
||||||
if argv.Merge.Master != nil {
|
|
||||||
start := time.Now()
|
|
||||||
repos, err := doMergeMaster()
|
|
||||||
dur := time.Since(start)
|
|
||||||
if err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
log.Printf("Merged %d master branches in %s\n", repos.Len(), shell.FormatDuration(dur))
|
|
||||||
okExit("")
|
|
||||||
}
|
|
||||||
badExit(fmt.Errorf("You must choose which branch to merge to (devel or master)"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Pull != nil {
|
if argv.Pull != nil {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.wit.com/dev/alexflint/arg"
|
|
||||||
"go.wit.com/gui"
|
"go.wit.com/gui"
|
||||||
"go.wit.com/lib/gadgets"
|
"go.wit.com/lib/gadgets"
|
||||||
"go.wit.com/lib/gui/prep"
|
"go.wit.com/lib/gui/prep"
|
||||||
|
@ -28,7 +27,8 @@ func myServer() string {
|
||||||
|
|
||||||
// this app's variables
|
// this app's variables
|
||||||
type mainType struct {
|
type mainType struct {
|
||||||
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
|
// 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
|
forge *forgepb.Forge // for holding the forge protobuf files
|
||||||
myGui *prep.GuiPrep // for initializing the GUI toolkits
|
myGui *prep.GuiPrep // for initializing the GUI toolkits
|
||||||
foundPaths []string // stores gopaths to act on (when doing go-clone)
|
foundPaths []string // stores gopaths to act on (when doing go-clone)
|
||||||
|
|
|
@ -41,10 +41,10 @@ func makeHowtoWin() *gadgets.GenericWindow {
|
||||||
grid.NewLabel("") // a stupid way to add padding
|
grid.NewLabel("") // a stupid way to add padding
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
|
||||||
// howtoWin.Group.NewLabel("Working dir: " + me.forge.GetGoSrc())
|
// howtoWin.Group.NewLabel("Working dir: " + me.forge.Config.ReposDir)
|
||||||
|
|
||||||
grid = howtoWin.Group.RawGrid()
|
grid = howtoWin.Group.RawGrid()
|
||||||
grid.NewButton("Download into "+me.forge.GetGoSrc(), func() {
|
grid.NewButton("Download into "+me.forge.Config.ReposDir, func() {
|
||||||
howtoWin.Disable()
|
howtoWin.Disable()
|
||||||
defer howtoWin.Enable()
|
defer howtoWin.Enable()
|
||||||
downloadForge()
|
downloadForge()
|
||||||
|
|
|
@ -58,34 +58,12 @@ func makePatchesWin(patches *forgepb.Patches) *stdPatchTableWin {
|
||||||
grid.NewLabel(fmt.Sprintf("total repos"))
|
grid.NewLabel(fmt.Sprintf("total repos"))
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
|
||||||
grid.NewButton("Update", func() {
|
|
||||||
log.Info("TODO: doesn't update this window")
|
|
||||||
me.forge.GetPatches()
|
|
||||||
dwin.win.Custom()
|
|
||||||
// loadUpstreamPatchsets()
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("Apply All", func() {
|
grid.NewButton("Apply All", func() {
|
||||||
var count int
|
var count int
|
||||||
all := patches.SortByFilename()
|
all := patches.SortByFilename()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
p := all.Next()
|
p := all.Next()
|
||||||
applyPatchNew(p)
|
applyPatchNew(p)
|
||||||
/*
|
|
||||||
rn := p.Namespace
|
|
||||||
repo := me.forge.FindByGoPath(rn)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("Could not figure out repo path", rn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count += 1
|
|
||||||
if _, err := applyAndTrackPatch(repo, p); err != nil {
|
|
||||||
cmd := []string{"git", "am", "--abort"}
|
|
||||||
err := repo.RunVerbose(cmd)
|
|
||||||
log.Info("warn user of git am error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
log.Info("ALL PATCHES WORKED! count =", count)
|
log.Info("ALL PATCHES WORKED! count =", count)
|
||||||
})
|
})
|
||||||
|
@ -139,11 +117,8 @@ func applyPatchLabel(p *forgepb.Patch) string {
|
||||||
// log.Info("Could not figure out repo path", rn)
|
// log.Info("Could not figure out repo path", rn)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if p.NewHash == "na" {
|
|
||||||
return "git am"
|
|
||||||
}
|
|
||||||
if p.NewHash == "" {
|
if p.NewHash == "" {
|
||||||
return "new"
|
return "git am"
|
||||||
}
|
}
|
||||||
return "done"
|
return "done"
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ func makeReposWin() *stdReposTableWin {
|
||||||
cmd = []string{"git", "branch", "--delete", "--remote", "origin/" + brname}
|
cmd = []string{"git", "branch", "--delete", "--remote", "origin/" + brname}
|
||||||
log.Info(repo.GetGoPath(), cmd)
|
log.Info(repo.GetGoPath(), cmd)
|
||||||
repo.RunVerbose(cmd)
|
repo.RunVerbose(cmd)
|
||||||
repo.Reload()
|
repo.ReloadCheck()
|
||||||
}
|
}
|
||||||
me.forge.SetConfigSave(true)
|
me.forge.SetConfigSave(true)
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
|
|
|
@ -21,8 +21,8 @@ type repoPatchWindow struct {
|
||||||
shelf *gui.Node // the first box in the stack, set as horizontal
|
shelf *gui.Node // the first box in the stack, set as horizontal
|
||||||
grid *gui.Node // the list of available patches
|
grid *gui.Node // the list of available patches
|
||||||
// summary *patchSummary // summary of current patches
|
// summary *patchSummary // summary of current patches
|
||||||
setgrid *gui.Node // the list of each patchset
|
setgrid *gui.Node // the list of each patchset
|
||||||
pset *forgepb.Patchset // the patchset in question
|
pset *forgepb.Set // the patchset in question
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: autogenerate these or make them standared 'gui' package functions
|
// todo: autogenerate these or make them standared 'gui' package functions
|
||||||
|
@ -109,7 +109,7 @@ func makeRepoPatchWindow(repo *gitpb.Repo, fset []*forgepb.Patch) *repoPatchWind
|
||||||
return pw
|
return pw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *repoPatchWindow) addPatchset(grid *gui.Node, pset *forgepb.Patchset) {
|
func (r *repoPatchWindow) addPatchset(grid *gui.Node, pset *forgepb.Set) {
|
||||||
repomap := make(map[*gitpb.Repo][]*forgepb.Patch)
|
repomap := make(map[*gitpb.Repo][]*forgepb.Patch)
|
||||||
repohash := make(map[*gitpb.Repo]string)
|
repohash := make(map[*gitpb.Repo]string)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue