Compare commits
160 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 | |
|
2b3dfe540c | |
|
14bd2c4b0e | |
|
860290fc26 | |
|
c0ec2f359a | |
|
f6bad20818 | |
|
a991a4c187 | |
|
ad2c2ff2ec | |
|
297355f27e | |
|
e62d74f0e6 | |
|
6c6af8707a | |
|
ce813a3450 | |
|
11bf5481c7 | |
|
66802a287f | |
|
c3afc8c2a1 | |
|
cd3ca5dc82 | |
|
2ddba9924c | |
|
d6a562849c | |
|
c55e807262 | |
|
2c7d1de637 | |
|
99de9e31bc | |
|
86eb446408 | |
|
b71471c61e | |
|
ca3a70d623 | |
|
db758bbed2 | |
|
3df2601f27 | |
|
5c6bbcdbb2 | |
|
f6a79c3be8 | |
|
a6c0edb89d | |
|
d99eb81385 | |
|
1087b39f9c | |
|
893c88bbf5 | |
|
e5a2bec217 | |
|
e713541b35 | |
|
7f831e90d2 | |
|
e639f7d7b7 | |
|
790c48e0d0 | |
|
809dfe7fa3 | |
|
04028e6181 | |
|
c5025d25b2 | |
|
e09849b1a2 | |
|
5dbfed7a31 | |
|
c9d732800a | |
|
13aff0d5dc | |
|
4063e03108 | |
|
f789b58389 | |
|
770e6752f1 | |
|
c381a8d179 | |
|
3a5e6ae51c | |
|
78e883a106 | |
|
19ce7eef56 | |
|
05f798dea3 | |
|
5b3764c1b7 | |
|
0517f01aa9 | |
|
7697ab186a | |
|
d2010b859a | |
|
5fec66f97c | |
|
680069d4ca | |
|
b020604931 | |
|
9a32a7fe0b | |
|
7081a04d58 | |
|
b847d9aa6c | |
|
aea7f16891 | |
|
6f4ec05ccb | |
|
e896cae995 | |
|
f6803f07f1 | |
|
30dcc8af9f | |
|
557a5853a4 | |
|
d4e65a581d | |
|
c7a12cbdd3 | |
|
6d249abb44 | |
|
f754a93493 | |
|
a84db9a788 | |
|
731a4d9da8 | |
|
c4252d2103 | |
|
9292eb18fa | |
|
b70417565a | |
|
9bcf2d968c | |
|
a21c117e5b | |
|
86c342b163 | |
|
d8b615f5b9 | |
|
d1573f83ab | |
|
d9ebcefd2f | |
|
b83a5d491f | |
|
eb9dea5dd0 | |
|
43c6af4a8b | |
|
e928cee038 | |
|
f17ccce780 | |
|
31c2a90f02 | |
|
80dd77a6c8 | |
|
12a6696960 | |
|
cf83bbf6ac | |
|
47cd26fbab | |
|
650ecc6aab | |
|
c0e82648db | |
|
2b7257fd2d | |
|
dad2e089c3 | |
|
ffe615ef2a | |
|
456de36547 | |
|
46c617a31a | |
|
ef8240da56 | |
|
d1c9436e45 |
|
@ -1,4 +1,5 @@
|
||||||
*.swp
|
*.swp
|
||||||
|
*.pb
|
||||||
go.mod
|
go.mod
|
||||||
go.sum
|
go.sum
|
||||||
/resources/*.so
|
/resources/*.so
|
||||||
|
|
48
Makefile
48
Makefile
|
@ -6,25 +6,27 @@ 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: gocui
|
default: install-verbose tag
|
||||||
#forge
|
|
||||||
|
tag:
|
||||||
|
forge tag list
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
@GO111MODULE=off go vet
|
@GO111MODULE=off go vet
|
||||||
@echo this go binary package builds okay
|
@echo this go binary package builds okay
|
||||||
|
|
||||||
verbose:
|
|
||||||
GO111MODULE=off go build -v -x \
|
|
||||||
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
|
||||||
|
|
||||||
build: goimports vet plugin
|
build: goimports vet plugin
|
||||||
GO111MODULE=off go build \
|
GO111MODULE=off go build \
|
||||||
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
||||||
|
|
||||||
install: goimports vet plugin
|
install: goimports plugin
|
||||||
GO111MODULE=off go install \
|
GO111MODULE=off go install \
|
||||||
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
||||||
cp -f ~/go/bin/forge ~/go/bin/last.forge # this is a hack so that go-deb can build a .deb file for forge
|
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 plugin
|
||||||
|
GO111MODULE=off go install -v -x \
|
||||||
|
-ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}"
|
||||||
|
|
||||||
install-raw: goimports vet plugin
|
install-raw: goimports vet plugin
|
||||||
go install \
|
go install \
|
||||||
|
@ -34,12 +36,17 @@ plugin:
|
||||||
rm -f resources/*.so
|
rm -f resources/*.so
|
||||||
# -cp ../../toolkits/gocui/gocui.so resources/
|
# -cp ../../toolkits/gocui/gocui.so resources/
|
||||||
|
|
||||||
andlabs: clean install
|
GTK: clean install
|
||||||
forge --gui gocui --gui-verbose --gui-file ../../toolkits/andlabs/andlabs.so
|
forge --gui andlabs
|
||||||
|
|
||||||
gocui: install
|
GTK-verbose: clean install
|
||||||
forge --gui gocui --gui-verbose --gui-file ../../toolkits/gocui/gocui.so >/tmp/forge.log 2>&1
|
forge --gui andlabs --gui-verbose
|
||||||
# forge --gui gocui --gui-verbose --debugger
|
|
||||||
|
CUI: install
|
||||||
|
forge --gui gocui
|
||||||
|
|
||||||
|
CUI-verbose: install
|
||||||
|
forge --gui gocui --gui-verbose >/tmp/forge.log 2>&1
|
||||||
|
|
||||||
goimports:
|
goimports:
|
||||||
reset
|
reset
|
||||||
|
@ -59,16 +66,21 @@ devel:
|
||||||
forge clean devel --force --verbose
|
forge clean devel --force --verbose
|
||||||
|
|
||||||
pull: install
|
pull: install
|
||||||
# forge pull dirty
|
|
||||||
# FORGE_URL="https://forge.grid.wit.com/" forge pull dirty
|
|
||||||
# FORGE_URL="https://forge.grid.wit.com/" forge pull patches
|
|
||||||
FORGE_URL="https://forge.grid.wit.com/" forge pull check
|
FORGE_URL="https://forge.grid.wit.com/" forge pull check
|
||||||
# forge pull patches
|
|
||||||
|
|
||||||
# cloudflare blocks POST due to captcha checks / human detection?
|
# cloudflare blocks POST due to captcha checks / human detection?
|
||||||
# POST must be direct socket. probably for the best anyway
|
# POST must be direct socket. probably for the best anyway
|
||||||
submit:
|
submit:
|
||||||
FORGE_URL="https://forge.grid.wit.com/" forge patch --submit "forge auto commit"
|
FORGE_URL="https://forge.grid.wit.com/" forge patch submit "forge auto commit"
|
||||||
|
|
||||||
commit:
|
commit:
|
||||||
FORGE_URL="https://forge.grid.wit.com/" forge commit --all
|
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
|
||||||
|
|
16
README.md
16
README.md
|
@ -3,7 +3,9 @@
|
||||||
forge is a GUI front end for 'git' designed with the
|
forge is a GUI front end for 'git' designed with the
|
||||||
intent of simplifying federated git development.
|
intent of simplifying federated git development.
|
||||||
|
|
||||||
FORGE NEVER DOES ANYTHING BUT EXEC's 'git'
|
## Install:
|
||||||
|
|
||||||
|
* go install go.wit.com/apps/forge@latest
|
||||||
|
|
||||||
## Theory
|
## Theory
|
||||||
|
|
||||||
|
@ -20,6 +22,10 @@ FORGE NEVER DOES ANYTHING BUT EXEC's 'git'
|
||||||
b) A "devel" branch that is published
|
b) A "devel" branch that is published
|
||||||
c) a "user" branch that can be local only to the developer
|
c) a "user" branch that can be local only to the developer
|
||||||
|
|
||||||
|
## Development Goals
|
||||||
|
|
||||||
|
* have a GUI that also works on the command line
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
This can be used to maintain git repositories
|
This can be used to maintain git repositories
|
||||||
|
@ -31,14 +37,6 @@ expiremental work on federated git
|
||||||
* uses a GUI or the console(console display needs work)
|
* uses a GUI or the console(console display needs work)
|
||||||
* always wrap around 'git' -- it basically just types 'git' commands really fast
|
* always wrap around 'git' -- it basically just types 'git' commands really fast
|
||||||
|
|
||||||
## Development Goals
|
|
||||||
|
|
||||||
* have a GUI that also works on the command line
|
|
||||||
|
|
||||||
## Install:
|
|
||||||
|
|
||||||
* go install go.wit.com/apps/forge@latest
|
|
||||||
|
|
||||||
## building from sources
|
## building from sources
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,16 +3,6 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"go.wit.com/lib/protobuf/forgepb"
|
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// saves the patches in ~/.config/forge/currentpatches/
|
// saves the patches in ~/.config/forge/currentpatches/
|
||||||
func savePatchset(pset *forgepb.Patchset) error {
|
func savePatchset(pset *forgepb.Patchset) error {
|
||||||
|
@ -22,40 +12,10 @@ 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 := findDirty()
|
|
||||||
if found.Len() == 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// From 18ee541f89be2e9f9a91c54873da87885e8ffdf5 Mon Sep 17 00:00:00 2001
|
// From 18ee541f89be2e9f9a91c54873da87885e8ffdf5 Mon Sep 17 00:00:00 2001
|
||||||
// From: Jeff Carr <jcarr@wit.com>
|
// From: Jeff Carr <jcarr@wit.com>
|
||||||
// Date: Sun, 5 Jan 2025 01:18:47 -0600
|
// Date: Sun, 5 Jan 2025 01:18:47 -0600
|
||||||
|
@ -69,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
|
||||||
|
@ -116,9 +39,10 @@ func doRegister(newurl string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
test := strings.TrimSpace(string(body))
|
test := strings.TrimSpace(string(body))
|
||||||
for line := range strings.SplitSeq(test, "\n") {
|
for _, line := range strings.Split(test, "\n") {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
log.Info("server returned:", line)
|
log.Info("server returned:", line)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
109
argv.go
109
argv.go
|
@ -6,6 +6,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/lib/gui/prep"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -15,17 +17,20 @@ import (
|
||||||
var argv args
|
var argv args
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
|
Help *EmptyCmd `arg:"subcommand:help" help:"New to forge? This is for you.'"`
|
||||||
Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch branches using 'git checkout'"`
|
Checkout *CheckoutCmd `arg:"subcommand:checkout" help:"switch branches using 'git checkout'"`
|
||||||
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 *DebugCmd `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"`
|
||||||
List *FindCmd `arg:"subcommand:list" help:"print a table of the current repos"`
|
List *FindCmd `arg:"subcommand:list" help:"print a table of the current repos"`
|
||||||
Merge *MergeCmd `arg:"subcommand:merge" help:"merge branches"`
|
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"`
|
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"`
|
||||||
|
@ -33,13 +38,16 @@ type args struct {
|
||||||
BuildForge bool `arg:"--forge-rebuild" help:"download and rebuild forge"`
|
BuildForge bool `arg:"--forge-rebuild" help:"download and rebuild forge"`
|
||||||
Force bool `arg:"--force" help:"try to strong arm things"`
|
Force bool `arg:"--force" help:"try to strong arm things"`
|
||||||
Verbose bool `arg:"--verbose" help:"show more output"`
|
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 {
|
type EmptyCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NormalCmd struct {
|
||||||
|
On *EmptyCmd `arg:"subcommand:on" help:"turn normal mode on"`
|
||||||
|
Off *EmptyCmd `arg:"subcommand:off" help:"turn normal mode off"`
|
||||||
|
}
|
||||||
|
|
||||||
type CommitCmd struct {
|
type CommitCmd struct {
|
||||||
Submit bool `arg:"--submit" default:"true" help:"submit the patches to forge"`
|
Submit bool `arg:"--submit" default:"true" help:"submit the patches to forge"`
|
||||||
}
|
}
|
||||||
|
@ -47,12 +55,7 @@ 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"`
|
|
||||||
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"`
|
Repo string `arg:"--repo" help:"which repo to look at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,17 +64,28 @@ type CleanDevelCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PatchCmd struct {
|
type PatchCmd struct {
|
||||||
|
Check *EmptyCmd `arg:"subcommand:check" help:"check the state of the patches"`
|
||||||
List *EmptyCmd `arg:"subcommand:list" help:"your downloaded patchsets"`
|
List *EmptyCmd `arg:"subcommand:list" help:"your downloaded patchsets"`
|
||||||
Get *EmptyCmd `arg:"subcommand:get" help:"get the new patchsets"`
|
Get *EmptyCmd `arg:"subcommand:get" help:"get the new patchsets"`
|
||||||
Show *EmptyCmd `arg:"subcommand:show" help:"your pending commits to your code"`
|
Show *EmptyCmd `arg:"subcommand:show" help:"your pending commits to your code"`
|
||||||
Submit string `arg:"--submit" help:"submit your commits"`
|
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 {
|
type PullCmd struct {
|
||||||
Check *EmptyCmd `arg:"subcommand:check" help:"check repo versions"`
|
Check *EmptyCmd `arg:"subcommand:check" help:"check repo versions"`
|
||||||
Dirty *EmptyCmd `arg:"subcommand:dirty" help:"only check dirty repos"`
|
Dirty *EmptyCmd `arg:"subcommand:dirty" help:"only check dirty repos"`
|
||||||
Patches *EmptyCmd `arg:"subcommand:patches" help:"only check repos with patches"`
|
Patches *EmptyCmd `arg:"subcommand:patches" help:"only check repos with patches"`
|
||||||
Sync *SyncCmd `arg:"subcommand:sync" help:"sync repos with upstream"`
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
@ -97,10 +111,6 @@ type ConfigCmd struct {
|
||||||
Register string `arg:"--register" help:"register your git URL (foo.com/mystuff) or (github.com/foo/bar)"`
|
Register string `arg:"--register" help:"register your git URL (foo.com/mystuff) or (github.com/foo/bar)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DebugCmd struct {
|
|
||||||
Config *EmptyCmd `arg:"subcommand:config" help:"used to debug protobuf Marshal() if things go wrong"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CheckoutCmd struct {
|
type CheckoutCmd struct {
|
||||||
User *FindCmd `arg:"subcommand:user" help:"git checkout user"`
|
User *FindCmd `arg:"subcommand:user" help:"git checkout user"`
|
||||||
Devel *FindCmd `arg:"subcommand:devel" help:"git checkout devel"`
|
Devel *FindCmd `arg:"subcommand:devel" help:"git checkout devel"`
|
||||||
|
@ -113,11 +123,6 @@ type MergeCmd struct {
|
||||||
Publish *EmptyCmd `arg:"subcommand:publish" help:"increment versions and publish master branch"`
|
Publish *EmptyCmd `arg:"subcommand:publish" help:"increment versions and publish master branch"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncCmd struct {
|
|
||||||
Clean *EmptyCmd `arg:"subcommand:clean" help:"sync everything to upstream master"`
|
|
||||||
User *EmptyCmd `arg:"subcommand:user" help:"sync everything to user"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DirtyCmd struct {
|
type DirtyCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,19 +149,57 @@ forge -- a tool to manage lots of git repos. forge includes a GUI and TUI.
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (args) doBashHelpDebug() {
|
// handles shell autocomplete
|
||||||
fmt.Fprintln(os.Stderr, "")
|
func DoAutoComplete(pb *prep.Auto) {
|
||||||
fmt.Fprintln(os.Stderr, "hello world")
|
switch pb.Cmd {
|
||||||
var more string
|
case "checkout":
|
||||||
p0 := "0" + argv.BashAuto[0]
|
pb.Autocomplete2("devel master user")
|
||||||
p1 := "1" + argv.BashAuto[1]
|
case "clean":
|
||||||
p2 := "2" + argv.BashAuto[2]
|
pb.Autocomplete2("")
|
||||||
if len(argv.BashAuto[1]) >= 0 {
|
case "commit":
|
||||||
more = "more"
|
pb.Autocomplete2("--all")
|
||||||
|
case "config":
|
||||||
|
fmt.Println("add fix list")
|
||||||
|
case "dirty":
|
||||||
|
fmt.Println("")
|
||||||
|
case "gui":
|
||||||
|
fmt.Println("")
|
||||||
|
case "--gui":
|
||||||
|
pb.Autocomplete2("andlabs gocui")
|
||||||
|
case "list":
|
||||||
|
pb.Autocomplete2("--mine --favorites --dirty")
|
||||||
|
case "merge":
|
||||||
|
pb.Autocomplete2("devel master --all")
|
||||||
|
case "normal":
|
||||||
|
pb.Autocomplete2("on off")
|
||||||
|
case "pull":
|
||||||
|
pb.Autocomplete2("--force check")
|
||||||
|
case "patch":
|
||||||
|
fmt.Println("check get list repos submit show")
|
||||||
|
case "tag":
|
||||||
|
fmt.Println("list --delete clean")
|
||||||
|
default:
|
||||||
|
if pb.Cmd == "" {
|
||||||
|
pb.Autocomplete2("help list checkout clean commit dirty fetch gui normal merge patch pull tag --gui")
|
||||||
} else {
|
} else {
|
||||||
more = "less"
|
pb.Autocomplete2("list checkout clean commit dirty normal merge tag")
|
||||||
}
|
}
|
||||||
p1a := fmt.Sprintf("1a.%s.%+v.\n", argv.BashAuto[1], len(argv.BashAuto[1]))
|
}
|
||||||
fmt.Fprintln(os.Stderr, "pull something else", argv.BashAuto, len(argv.BashAuto), p0, p1, p2, p1a, "end", more)
|
os.Exit(0)
|
||||||
fmt.Fprintln(os.Stderr, "")
|
}
|
||||||
|
|
||||||
|
func (args) Appname() string {
|
||||||
|
return ARGNAME
|
||||||
|
}
|
||||||
|
|
||||||
|
func ifBlank(arg string) bool {
|
||||||
|
if arg == "''" {
|
||||||
|
// if empty, the user has not typed something
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a args) DoAutoComplete(autoArgv *prep.Auto) {
|
||||||
|
DoAutoComplete(autoArgv)
|
||||||
}
|
}
|
||||||
|
|
123
argvAutoshell.go
123
argvAutoshell.go
|
@ -1,123 +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 (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
handles shell autocomplete
|
|
||||||
*/
|
|
||||||
|
|
||||||
// used for shell auto completion
|
|
||||||
// var ARGNAME string = "forge" // todo: get this from $0 ?
|
|
||||||
|
|
||||||
func deleteMatch() {
|
|
||||||
// f := forgedb.InitSimple()
|
|
||||||
fmt.Println("go.wit.com/lib/gui/repostatus todo: need to do this")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (args) doBashAuto() {
|
|
||||||
argv.doBashHelp()
|
|
||||||
switch argv.BashAuto[0] {
|
|
||||||
case "checkout":
|
|
||||||
fmt.Println("user devel master ")
|
|
||||||
case "clean":
|
|
||||||
// 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.Println("devel user")
|
|
||||||
case "commit":
|
|
||||||
fmt.Println("--all")
|
|
||||||
case "config":
|
|
||||||
fmt.Println("add fix list debug")
|
|
||||||
case "delete":
|
|
||||||
deleteMatch()
|
|
||||||
case "debug":
|
|
||||||
fmt.Println("config")
|
|
||||||
case "dirty":
|
|
||||||
fmt.Println("")
|
|
||||||
case "examine":
|
|
||||||
fmt.Println("fix")
|
|
||||||
case "list":
|
|
||||||
fmt.Println("--full")
|
|
||||||
case "merge":
|
|
||||||
fmt.Println("devel master")
|
|
||||||
case "pull":
|
|
||||||
fmt.Println("dirty clean list patches sync --force")
|
|
||||||
case "--find":
|
|
||||||
fmt.Println("foo bar")
|
|
||||||
case "patch":
|
|
||||||
fmt.Println("get list --submit show")
|
|
||||||
case "user":
|
|
||||||
fmt.Println("--force")
|
|
||||||
case "devel":
|
|
||||||
fmt.Println("--force")
|
|
||||||
case "sync":
|
|
||||||
fmt.Println("clean user --force")
|
|
||||||
case "master":
|
|
||||||
fmt.Println("")
|
|
||||||
case "verify":
|
|
||||||
fmt.Println("user devel master")
|
|
||||||
default:
|
|
||||||
if argv.BashAuto[0] == ARGNAME {
|
|
||||||
// list the subcommands here
|
|
||||||
fmt.Println("--bash list checkout commit config dirty debug fetch merge patch pull")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// prints help to STDERR // TODO: move everything below this to go-args
|
|
||||||
func (args) doBashHelp() {
|
|
||||||
if argv.BashAuto[1] != "''" {
|
|
||||||
// if this is not blank, then the user has typed something
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if argv.BashAuto[0] != ARGNAME {
|
|
||||||
// if this is not the name of the command, the user already started doing something
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if argv.BashAuto[0] == ARGNAME {
|
|
||||||
me.pp.WriteHelp(os.Stderr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Fprintln(os.Stderr, "")
|
|
||||||
fmt.Fprintln(os.Stderr, "hello world")
|
|
||||||
fmt.Fprintln(os.Stderr, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// complete -F forge --bash forge
|
|
||||||
func (args) doBash() {
|
|
||||||
fmt.Println("# add this in your bashrc:")
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println("# todo: add this to go-arg as a 'hidden' go-arg option --bash")
|
|
||||||
fmt.Println("#")
|
|
||||||
fmt.Println("# todo: can this output work/parse with:")
|
|
||||||
fmt.Println("# complete -C `" + ARGNAME + " --bash` " + ARGNAME)
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println("_" + ARGNAME + "_complete()")
|
|
||||||
fmt.Println("{")
|
|
||||||
fmt.Println(" # sets local to this func vars")
|
|
||||||
fmt.Println(" local cur prev all")
|
|
||||||
fmt.Println(" cur=${COMP_WORDS[COMP_CWORD]}")
|
|
||||||
fmt.Println(" prev=${COMP_WORDS[COMP_CWORD-1]}")
|
|
||||||
fmt.Println(" all=${COMP_WORDS[@]}")
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println(" # this is where we generate the go-arg output")
|
|
||||||
fmt.Println(" GOARGS=$(" + ARGNAME + " --auto-complete $prev \\'$cur\\' $all)")
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println(" # this compares the command line input from the user")
|
|
||||||
fmt.Println(" # to whatever strings we output")
|
|
||||||
fmt.Println(" COMPREPLY=( $(compgen -W \"$GOARGS\" -- $cur) ) # THIS WORKS")
|
|
||||||
fmt.Println(" return 0")
|
|
||||||
fmt.Println("}")
|
|
||||||
fmt.Println("complete -F _" + ARGNAME + "_complete " + ARGNAME)
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println("# copy and paste the above into your bash shell should work")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
|
@ -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")
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/gui"
|
||||||
|
"go.wit.com/lib/debugger"
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if debugger.ArgDebug() {
|
||||||
|
log.Info("cmd line --debugger == true")
|
||||||
|
go func() {
|
||||||
|
log.Sleep(2)
|
||||||
|
debugger.DebugWindow()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func debug() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
gui.Crash(r, "forge debug()")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
for {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
if me.repoAllB != nil {
|
||||||
|
tmp := fmt.Sprintf("All (%d)", me.forge.Repos.Len())
|
||||||
|
me.repoAllB.SetLabel(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if me.repoDevelMergeB != nil {
|
||||||
|
found := findMergeToDevel()
|
||||||
|
tmp := fmt.Sprintf("needs merge to devel (%d)", found.Len())
|
||||||
|
me.repoDevelMergeB.SetLabel(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if me.repoWritableB != nil {
|
||||||
|
found := gitpb.NewRepos()
|
||||||
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
|
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
|
|
||||||
|
}
|
||||||
|
tmp := fmt.Sprintf("writable (%d)", found.Len())
|
||||||
|
me.repoWritableB.SetLabel(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty := me.forge.CheckDirty()
|
||||||
|
|
||||||
|
if me.repoDirtyB != nil {
|
||||||
|
tmp := fmt.Sprintf("dirty (%d)", dirty.Len())
|
||||||
|
me.repoDirtyB.SetLabel(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if me.reposWinB != nil {
|
||||||
|
tmp := fmt.Sprintf("Repos (%d)", me.forge.Repos.Len())
|
||||||
|
if dirty.Len() > 0 {
|
||||||
|
tmp = fmt.Sprintf("Repos (%d) (%d dirty)", me.forge.Repos.Len(), dirty.Len())
|
||||||
|
}
|
||||||
|
me.reposWinB.SetLabel(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for new patches
|
||||||
|
log.Info("should check for packages here")
|
||||||
|
// if err := me.forge.ListPatches(); err != nil {
|
||||||
|
// log.Info("List Patchsets Failed", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
log.Printf("finished a forge scan here in (%s)\n", shell.FormatDuration(time.Since(now)))
|
||||||
|
time.Sleep(90 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
311
doCheckout.go
311
doCheckout.go
|
@ -5,286 +5,39 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
"go.wit.com/lib/gui/shell"
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrorNotAllReposOnMaster error = fmt.Errorf("not all repos on are on the master branch")
|
|
||||||
var ErrorNotAllReposOnDevel error = fmt.Errorf("not all repos on are on the devel branch")
|
|
||||||
var ErrorNotAllReposOnUser error = fmt.Errorf("not all repos on are on the user branch")
|
|
||||||
|
|
||||||
func IsEverythingOnMaster() (int, int, int, error) {
|
|
||||||
var total int
|
|
||||||
var count int
|
|
||||||
var nope int
|
|
||||||
|
|
||||||
// first make sure every repo is on the master branch
|
|
||||||
for repo := range me.forge.Repos.IterAll() {
|
|
||||||
total += 1
|
|
||||||
if repo.GetMasterBranchName() == repo.GetCurrentBranchName() {
|
|
||||||
count += 1
|
|
||||||
} else {
|
|
||||||
nope += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if total != count {
|
|
||||||
// log.Info(ErrorNotAllReposOnMaster)
|
|
||||||
return total, count, nope, ErrorNotAllReposOnMaster
|
|
||||||
}
|
|
||||||
return total, count, nope, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsEverythingOnDevel() (int, int, int, error) {
|
|
||||||
var total int
|
|
||||||
var count int
|
|
||||||
var nope int
|
|
||||||
|
|
||||||
// first make sure every repo is on the master branch
|
|
||||||
for repo := range me.forge.Repos.IterAll() {
|
|
||||||
total += 1
|
|
||||||
if repo.GetDevelBranchName() == repo.GetCurrentBranchName() {
|
|
||||||
count += 1
|
|
||||||
} else {
|
|
||||||
nope += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if total != count {
|
|
||||||
return total, count, nope, ErrorNotAllReposOnDevel
|
|
||||||
}
|
|
||||||
return total, count, nope, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsEverythingOnUser() (int, int, int, error) {
|
|
||||||
var total int
|
|
||||||
var count int
|
|
||||||
var nope int
|
|
||||||
|
|
||||||
// first make sure every repo is on the master branch
|
|
||||||
for repo := range me.forge.Repos.IterAll() {
|
|
||||||
total += 1
|
|
||||||
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
|
|
||||||
count += 1
|
|
||||||
} else {
|
|
||||||
nope += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if total != count {
|
|
||||||
return total, count, nope, ErrorNotAllReposOnUser
|
|
||||||
}
|
|
||||||
return total, count, nope, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func doGitReset() {
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
|
||||||
// log.Info("is readonly", repo.GetGoPath())
|
|
||||||
if repo.CheckDirty() {
|
|
||||||
log.Info("is readonly and dirty", repo.GetGoPath())
|
|
||||||
cmd := []string{"git", "reset", "--hard"}
|
|
||||||
repo.RunRealtime(cmd)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// log.Info("is not readonly", repo.GetGoPath())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func rillCheckoutUser(repo *gitpb.Repo) error {
|
|
||||||
if repo.IsDirty() {
|
|
||||||
// never do dirty repos
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if repo.GetCurrentBranchName() == repo.GetMasterBranchName() {
|
|
||||||
// repo is already on devel branch. have to move them there first for now
|
|
||||||
// return repo.CheckoutDevel()
|
|
||||||
}
|
|
||||||
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
|
|
||||||
// repo is already on user branch
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := repo.CheckoutUser(); err != nil {
|
|
||||||
log.Info(repo.GetFullPath(), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// trys to figure out if there is still something to update
|
// trys to figure out if there is still something to update
|
||||||
func doAllCheckoutUser() error {
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
if argv.Force {
|
|
||||||
log.Info("going to force create user branches")
|
|
||||||
if err := makeUserBranches(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
me.forge.RillFuncError(rillCheckoutUser)
|
|
||||||
count := me.forge.RillReload()
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
total, count, nope, err := IsEverythingOnUser()
|
|
||||||
log.Printf("User branch check. %d total repos. (%d ok) (%d not on user branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
|
||||||
if err != nil {
|
|
||||||
// display all repos not on user
|
|
||||||
found := new(gitpb.Repos)
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
log.Printf("There are %d repos that are NOT on the user branch\n", found.Len())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func rillCheckoutDevel(repo *gitpb.Repo) error {
|
|
||||||
if repo.IsDirty() {
|
|
||||||
// never do dirty repos
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if repo.GetCurrentBranchName() == repo.GetDevelBranchName() {
|
|
||||||
// repo is already on devel branch
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
repo.CheckoutDevel()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// is every repo on the devel branch?
|
|
||||||
func doAllCheckoutDevel() error {
|
|
||||||
now := time.Now()
|
|
||||||
if argv.Force {
|
|
||||||
log.Info("going to force create devel branches")
|
|
||||||
makeDevelBranches()
|
|
||||||
}
|
|
||||||
log.Info("going to rill:")
|
|
||||||
me.forge.RillFuncError(rillCheckoutDevel)
|
|
||||||
count := me.forge.RillReload()
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
total, count, nope, err := IsEverythingOnDevel()
|
|
||||||
log.Printf("Devel branch check. %d total repos. (%d ok) (%d not on devel branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
|
||||||
if err != nil {
|
|
||||||
// display all repos not on user
|
|
||||||
found := new(gitpb.Repos)
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetDevelBranchName() {
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
log.Printf("There are %d repos that are NOT on the devel branch\n", found.Len())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func rillCheckoutMaster(repo *gitpb.Repo) error {
|
|
||||||
if repo.IsDirty() {
|
|
||||||
// never do dirty repos
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// 'giterr' means something is very wrong with this repo
|
|
||||||
if repo.GetMasterVersion() == "giterr" {
|
|
||||||
repo.CheckoutMaster()
|
|
||||||
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
|
|
||||||
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
|
|
||||||
log.Info("master == giterr. BAD REPO", repo.GetFullPath())
|
|
||||||
cmd := []string{"git", "checkout", "main"} // todo: figure out main
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
os.Exit(-1)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if repo.GetCurrentBranchName() == repo.GetMasterBranchName() {
|
|
||||||
// repo is already on master
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
|
||||||
// skip other checks for readonly repos
|
|
||||||
repo.CheckoutMaster()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if repo.GetUserVersion() != repo.GetDevelVersion() {
|
|
||||||
// don't switch branches if the user branch has uncommitted patches
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if repo.GetDevelVersion() != repo.GetMasterVersion() {
|
|
||||||
// don't switch braches if the devel branch does not match master (needs merge)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
repo.CheckoutMaster()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// trys to figure out if there is still something to update
|
|
||||||
func doAllCheckoutMaster() error {
|
|
||||||
now := time.Now()
|
|
||||||
me.forge.RillFuncError(rillCheckoutMaster)
|
|
||||||
count := me.forge.RillReload()
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
total, count, nope, err := IsEverythingOnMaster()
|
|
||||||
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
|
||||||
if err != nil {
|
|
||||||
// display all repos not on master
|
|
||||||
found := new(gitpb.Repos)
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
log.Printf("There are %d repos that are NOT on the master branch\n", found.Len())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// trys to figure out if there is still something to update
|
|
||||||
// todo: redo this logic as it is terrible
|
|
||||||
|
|
||||||
func doCheckout() error {
|
func doCheckout() error {
|
||||||
if argv.Checkout.User != nil {
|
if argv.Checkout.User != nil {
|
||||||
if err := doAllCheckoutUser(); err != nil {
|
start := time.Now()
|
||||||
|
err := me.forge.DoAllCheckoutUser(argv.Force)
|
||||||
|
dur := time.Since(start)
|
||||||
|
log.Printf("Checked out %d user braches in %s\n", me.forge.Repos.Len(), shell.FormatDuration(dur))
|
||||||
|
if err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Checkout.Devel != nil {
|
if argv.Checkout.Devel != nil {
|
||||||
if err := doAllCheckoutDevel(); err != nil {
|
// setForgeMode(forgepb.ForgeMode_DEVEL)
|
||||||
|
if err := me.forge.DoAllCheckoutDevelNew(argv.Force); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Checkout.Master != nil {
|
if argv.Checkout.Master != nil {
|
||||||
if err := doAllCheckoutMaster(); err != nil {
|
setForgeMode(forgepb.ForgeMode_MASTER) // disable "normal" mode if set
|
||||||
|
|
||||||
|
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
|
@ -292,45 +45,3 @@ func doCheckout() error {
|
||||||
badExit(fmt.Errorf("did not specify what branch to checkout"))
|
badExit(fmt.Errorf("did not specify what branch to checkout"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDevelBranches() error {
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
branch := repo.GetDevelBranchName()
|
|
||||||
if repo.Exists(filepath.Join(".git/refs/heads", branch)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if repo.Exists(filepath.Join(".git/refs/remotes/origin", branch)) {
|
|
||||||
cmd := []string{"git", "checkout", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cmd := []string{"git", "branch", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
cmd = []string{"git", "checkout", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeUserBranches() error {
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
branch := repo.GetUserBranchName()
|
|
||||||
if repo.Exists(filepath.Join(".git/refs/heads", branch)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if repo.Exists(filepath.Join(".git/refs/remotes/origin", branch)) {
|
|
||||||
cmd := []string{"git", "checkout", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cmd := []string{"git", "branch", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
cmd = []string{"git", "checkout", branch}
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
255
doClean.go
255
doClean.go
|
@ -6,61 +6,131 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrorReposHasLocalBranches error = fmt.Errorf("repo still has local branches")
|
func checkRemoteBranches(repo *gitpb.Repo) error {
|
||||||
var ErrorMergeBranch error = fmt.Errorf("trunk has things not in the branch")
|
if err := repo.ReloadCheck(); err != nil {
|
||||||
var ErrorMergeTrunk error = fmt.Errorf("branch has things not in trunk")
|
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
|
||||||
|
// automatically deletes local devel and user branches
|
||||||
func doClean() error {
|
func doClean() error {
|
||||||
if argv.Clean.Pub != nil {
|
setForgeMode(forgepb.ForgeMode_CLEAN)
|
||||||
if err := doCleanPub(); err != nil {
|
|
||||||
badExit(err)
|
if argv.Clean.Verify != nil {
|
||||||
|
stats := me.forge.RillRepos(checkRemoteBranches)
|
||||||
|
for path, stat := range stats {
|
||||||
|
if stat.Err == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
log.Info("finished attempt at cleaning devel branches")
|
dur := stat.End.Sub(stat.Start)
|
||||||
return nil
|
if dur > time.Second {
|
||||||
|
log.Infof("%s checkRemoteBranches() took a long time (%s) (err=%v)\n", path, shell.FormatDuration(dur), stat.Err)
|
||||||
}
|
}
|
||||||
if argv.Clean.Devel != nil {
|
|
||||||
if err := doCleanDevel(); err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
log.Info("finished attempt at cleaning devel branches")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if argv.Clean.User != nil {
|
|
||||||
if err := doCleanUser(); err != nil {
|
|
||||||
log.Info(err)
|
|
||||||
okExit("")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCleanUser() error {
|
// fix this to work, then delete all the other options for "forge clean'
|
||||||
if _, count, _, err := IsEverythingOnMaster(); err != nil {
|
if err := me.forge.DoAllCheckoutMaster(); err != nil {
|
||||||
if count == 0 {
|
// badExit(err)
|
||||||
log.Info("No repos are on the master branch")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
log.Info("Not all repos are on the master branch")
|
|
||||||
// return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var anyerr error
|
|
||||||
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
if err := doCleanUserRepo(repo); err != nil {
|
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if repo.IsDirty() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// when publishing, clean out the details of that if it's still there
|
||||||
|
if repo.GetTargetVersion() != "" {
|
||||||
|
repo.SetTargetVersion("")
|
||||||
|
configSave = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to delete user
|
||||||
|
if err := doRepoCleanUser(repo); err != nil {
|
||||||
log.Info(repo.GetGoPath(), err)
|
log.Info(repo.GetGoPath(), err)
|
||||||
anyerr = err
|
}
|
||||||
|
|
||||||
|
// try to delete devel
|
||||||
|
doRepoCleanDevel(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
found := gitpb.NewRepos()
|
||||||
|
|
||||||
|
total := 0
|
||||||
|
// find all repos that aren't "clean"
|
||||||
|
all = me.forge.Repos.SortByFullPath()
|
||||||
|
for all.Scan() {
|
||||||
|
repo := all.Next()
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
// find repos not on master branch
|
||||||
|
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// find dirty repos
|
||||||
|
if repo.IsDirty() {
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// find repos that still have a local user branch
|
||||||
|
if repo.IsLocalBranch(repo.GetUserBranchName()) {
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// find repos that still have a local devel branch
|
||||||
|
if repo.IsLocalBranch(repo.GetDevelBranchName()) {
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return anyerr
|
|
||||||
|
// display all the repos that aren't clean to the user
|
||||||
|
log.Printf("\n") // padding for now
|
||||||
|
if argv.Verbose {
|
||||||
|
me.forge.PrintHumanTableDirty(found)
|
||||||
|
} else {
|
||||||
|
me.forge.PrintHumanTable(found)
|
||||||
|
}
|
||||||
|
log.Printf("\n") // padding for now
|
||||||
|
|
||||||
|
var hmm int
|
||||||
|
hmm = found.Len()
|
||||||
|
if hmm == 0 {
|
||||||
|
log.Printf("%d repos are not clean\n", hmm)
|
||||||
|
} else {
|
||||||
|
log.Info("All repos are clean", total, hmm)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -68,39 +138,28 @@ func doesLocalBranchExist(repo *gitpb.Repo, branch string) bool {
|
||||||
return repo.Exists(filepath.Join(".git/refs/heads", branch))
|
return repo.Exists(filepath.Join(".git/refs/heads", branch))
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
func doRepoCleanDevel(repo *gitpb.Repo) error {
|
||||||
func doCleanDevel() error {
|
|
||||||
var total int
|
|
||||||
var count int
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
total += 1
|
|
||||||
if !repo.IsLocalBranch(repo.GetDevelBranchName()) {
|
if !repo.IsLocalBranch(repo.GetDevelBranchName()) {
|
||||||
// there is no local branch named 'devel'
|
// there is no local branch named 'devel'
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
|
||||||
log.Info("Repo not on master branch:", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if repo.IsDirty() {
|
|
||||||
log.Info("Repo is dirty:", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count += 1
|
|
||||||
if err := justDeleteTheDevelBranchAlready(repo); err != nil {
|
|
||||||
log.Info("justDeleteTheDevel() err", repo.GetGoPath(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Info("")
|
|
||||||
log.Printf("attempted cleaning %d devel branches of %d total branches\n", count, total)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes all local branches
|
if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
|
||||||
func doCleanUserRepo(repo *gitpb.Repo) error {
|
return log.Errorf("%s not on master branch:", repo.GetFullPath())
|
||||||
|
}
|
||||||
|
if repo.IsDirty() {
|
||||||
|
return log.Errorf("%s is dirty:", repo.GetFullPath())
|
||||||
|
}
|
||||||
|
if err := justDeleteTheDevelBranchAlready(repo); err != nil {
|
||||||
|
log.Info("justDeleteTheDevel() err", repo.GetGoPath(), err)
|
||||||
|
configSave = true
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// removes all local user branches
|
||||||
|
func doRepoCleanUser(repo *gitpb.Repo) error {
|
||||||
if repo.IsDirty() {
|
if repo.IsDirty() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -118,33 +177,38 @@ func doCleanUserRepo(repo *gitpb.Repo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("trying to delete", bruser, repo.GetUserVersion())
|
// will you loose work if you delete your user branch?
|
||||||
|
// if DevelBranchExists()
|
||||||
b1 := repo.CountDiffObjects(bruser, brdevel) // should be zero
|
// then if UserBranchCommits exist in DevelBranch
|
||||||
|
// DeleteUserBranch is safe
|
||||||
|
if repo.IsLocalBranch(brdevel) {
|
||||||
|
b1 := repo.CountDiffObjects(bruser, "refs/heads/"+brdevel) // should be zero
|
||||||
if b1 == 0 {
|
if b1 == 0 {
|
||||||
|
// every user branch exists in devel. delete user branch
|
||||||
cmd := []string{"git", "branch", "-D", bruser}
|
cmd := []string{"git", "branch", "-D", bruser}
|
||||||
log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
|
// log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
|
||||||
err := repo.RunVerbose(cmd)
|
_, err := repo.RunVerboseOnError(cmd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("%s branch has things not in %s count=%d", bruser, brdevel, b1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hack to cleanup release versioning info
|
brmaster := repo.GetMasterBranchName()
|
||||||
func doCleanPub() error {
|
|
||||||
total := 0
|
// will you loose work if you delete your user branch?
|
||||||
all := me.forge.Repos.SortByFullPath()
|
// if master branch exists()
|
||||||
for all.Scan() {
|
// then if all user commits exist in master
|
||||||
repo := all.Next()
|
// delete user branch is safe
|
||||||
if repo.GetTargetVersion() != "" {
|
if repo.IsLocalBranch(brmaster) {
|
||||||
repo.SetTargetVersion("")
|
b1 := repo.CountDiffObjects(bruser, "refs/heads/"+brmaster) // should be zero
|
||||||
configSave = true
|
if b1 == 0 {
|
||||||
total += 1
|
cmd := []string{"git", "branch", "-D", bruser}
|
||||||
|
// log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
|
||||||
|
_, err := repo.RunVerboseOnError(cmd)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Printf("clearing %d total repos\n", total)
|
|
||||||
return nil
|
return fmt.Errorf("%s branch has unique commits", bruser)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if you call this, there is no going back. no checks anymore. nothing
|
// if you call this, there is no going back. no checks anymore. nothing
|
||||||
|
@ -165,8 +229,8 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error {
|
||||||
b1 := repo.CountDiffObjects(branch, remote) // should be zero
|
b1 := repo.CountDiffObjects(branch, remote) // should be zero
|
||||||
if b1 == 0 {
|
if b1 == 0 {
|
||||||
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
|
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
|
||||||
log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
|
// log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
|
||||||
err := repo.RunVerbose(cmd)
|
_, err := repo.RunVerboseOnError(cmd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd := []string{"git", "push"}
|
cmd := []string{"git", "push"}
|
||||||
|
@ -177,15 +241,32 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error {
|
||||||
|
|
||||||
// remote doesn't exist, check against master
|
// remote doesn't exist, check against master
|
||||||
master := repo.GetMasterBranchName()
|
master := repo.GetMasterBranchName()
|
||||||
b1 := repo.CountDiffObjects(branch, master) // should be zero
|
b1 := repo.CountDiffObjects(branch, "refs/heads/"+master) // should be zero
|
||||||
if b1 == 0 {
|
if b1 == 0 {
|
||||||
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
|
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
|
||||||
log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
|
// log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
|
||||||
err := repo.RunVerbose(cmd)
|
_, err := repo.RunVerboseOnError(cmd)
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doGitReset() {
|
||||||
|
all := me.forge.Repos.SortByFullPath()
|
||||||
|
for all.Scan() {
|
||||||
|
repo := all.Next()
|
||||||
|
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
||||||
|
// log.Info("is readonly", repo.GetGoPath())
|
||||||
|
if repo.CheckDirty() {
|
||||||
|
log.Info("is readonly and dirty", repo.GetGoPath())
|
||||||
|
cmd := []string{"git", "reset", "--hard"}
|
||||||
|
repo.RunRealtime(cmd)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log.Info("is not readonly", repo.GetGoPath())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
doCommit.go
32
doCommit.go
|
@ -6,16 +6,15 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
func doCommit() {
|
func doCommit() error {
|
||||||
if argv.All {
|
if argv.All {
|
||||||
log.Info("do a commit everywhere")
|
found := me.forge.CheckDirty()
|
||||||
doCheckDirtyAndConfigSave()
|
|
||||||
found := findDirty()
|
|
||||||
var newpatches bool
|
var newpatches bool
|
||||||
for repo := range found.IterAll() {
|
for repo := range found.IterAll() {
|
||||||
log.Info("do a commit on repo", repo.GetGoPath())
|
log.Info("do a commit on repo", repo.GetGoPath())
|
||||||
|
@ -23,25 +22,21 @@ func doCommit() {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
newpatches = true
|
newpatches = true
|
||||||
}
|
repo.CheckDirty()
|
||||||
if !argv.Commit.Submit {
|
|
||||||
okExit("")
|
|
||||||
}
|
}
|
||||||
if newpatches {
|
if newpatches {
|
||||||
// if there are enw patches, autocommit them
|
config.SetChanged("repos", true)
|
||||||
_, err := me.forge.SubmitDevelPatchSet("forge auto commit")
|
return doPatchSubmit()
|
||||||
if err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
pwd, _ := os.Getwd()
|
repo := findCurrentPwdRepoOrDie()
|
||||||
repo := me.forge.Repos.FindByFullPath(pwd)
|
|
||||||
if repo == nil {
|
if !repo.CheckDirty() {
|
||||||
log.Info("todo: forge doesn't know how to work here yet")
|
okExit(log.Sprintf("this repo %s is not dirty.\n\n--all # commit all changes in all repos", repo.GetFullPath()))
|
||||||
okExit("")
|
} else {
|
||||||
|
log.Info("repo is dirty", repo.GetFullPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
||||||
|
@ -68,7 +63,8 @@ func doCommit() {
|
||||||
if err := shell.ExecCheck([]string{"git", "commit", "--all"}); err != nil {
|
if err := shell.ExecCheck([]string{"git", "commit", "--all"}); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
log.Info("git commit ok. forge done")
|
|
||||||
|
return doPatchSubmit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCommitRepo(repo *gitpb.Repo) error {
|
func doCommitRepo(repo *gitpb.Repo) error {
|
||||||
|
|
|
@ -21,6 +21,8 @@ func doConfig() {
|
||||||
log.Info("todo")
|
log.Info("todo")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if argv.Config.Register != "" {
|
if argv.Config.Register != "" {
|
||||||
if err := doRegister(argv.Config.Register); err == nil {
|
if err := doRegister(argv.Config.Register); err == nil {
|
||||||
okExit("attempting to register " + argv.Config.Register)
|
okExit("attempting to register " + argv.Config.Register)
|
||||||
|
@ -28,6 +30,7 @@ func doConfig() {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// try to add, then save config and exit
|
// try to add, then save config and exit
|
||||||
if argv.Config.Add != nil {
|
if argv.Config.Add != nil {
|
||||||
|
@ -51,6 +54,8 @@ func doConfig() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("config.PathLock =", me.forge.Config.PathLock)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
73
doDirty.go
73
doDirty.go
|
@ -3,81 +3,14 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func doDirty() {
|
func doDirty() {
|
||||||
doCheckDirtyAndConfigSave()
|
found := me.forge.CheckDirty()
|
||||||
if allerr := me.forge.RillRepos(checkNormalRepoState); len(allerr) != 0 {
|
if found.Len() == 0 {
|
||||||
log.Info("Some repos are not in a 'normal' state. error count =", len(allerr))
|
return
|
||||||
for repo, err := range allerr {
|
|
||||||
log.Info("repo not normal", repo.GetFullPath(), err)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
found := findDirty()
|
|
||||||
if argv.Verbose {
|
if argv.Verbose {
|
||||||
me.forge.PrintHumanTableDirty(found)
|
me.forge.PrintHumanTableDirty(found)
|
||||||
} else {
|
} else {
|
||||||
me.forge.PrintHumanTable(found)
|
me.forge.PrintHumanTable(found)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 99% of the time, the repos during development should be on your user branch.
|
|
||||||
// error out if it's not
|
|
||||||
// this checks to see if a devel and user branch exist
|
|
||||||
// this needs to run each time in case repos were added manually by the user
|
|
||||||
// this also verifies that
|
|
||||||
func checkNormalRepoState(repo *gitpb.Repo) error {
|
|
||||||
if err := repo.MakeLocalDevelBranch(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
|
||||||
return repo.CheckoutUser()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func straightCheckDirty() int {
|
|
||||||
var count int
|
|
||||||
// var total int
|
|
||||||
// now := time.Now()
|
|
||||||
for repo := range me.forge.Repos.IterAll() {
|
|
||||||
// total += 1
|
|
||||||
if repo.IsDirty() {
|
|
||||||
count += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// log.Printf("rill dirty check (%d dirty repos) (%d total repos) took:%s\n", count, total, shell.FormatDuration(time.Since(now)))
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
func doCheckDirty(repo *gitpb.Repo) error {
|
|
||||||
repo.CheckDirty()
|
|
||||||
// reset these in here for now
|
|
||||||
if repo.GetTargetVersion() != "" {
|
|
||||||
repo.TargetVersion = ""
|
|
||||||
me.forge.SetConfigSave(true)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// recheck every repo's dirty state according to 'git'
|
|
||||||
func doCheckDirtyAndConfigSave() {
|
|
||||||
start := straightCheckDirty()
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
me.forge.RillFuncError(doCheckDirty)
|
|
||||||
end := straightCheckDirty()
|
|
||||||
log.Printf("dirty check (%d dirty repos) (%d total repos) took:%s\n", end, me.forge.Repos.Len(), shell.FormatDuration(time.Since(now)))
|
|
||||||
|
|
||||||
if start != end {
|
|
||||||
// todo: use internal forgepb configsave flag. should work?
|
|
||||||
me.forge.SetConfigSave(true)
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
58
doFind.go
58
doFind.go
|
@ -24,7 +24,7 @@ func doFind() *gitpb.Repos {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.List.Dirty {
|
if argv.List.Dirty {
|
||||||
return findDirty()
|
return me.forge.FindDirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
return findAll()
|
return findAll()
|
||||||
|
@ -52,7 +52,7 @@ func (f *FindCmd) findRepos() *gitpb.Repos {
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Dirty {
|
if f.Dirty {
|
||||||
return findDirty()
|
return me.forge.FindDirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.User {
|
if f.User {
|
||||||
|
@ -66,7 +66,7 @@ func findPrivate() *gitpb.Repos {
|
||||||
found := gitpb.NewRepos()
|
found := gitpb.NewRepos()
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
|
if me.forge.Config.IsPrivate(repo.GetGoPath()) {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func findMine() *gitpb.Repos {
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
|
|
||||||
if me.forge.Config.IsWritable(repo.GetGoPath()) {
|
if me.forge.Config.IsWritable(repo.GetGoPath()) {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
@ -95,19 +95,7 @@ func findFavorites() *gitpb.Repos {
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
|
|
||||||
if me.forge.Config.IsFavorite(repo.GetGoPath()) {
|
if me.forge.Config.IsFavorite(repo.GetGoPath()) {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
|
||||||
}
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
// finds repos that git is reporting as dirty
|
|
||||||
func findDirty() *gitpb.Repos {
|
|
||||||
found := gitpb.NewRepos()
|
|
||||||
|
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
|
||||||
if repo.IsDirty() {
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
@ -116,7 +104,7 @@ func findDirty() *gitpb.Repos {
|
||||||
func findAll() *gitpb.Repos {
|
func findAll() *gitpb.Repos {
|
||||||
found := gitpb.NewRepos()
|
found := gitpb.NewRepos()
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
@ -125,7 +113,7 @@ func find50() *gitpb.Repos {
|
||||||
count := 0
|
count := 0
|
||||||
found := gitpb.NewRepos()
|
found := gitpb.NewRepos()
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
if count > 50 {
|
if count > 50 {
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
@ -139,7 +127,7 @@ func findUser() *gitpb.Repos {
|
||||||
|
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
|
if repo.GetCurrentBranchName() == repo.GetUserBranchName() {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
@ -152,7 +140,7 @@ func findPublishable() *gitpb.Repos {
|
||||||
if repo.GetTargetVersion() == "" {
|
if repo.GetTargetVersion() == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
@ -163,12 +151,12 @@ func findReposWithPatches() *gitpb.Repos {
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
if repo.GetTargetVersion() != "" {
|
if repo.GetTargetVersion() != "" {
|
||||||
// add everything that has a target version set
|
// add everything that has a target version set
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if repo.IsDirty() {
|
if repo.IsDirty() {
|
||||||
// always add dirty branches
|
// always add dirty branches
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if repo.GetUserVersion() == "" || repo.GetUserVersion() == "uerr" {
|
if repo.GetUserVersion() == "" || repo.GetUserVersion() == "uerr" {
|
||||||
|
@ -176,7 +164,21 @@ func findReposWithPatches() *gitpb.Repos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if repo.GetUserVersion() != repo.GetDevelVersion() {
|
if repo.GetUserVersion() != repo.GetDevelVersion() {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// show anything that differs between 'devel' & 'master' branches
|
||||||
|
if repo.GetDevelVersion() != repo.GetMasterVersion() {
|
||||||
|
// this repo.State code isn't great, but it got me here quickly
|
||||||
|
// I'll defend my code by saying it's faster for me if I do dumb things
|
||||||
|
// sometimes and fix them later. Probably some employee will have to
|
||||||
|
// fix this. if that is the case I owe you lunch. or stock options
|
||||||
|
if repo.State == "DEVEL behind MASTER" {
|
||||||
|
// log.Info("repo state", repo.FullPath, repo.State)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,15 +187,9 @@ func findReposWithPatches() *gitpb.Repos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// show anything that differs between 'devel' & 'master' branches
|
|
||||||
if repo.GetDevelVersion() != repo.GetMasterVersion() {
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is an old test to see if the current 'last tag' is accurate and should be removed
|
// this is an old test to see if the current 'last tag' is accurate and should be removed
|
||||||
if repo.GetLastTag() != repo.GetMasterVersion() {
|
if repo.GetLastTag() != repo.GetMasterVersion() {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
repo.FindLastTag()
|
repo.FindLastTag()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
239
doGui.go
239
doGui.go
|
@ -18,97 +18,39 @@ import (
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func debug() {
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
for {
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
if me.repoAllB != nil {
|
|
||||||
tmp := fmt.Sprintf("All (%d)", me.forge.Repos.Len())
|
|
||||||
me.repoAllB.SetLabel(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if me.repoDevelMergeB != nil {
|
|
||||||
found := findMergeToDevel()
|
|
||||||
tmp := fmt.Sprintf("needs merge to devel (%d)", found.Len())
|
|
||||||
me.repoDevelMergeB.SetLabel(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if me.repoWritableB != nil {
|
|
||||||
found := gitpb.NewRepos()
|
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
found.AppendByGoPath(repo)
|
|
||||||
|
|
||||||
}
|
|
||||||
tmp := fmt.Sprintf("writable (%d)", found.Len())
|
|
||||||
me.repoWritableB.SetLabel(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
doCheckDirtyAndConfigSave()
|
|
||||||
found := findDirty()
|
|
||||||
dirty := found.Len()
|
|
||||||
|
|
||||||
if me.repoDirtyB != nil {
|
|
||||||
tmp := fmt.Sprintf("dirty (%d)", dirty)
|
|
||||||
me.repoDirtyB.SetLabel(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if me.reposWinB != nil {
|
|
||||||
tmp := fmt.Sprintf("Repos (%d)", me.forge.Repos.Len())
|
|
||||||
if dirty > 0 {
|
|
||||||
tmp = fmt.Sprintf("Repos (%d) (%d dirty)", me.forge.Repos.Len(), dirty)
|
|
||||||
}
|
|
||||||
me.reposWinB.SetLabel(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("finished a forge scan here in (%s)\n", shell.FormatDuration(time.Since(now)))
|
|
||||||
time.Sleep(90 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doGui() {
|
func doGui() {
|
||||||
if me.forge.Config.GetDefaultGui() == "" {
|
win := gadgets.NewGenericWindow("Forge: A federated git development tool by WIT.COM", "Current Settings")
|
||||||
me.forge.Config.DefaultGui = "gocui"
|
win.Custom = func() {
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
me.myGui = gui.New()
|
|
||||||
me.myGui.InitEmbed(resources)
|
|
||||||
me.myGui.SetAppDefaultPlugin(me.forge.Config.DefaultGui) // sets the default GUI plugin to use
|
|
||||||
me.myGui.Default()
|
|
||||||
|
|
||||||
mainWindow := gadgets.NewGenericWindow("Forge: (this kinda works sometimes)", "Current Settings")
|
|
||||||
mainWindow.Custom = func() {
|
|
||||||
log.Warn("MAIN WINDOW CLOSE")
|
log.Warn("MAIN WINDOW CLOSE")
|
||||||
now := time.Now()
|
okExit("")
|
||||||
count := me.forge.RillReload()
|
|
||||||
log.Info("Repo Reload count =", count)
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
log.Printf("rill repos.Reload() took (%s)\n", shell.FormatDuration(time.Since(now)))
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawWindow(mainWindow)
|
|
||||||
|
|
||||||
// sits here forever
|
|
||||||
debug()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func drawWindow(win *gadgets.GenericWindow) {
|
|
||||||
grid := win.Group.RawGrid()
|
grid := win.Group.RawGrid()
|
||||||
|
if me.forge.Config.GetPathLock() {
|
||||||
me.goSrcPwd = gadgets.NewOneLiner(grid, "Working Directory")
|
me.goSrcPwd = gadgets.NewOneLiner(grid, "Working Directory")
|
||||||
grid.NewLabel("")
|
me.goSrcPwd.SetText(me.forge.Config.ReposDir)
|
||||||
|
} else {
|
||||||
|
me.goSrcEdit = gadgets.NewBasicEntry(grid, "Working Directory")
|
||||||
|
me.goSrcEdit.SetText(me.forge.Config.ReposDir)
|
||||||
|
me.goSrcEdit.Custom = func() {
|
||||||
|
log.Info("updating text to", me.goSrcEdit.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lockpath := grid.NewCheckbox("Lock").SetChecked(me.forge.Config.PathLock)
|
||||||
|
lockpath.Custom = func() {
|
||||||
|
if lockpath.IsChecked() {
|
||||||
|
log.Info("lock working directory")
|
||||||
|
me.forge.Config.PathLock = true
|
||||||
|
} else {
|
||||||
|
log.Info("unlock working directory")
|
||||||
|
me.forge.Config.PathLock = false
|
||||||
|
}
|
||||||
|
me.forge.Config.ConfigSave()
|
||||||
|
okExit("you must restart forge after changing the Path Lock")
|
||||||
|
}
|
||||||
|
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
|
||||||
me.goSrcPwd.SetText(me.forge.GetGoSrc())
|
|
||||||
|
|
||||||
// use ENV GIT_AUTHOR
|
// use ENV GIT_AUTHOR
|
||||||
me.gitAuthor = gadgets.NewOneLiner(grid, "Git Author")
|
me.gitAuthor = gadgets.NewOneLiner(grid, "Git Author")
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
@ -123,31 +65,8 @@ func drawWindow(win *gadgets.GenericWindow) {
|
||||||
|
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
|
||||||
// groupM := hbox.NewGroup("Windows")
|
|
||||||
// gridM := groupM.RawGrid()
|
|
||||||
// hbox := win.Stack.Box().Horizontal()
|
|
||||||
gridM := win.Stack.RawGrid()
|
gridM := win.Stack.RawGrid()
|
||||||
|
|
||||||
var releaseWin *gadgets.GenericWindow
|
|
||||||
gridM.NewButton("Release Window", func() {
|
|
||||||
log.Info("todo: move releaser here")
|
|
||||||
log.Info("for now, run guireleaser")
|
|
||||||
if releaseWin != nil {
|
|
||||||
releaseWin.Toggle()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
releaseWin = makeModeMasterWin()
|
|
||||||
})
|
|
||||||
|
|
||||||
var patches *stdPatchsetTableWin
|
|
||||||
gridM.NewButton("Patch Window", func() {
|
|
||||||
if patches != nil {
|
|
||||||
patches.Toggle()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
patches = makePatchsetsWin()
|
|
||||||
})
|
|
||||||
|
|
||||||
var insertWin *gadgets.GenericWindow
|
var insertWin *gadgets.GenericWindow
|
||||||
s := fmt.Sprintf("Repos (%d)", me.forge.Repos.Len())
|
s := fmt.Sprintf("Repos (%d)", me.forge.Repos.Len())
|
||||||
me.reposWinB = gridM.NewButton(s, func() {
|
me.reposWinB = gridM.NewButton(s, func() {
|
||||||
|
@ -160,55 +79,52 @@ func drawWindow(win *gadgets.GenericWindow) {
|
||||||
insertWin = makeReposWinNew()
|
insertWin = makeReposWinNew()
|
||||||
})
|
})
|
||||||
|
|
||||||
// var reposWin *gadgets.GenericWindow
|
|
||||||
var reposWin *stdReposTableWin
|
|
||||||
gridM.NewButton("Fix Repos", func() {
|
|
||||||
if reposWin != nil {
|
|
||||||
reposWin.Toggle()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
reposWin = makeReposWin()
|
|
||||||
})
|
|
||||||
|
|
||||||
var patchesWin *stdPatchTableWin
|
var patchesWin *stdPatchTableWin
|
||||||
gridM.NewButton("Pending patches", func() {
|
var patchButton *gui.Node
|
||||||
|
patchButton = gridM.NewButton("Your patches", func() {
|
||||||
if patchesWin != nil {
|
if patchesWin != nil {
|
||||||
patchesWin.Toggle()
|
patchesWin.Toggle()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loadUpstreamPatchsets()
|
if !isPatchingSafe() {
|
||||||
if me.psets == nil {
|
patchButton.SetLabel("not safe yet")
|
||||||
log.Info("failed to download current patchsets")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// patchesWin = makePatchesWin(me.forge.Patchsets)
|
||||||
notdone := new(forgepb.Patches)
|
notdone := new(forgepb.Patches)
|
||||||
|
|
||||||
all := me.psets.All()
|
all := me.forge.Patchsets.All()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
pset := all.Next()
|
pset := all.Next()
|
||||||
AddNotDonePatches(notdone, pset, false)
|
if pset.State == "DONE" {
|
||||||
|
// skip old patchsets
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
AddAllPatches(notdone, pset, false)
|
||||||
|
// AddNotDonePatches(notdone, pset, false)
|
||||||
|
}
|
||||||
|
notdone.PrintTable()
|
||||||
|
|
||||||
for patch := range notdone.IterAll() {
|
|
||||||
comment := cleanSubject(patch.Comment)
|
|
||||||
log.Info("new patch:", patch.NewHash, "commithash:", patch.CommitHash, patch.RepoNamespace, comment)
|
|
||||||
}
|
|
||||||
// savePatchsets()
|
|
||||||
patchesWin = makePatchesWin(notdone)
|
patchesWin = makePatchesWin(notdone)
|
||||||
})
|
})
|
||||||
|
|
||||||
gridM.NextRow()
|
var pubWin *gadgets.GenericWindow
|
||||||
var howtoWin *gadgets.GenericWindow
|
gridM.NewButton("Publish", func() {
|
||||||
gridM.NewButton("Tutorial", func() {
|
if pubWin != nil {
|
||||||
if howtoWin != nil {
|
pubWin.Toggle()
|
||||||
howtoWin.Toggle()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
howtoWin = makeHowtoWin()
|
pubWin = makePublishWindow()
|
||||||
})
|
})
|
||||||
|
|
||||||
gridM.NextRow()
|
var oldWin *gadgets.GenericWindow
|
||||||
gridM.NewLabel("")
|
gridM.NewButton("old", func() {
|
||||||
|
if oldWin != nil {
|
||||||
|
oldWin.Toggle()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldWin = makeOldStuff()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the magic that generates a window directly from the protocol buffer
|
// this is the magic that generates a window directly from the protocol buffer
|
||||||
|
@ -216,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()
|
||||||
|
@ -258,7 +174,7 @@ func findMergeToDevel() *gitpb.Repos {
|
||||||
for repo := range me.forge.Repos.IterByFullPath() {
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
// this sees if user has patches for devel. If it does, add it to found
|
// this sees if user has patches for devel. If it does, add it to found
|
||||||
if repo.CountDiffObjects(repo.GetUserBranchName(), repo.GetDevelBranchName()) > 0 {
|
if repo.CountDiffObjects(repo.GetUserBranchName(), repo.GetDevelBranchName()) > 0 {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -269,7 +185,7 @@ func findMergeToDevel() *gitpb.Repos {
|
||||||
// me.forge.PrintHumanTable(found)
|
// me.forge.PrintHumanTable(found)
|
||||||
|
|
||||||
// check for merges from devel
|
// check for merges from devel
|
||||||
total, count, nope, _ := IsEverythingOnDevel()
|
total, count, nope, _ := me.forge.IsEverythingOnDevel()
|
||||||
log.Printf("devel branch check. %d total repos. (%d ok) (%d not on devel branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
log.Printf("devel branch check. %d total repos. (%d ok) (%d not on devel branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
@ -281,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
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -289,7 +205,7 @@ func findMergeToMaster() *gitpb.Repos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if repo.GetMasterVersion() != repo.GetDevelVersion() {
|
if repo.GetMasterVersion() != repo.GetDevelVersion() {
|
||||||
me.found.AppendByGoPath(repo)
|
me.found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -299,12 +215,12 @@ 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
|
||||||
if repo.CountDiffObjects(repo.GetDevelBranchName(), repo.GetMasterBranchName()) > 0 {
|
if repo.CountDiffObjects(repo.GetDevelBranchName(), repo.GetMasterBranchName()) > 0 {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -315,7 +231,7 @@ func findMergeToMaster() *gitpb.Repos {
|
||||||
me.forge.PrintHumanTable(found)
|
me.forge.PrintHumanTable(found)
|
||||||
|
|
||||||
// check for merges from devel
|
// check for merges from devel
|
||||||
total, count, nope, _ := IsEverythingOnMaster()
|
total, count, nope, _ := me.forge.IsEverythingOnMaster()
|
||||||
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch) (%s)\n", total, count, nope, shell.FormatDuration(time.Since(now)))
|
||||||
|
|
||||||
return found
|
return found
|
||||||
|
@ -331,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 {
|
||||||
|
@ -382,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 {
|
||||||
|
@ -413,3 +329,34 @@ func mergeUserToDevel(doit bool) {
|
||||||
}
|
}
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// old things before they are removed, deprecated, fixed, etc
|
||||||
|
func makeOldStuff() *gadgets.GenericWindow {
|
||||||
|
oldWin := gadgets.NewGenericWindow("old code", "old code on it's way out")
|
||||||
|
|
||||||
|
grid := oldWin.Group.RawGrid()
|
||||||
|
|
||||||
|
// var reposWin *gadgets.GenericWindow
|
||||||
|
var reposWin *stdReposTableWin
|
||||||
|
grid.NewButton("Fix Repos", func() {
|
||||||
|
if reposWin != nil {
|
||||||
|
reposWin.Toggle()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reposWin = makeReposWin()
|
||||||
|
})
|
||||||
|
|
||||||
|
var howtoWin *gadgets.GenericWindow
|
||||||
|
grid.NewButton("Tutorial", func() {
|
||||||
|
if howtoWin != nil {
|
||||||
|
howtoWin.Toggle()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
howtoWin = makeHowtoWin()
|
||||||
|
})
|
||||||
|
|
||||||
|
grid.NextRow()
|
||||||
|
grid.NewLabel("")
|
||||||
|
|
||||||
|
return oldWin
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the GPL 3.0
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
|
"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 {
|
||||||
|
found := forgepb.NewPatches()
|
||||||
|
for repo := range me.forge.Repos.IterAll() {
|
||||||
|
if repo.GetDevelVersion() == repo.GetMasterVersion() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tmp := log.Sprintf("%s..%s", repo.GetMasterVersion(), repo.GetDevelVersion())
|
||||||
|
r, err := repo.RunStrict([]string{"git", "log", "--pretty=format:%H", tmp})
|
||||||
|
_ = err
|
||||||
|
for i, line := range r.Stdout {
|
||||||
|
log.Info(i, line, repo.FullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func doMergeDevel() (*gitpb.Repos, error) {
|
||||||
|
var err error
|
||||||
|
done := gitpb.NewRepos()
|
||||||
|
found := findMergeToDevel()
|
||||||
|
for repo := range found.IterAll() {
|
||||||
|
if repo.CheckDirty() {
|
||||||
|
log.Info("repo is dirty", repo.GetFullPath())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
done.Append(repo)
|
||||||
|
config.SetChanged("repos", true)
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
var err error
|
||||||
|
setForgeMode(forgepb.ForgeMode_MASTER)
|
||||||
|
|
||||||
|
done := gitpb.NewRepos()
|
||||||
|
found := findMergeToMaster()
|
||||||
|
for repo := range found.IterAll() {
|
||||||
|
if repo.CheckDirty() {
|
||||||
|
log.Info("repo is dirty", repo.GetGoPath())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Starting merge on", repo.GetGoPath())
|
||||||
|
if repo.CheckoutMaster() {
|
||||||
|
log.Info("checkout devel failed", repo.GetGoPath())
|
||||||
|
err = log.Errorf("checkout devel failed")
|
||||||
|
badExit(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := repo.MergeToMaster(); 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
done.Append(repo)
|
||||||
|
config.SetChanged("repos", true)
|
||||||
|
}
|
||||||
|
return done, err
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
// 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 (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.wit.com/lib/config"
|
||||||
|
"go.wit.com/lib/gui/shell"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func doNormal() bool {
|
||||||
|
me.forge.CheckDirtyQuiet()
|
||||||
|
|
||||||
|
var count int
|
||||||
|
stats := me.forge.RillRepos(checkNormalRepoState)
|
||||||
|
for path, stat := range stats {
|
||||||
|
dur := stat.End.Sub(stat.Start)
|
||||||
|
if dur > 10*time.Second {
|
||||||
|
log.Infof("%s checkNormalRepoState() took a long time (%s)\n", path, shell.FormatDuration(dur))
|
||||||
|
}
|
||||||
|
if stat.Err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// log.Infof("%-60s, %-60s %v %s\n", stat.Start, stat.End.String(), dur, path)
|
||||||
|
// log.Infof("%-30v %s %v\n", dur, path, stat.Err)
|
||||||
|
// log.Info("got path", path, stat.Err)
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
log.Info("Some repos are not in a 'normal' state. error count =", count)
|
||||||
|
log.Info("TODO: list the repos here. forge patch repos?")
|
||||||
|
dumpWorkRepos()
|
||||||
|
config.SetChanged("repos", true)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 99% of the time, the repos during development should be on your user branch.
|
||||||
|
// error out if it's not
|
||||||
|
// this checks to see if a devel and user branch exist
|
||||||
|
// this needs to run each time in case repos were added manually by the user
|
||||||
|
// this also verifies that
|
||||||
|
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() == "" {
|
||||||
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
log.Info("ABNORMAL: master branch name was blank in", repo.GetFullPath())
|
||||||
|
}
|
||||||
|
if repo.GetMasterBranchName() == "" {
|
||||||
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
err = log.Errorf("master branch name blank")
|
||||||
|
}
|
||||||
|
if repo.GetDevelBranchName() == "" {
|
||||||
|
me.forge.VerifyBranchNames(repo)
|
||||||
|
err = log.Errorf("devel branch name blank")
|
||||||
|
}
|
||||||
|
if repo.GetUserBranchName() == "" {
|
||||||
|
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.VerifyRemoteAndLocalBranches(repo.GetDevelBranchName())
|
||||||
|
repo.VerifyRemoteAndLocalBranches(repo.GetMasterBranchName())
|
||||||
|
|
||||||
|
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
||||||
|
log.Infof("changing to user(%s) branch: %s\n", repo.GetUserBranchName(), repo.FullPath)
|
||||||
|
repo.CheckoutUser()
|
||||||
|
repo.ReloadCheck()
|
||||||
|
err = log.Errorf("now on user branch")
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
276
doPatch.go
276
doPatch.go
|
@ -4,100 +4,210 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"go.wit.com/lib/fhelp"
|
||||||
"go.wit.com/lib/protobuf/forgepb"
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func doPatch() error {
|
func doPatchInit() {
|
||||||
if argv.Patch.Submit != "" {
|
if me.forge.Patchsets != nil {
|
||||||
_, err := me.forge.SubmitDevelPatchSet(argv.Patch.Submit)
|
if me.forge.Patchsets.Len() == 0 {
|
||||||
|
// log.Info("IGNORE: patches are empty")
|
||||||
|
} else {
|
||||||
|
log.Info("IGNORE: patches already initalized len =", me.forge.Patchsets.Len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := me.forge.LoadPatchsets(); err != nil {
|
||||||
|
log.Info("patches failed to open", err)
|
||||||
|
if err := me.forge.SavePatchsets(); err != nil {
|
||||||
|
log.Warn("savePatchsets() failed", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPatchingSafe() bool {
|
||||||
|
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log.Info("This patch command is not safe to run now")
|
||||||
|
log.Info("you must reset the state of your git repositories. Run:")
|
||||||
|
log.Info("")
|
||||||
|
log.Info("forge normal")
|
||||||
|
log.Info("")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// submit's current working patches
|
||||||
|
func doPatchSubmit() error {
|
||||||
|
pset, err := me.forge.MakeDevelPatchSet("testing")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func doPatch() error {
|
||||||
|
if argv.Patch.Repos != nil {
|
||||||
|
dumpWorkRepos()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if argv.Patch.Submit != nil {
|
||||||
|
return doPatchSubmit()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isPatchingSafe() {
|
||||||
|
return log.Errorf("not safe to work on patches")
|
||||||
|
}
|
||||||
|
|
||||||
if argv.Patch.Get != nil {
|
if argv.Patch.Get != nil {
|
||||||
return doPatchGet()
|
psets := forgepb.NewSets()
|
||||||
|
newpb, _, _ := psets.HttpPostVerbose(myServer(), "get")
|
||||||
|
newpb.PrintTable()
|
||||||
|
me.forge.Patchsets = newpb
|
||||||
|
me.forge.SavePatchsets()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if argv.Patch.Check != nil {
|
||||||
|
/*
|
||||||
|
old := findExpired()
|
||||||
|
// old.PrintTable()
|
||||||
|
for p := range old.IterAll() {
|
||||||
|
log.Info("patch", p.Filename, p.Namespace)
|
||||||
|
}
|
||||||
|
newpb, err := old.HttpPostVerbose(myServer(), "check")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newpb.PrintTable()
|
||||||
|
*/
|
||||||
|
log.Info("do something here to find patches merged to devel")
|
||||||
|
doMergeReport()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Patch.List != nil {
|
if argv.Patch.List != nil {
|
||||||
return doPatchList()
|
var changed bool
|
||||||
|
newpatches := new(forgepb.Set)
|
||||||
|
newpatches.Patches = forgepb.NewPatches()
|
||||||
|
for pset := range me.forge.Patchsets.IterAll() {
|
||||||
|
pset.PrintTable()
|
||||||
|
for patch := range pset.Patches.IterAll() {
|
||||||
|
changed = true
|
||||||
|
if patch.NewHash == "" || patch.NewHash == "na" {
|
||||||
|
if newpatches.Patches.AppendByPatchId(patch) {
|
||||||
|
log.Info("patchId added here", patch.PatchId)
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
|
if err := me.forge.SavePatchsets(); err != nil {
|
||||||
|
log.Warn("savePatchsets() failed", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("NEW PATCHES TABLE")
|
||||||
|
newpatches.PrintTable()
|
||||||
|
for patch := range newpatches.Patches.IterAll() {
|
||||||
|
if err := setNewCommitHash(patch); err == nil {
|
||||||
|
log.Info("newhash set already here", patch.PatchId, patch.NewHash)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Infof("%s is new\n", patch.Filename)
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("\tCould not find namespace:", patch.Namespace)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fhelp.QuestionUser("apply this patch?") {
|
||||||
|
newhash, err := applyAndTrackPatch(repo, patch)
|
||||||
|
log.Info("apply results:", newhash, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
me.forge.Patchsets.PrintTable()
|
||||||
|
dumpWorkRepos()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows repos that are:
|
||||||
|
// - git dirty repos
|
||||||
|
// - repos with 'user' branch patches not in 'devel' branch
|
||||||
|
// - repos with awaiting master branch verions
|
||||||
|
//
|
||||||
|
// return true if any are found
|
||||||
|
func dumpWorkRepos() bool {
|
||||||
|
// always run dirty first
|
||||||
|
me.forge.CheckDirtyQuiet()
|
||||||
|
|
||||||
// if no option is given to patch, list out the
|
// if no option is given to patch, list out the
|
||||||
// repos that have patches ready in them
|
// repos that have patches ready in them
|
||||||
found := findReposWithPatches()
|
found := findReposWithPatches()
|
||||||
if found.Len() == 0 {
|
if found.Len() == 0 {
|
||||||
log.Info("you currently have no patches in your user branches")
|
log.Info("you currently have no repos with patches")
|
||||||
return nil
|
return false
|
||||||
}
|
} else {
|
||||||
me.forge.PrintHumanTable(found)
|
me.forge.PrintHumanTable(found)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
func doPatchList() error {
|
|
||||||
openPatchsets()
|
|
||||||
if me.psets == nil {
|
|
||||||
return fmt.Errorf("Open Patchsets failed")
|
|
||||||
}
|
|
||||||
log.Info("got psets len", len(me.psets.Patchsets))
|
|
||||||
all := me.psets.SortByName()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
// log.Info("pset name =", pset.Name)
|
|
||||||
dumpPatchset(pset)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func savePatchsets() error {
|
|
||||||
if me.psets == nil {
|
|
||||||
return fmt.Errorf("savePatchesets() can't save nil")
|
|
||||||
}
|
|
||||||
log.Info("savePatchsets() len =", me.psets.Len())
|
|
||||||
data, err := me.psets.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
log.Info("protobuf.Marshal() failed:", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fullpath := filepath.Join(me.forge.GetConfigDir(), "patchsets.pb")
|
|
||||||
var pfile *os.File
|
|
||||||
pfile, err = os.OpenFile(fullpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Patchsets save failed:", err, fullpath)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pfile.Write(data)
|
|
||||||
pfile.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func openPatchsets() {
|
|
||||||
fullpath := filepath.Join(me.forge.GetConfigDir(), "patchsets.pb")
|
|
||||||
data, err := os.ReadFile(fullpath)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Patchsets open failed:", err, fullpath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
psets := new(forgepb.Patchsets)
|
|
||||||
err = psets.Unmarshal(data)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Unmarshal patchsets failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.psets = psets
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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())
|
||||||
|
@ -106,13 +216,6 @@ func dumpPatchset(pset *forgepb.Patchset) bool {
|
||||||
log.Printf("Patchset Name: %-24s Author: %s <%s> IS GOOD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail())
|
log.Printf("Patchset Name: %-24s Author: %s <%s> IS GOOD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
log.Info("applyPatches() State", pset.State)
|
|
||||||
log.Info("applyPatches() COMMENT", pset.Comment)
|
|
||||||
log.Info("applyPatches() Branch Name", pset.GetStartBranchName())
|
|
||||||
log.Info("applyPatches() Start Hash", pset.GetStartBranchHash())
|
|
||||||
*/
|
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
var bad int
|
var bad int
|
||||||
all := pset.Patches.SortByFilename()
|
all := pset.Patches.SortByFilename()
|
||||||
|
@ -143,12 +246,12 @@ func IsValidPatch(p *forgepb.Patch) bool {
|
||||||
log.Info("can not apply patch! repo not found", basepath, filename)
|
log.Info("can not apply patch! repo not found", basepath, filename)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if repo.DevelHash() != p.StartHash {
|
if repo.ActualDevelHash() != p.StartHash {
|
||||||
log.Info("can not apply patch! devel hash mismatch", basepath, filename)
|
log.Info("can not apply patch! devel hash mismatch", basepath, filename)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if repo.DevelHash() == p.StartHash {
|
if repo.ActualDevelHash() == p.StartHash {
|
||||||
log.Info("local devel hash:", repo.DevelHash(), "matches patch hash", p.StartHash, "and can be applied")
|
log.Info("local devel hash:", repo.ActualDevelHash(), "matches patch hash", p.StartHash, "and can be applied")
|
||||||
}
|
}
|
||||||
log.Info("start:", p.StartHash, "end:", p.CommitHash, "file:", basepath, filename, "devel version", repo.GetDevelVersion())
|
log.Info("start:", p.StartHash, "end:", p.CommitHash, "file:", basepath, filename, "devel version", repo.GetDevelVersion())
|
||||||
for _, line := range p.Files {
|
for _, line := range p.Files {
|
||||||
|
@ -156,24 +259,3 @@ func IsValidPatch(p *forgepb.Patch) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func doPatchGet() error {
|
|
||||||
psets, err := me.forge.GetPatchesets()
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Get Patchsets failed", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Info("Got Patchsets ok", psets.Uuid)
|
|
||||||
|
|
||||||
log.Info("got psets len", len(psets.Patchsets))
|
|
||||||
all := psets.SortByName()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
// log.Info("pset name =", pset.Name)
|
|
||||||
dumpPatchset(pset)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("FIXME: can't save these yet. must merge with on disk psets here")
|
|
||||||
// savePatchsets()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
238
doPull.go
238
doPull.go
|
@ -4,14 +4,61 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// is every repo on the devel branch?
|
||||||
|
func doPull() error {
|
||||||
|
if argv.Pull.Check != nil {
|
||||||
|
// stats := me.forge.RillFuncError(rillPull)
|
||||||
|
log.Info("TODO: actually git pull here? this is a bad idea. stopping.")
|
||||||
|
submit := gitpb.NewRepos()
|
||||||
|
for repo := range me.forge.Repos.IterByFullPath() {
|
||||||
|
newrepo := new(gitpb.Repo)
|
||||||
|
newrepo.MasterHash = repo.MasterHash
|
||||||
|
newrepo.DevelHash = repo.DevelHash
|
||||||
|
newrepo.Namespace = repo.Namespace
|
||||||
|
newrepo.URL = repo.URL
|
||||||
|
submit.Append(newrepo)
|
||||||
|
}
|
||||||
|
updatepb, regPB, err := submit.HttpPost(myServer(), "check")
|
||||||
|
if regPB == nil || err != nil {
|
||||||
|
log.Info("regPB==nil or err:", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Infof("pull check %s pb.Len()=%d client.Len()=%d server.Len()=%d err=%v\n", regPB.URL, updatepb.Len(), regPB.ClientDataLen, regPB.ServerDataLen, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// below this, you must not be in 'normal' mode
|
||||||
|
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
||||||
|
log.Info("you must check out the devel or master branches")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if argv.Force == true {
|
||||||
|
now := time.Now()
|
||||||
|
stats := me.forge.RillFuncError(rillPull)
|
||||||
|
count := me.forge.RillReload()
|
||||||
|
if count != 0 {
|
||||||
|
me.forge.ConfigSave()
|
||||||
|
}
|
||||||
|
|
||||||
|
total, count, nope, _ := me.forge.IsEverythingOnMaster()
|
||||||
|
log.Printf("Master branch check. %d total repos. (%d git pulled) (%d not on master branch) (%s) git pull total=FIXME%d\n", total, count, nope, shell.FormatDuration(time.Since(now)), len(stats))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("do a pull check here?")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func rillPull(repo *gitpb.Repo) error {
|
func rillPull(repo *gitpb.Repo) error {
|
||||||
if repo.IsDirty() {
|
if repo.IsDirty() {
|
||||||
// never do dirty repos
|
// never do dirty repos
|
||||||
|
@ -41,130 +88,7 @@ func rillPull(repo *gitpb.Repo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// is every repo on the devel branch?
|
|
||||||
|
|
||||||
func doGitPullNew() error {
|
|
||||||
if argv.Pull == nil {
|
|
||||||
return fmt.Errorf("not really 'fetch pull'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Force {
|
|
||||||
now := time.Now()
|
|
||||||
pullcount := me.forge.RillFuncError(rillPull)
|
|
||||||
count := me.forge.RillReload()
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
total, count, nope, _ := IsEverythingOnMaster()
|
|
||||||
log.Printf("Master branch check. %d total repos. (%d git pulled) (%d not on master branch) (%s) git pull total=%d\n", total, count, nope, shell.FormatDuration(time.Since(now)), pullcount)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
check := gitpb.NewRepos()
|
|
||||||
|
|
||||||
if argv.Pull.Dirty != nil {
|
|
||||||
check = findDirty()
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Pull.Patches != nil {
|
|
||||||
check = findReposWithPatches()
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Pull.Check != nil {
|
|
||||||
// TODO: never wrote this yet
|
|
||||||
// update, err := me.forge.CheckVersions()
|
|
||||||
// return err
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if check.Len() == 0 {
|
|
||||||
// check = doFind()
|
|
||||||
check = findAll()
|
|
||||||
// check = find50()
|
|
||||||
// check = findMine()
|
|
||||||
}
|
|
||||||
|
|
||||||
me.forge.PrintHumanTableFull(check)
|
|
||||||
if argv.Pull.Dirty != nil {
|
|
||||||
log.Info("dirty count =", check.Len())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
found, err := me.forge.LookupPB(check)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("LookupPB() failed", err, "len(check)=", check.Len())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// me.forge.PrintHumanTableFull(found)
|
|
||||||
|
|
||||||
// check to see if the repos need to be updated
|
|
||||||
update := gitpb.NewRepos()
|
|
||||||
|
|
||||||
if found.Len() == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
log.Info("found.Len() ==", found.Len())
|
|
||||||
|
|
||||||
for repo := range found.IterAll() {
|
|
||||||
masterb := repo.GetMasterBranchName()
|
|
||||||
if masterb == "" {
|
|
||||||
log.Info(repo.GetNamespace(), "master branch blank")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
a := repo.GetLocalHash(masterb)
|
|
||||||
ns := repo.GetNamespace()
|
|
||||||
repo2 := me.forge.Repos.FindByNamespace(ns)
|
|
||||||
if repo2 == nil {
|
|
||||||
log.Info("repo namespace does not exist", a, repo.Namespace)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b := repo2.GetLocalHash(repo2.GetMasterBranchName())
|
|
||||||
if b == a {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Info(a, "!=", b, repo.Namespace)
|
|
||||||
update.AppendByNamespace(repo2)
|
|
||||||
}
|
|
||||||
if update.Len() == 0 {
|
|
||||||
// nothing to update
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if _, err := me.forge.UpdatePB(update); err != nil {
|
|
||||||
log.Info("UpdatePB() failed", err, "len(check)=", update.Len())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func doGitPull() {
|
|
||||||
allerr := me.found.RillGitPull(40, 5)
|
|
||||||
|
|
||||||
all := me.found.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
result := allerr[repo]
|
|
||||||
if result.Error == gitpb.ErrorGitPullOnDirty {
|
|
||||||
log.Info("skip git pull. repo is dirty", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if result.Error == gitpb.ErrorGitPullOnLocal {
|
|
||||||
log.Info("skip git pull. local branch ", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if result.Exit == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("git pull error:", repo.GetGoPath(), result.Error)
|
|
||||||
log.Info("git pull error:", repo.GetGoPath(), result.Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// git fetch origin master:master
|
// git fetch origin master:master
|
||||||
func rillFetchMaster(repo *gitpb.Repo) error {
|
func rillFetchMaster(repo *gitpb.Repo) error {
|
||||||
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
|
||||||
|
@ -184,70 +108,4 @@ func doGitFetch() {
|
||||||
me.forge.ConfigSave()
|
me.forge.ConfigSave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doMergeDevel() (*gitpb.Repos, error) {
|
|
||||||
var err error
|
|
||||||
done := gitpb.NewRepos()
|
|
||||||
found := findMergeToDevel()
|
|
||||||
for repo := range found.IterAll() {
|
|
||||||
if repo.CheckDirty() {
|
|
||||||
log.Info("repo is dirty", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Info("Starting merge on", repo.GetGoPath())
|
|
||||||
if repo.CheckoutDevel() {
|
|
||||||
log.Info("checkout devel failed", repo.GetGoPath())
|
|
||||||
err = fmt.Errorf("checkout devel failed")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := repo.MergeToDevel(); err != nil {
|
|
||||||
log.Info("merge from user failed", repo.GetGoPath(), err)
|
|
||||||
err = fmt.Errorf("merge from user failed")
|
|
||||||
// log.Info(strings.Join(r.Stdout, "\n"))
|
|
||||||
// log.Info(strings.Join(r.Stderr, "\n"))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
done.Append(repo)
|
|
||||||
/*
|
|
||||||
if repo.CheckoutMaster() {
|
|
||||||
log.Info("checkout master failed", repo.GetGoPath())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := repo.MergeToMaster(); err != nil {
|
|
||||||
log.Info("merge from devel failed", repo.GetGoPath(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
return done, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func doMergeMaster() (*gitpb.Repos, error) {
|
|
||||||
var err error
|
|
||||||
done := gitpb.NewRepos()
|
|
||||||
found := findMergeToMaster()
|
|
||||||
for repo := range found.IterAll() {
|
|
||||||
if repo.CheckDirty() {
|
|
||||||
log.Info("repo is dirty", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("Starting merge on", repo.GetGoPath())
|
|
||||||
if repo.CheckoutMaster() {
|
|
||||||
log.Info("checkout devel failed", repo.GetGoPath())
|
|
||||||
err = fmt.Errorf("checkout devel failed")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := repo.MergeToMaster(); err != nil {
|
|
||||||
log.Info("merge from user failed", repo.GetGoPath(), err)
|
|
||||||
err = fmt.Errorf("merge from user failed")
|
|
||||||
// log.Info(strings.Join(r.Stdout, "\n"))
|
|
||||||
// log.Info(strings.Join(r.Stderr, "\n"))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
done.Append(repo)
|
|
||||||
}
|
|
||||||
return done, err
|
|
||||||
}
|
|
||||||
|
|
43
doSync.go
43
doSync.go
|
@ -3,18 +3,9 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// trys to figure out if there is still something to update
|
// trys to figure out if there is still something to update
|
||||||
|
|
||||||
|
/*
|
||||||
func doSync() error {
|
func doSync() error {
|
||||||
if argv.Pull.Sync.Clean != nil {
|
if argv.Pull.Sync.Clean != nil {
|
||||||
return doSyncClean()
|
return doSyncClean()
|
||||||
|
@ -27,36 +18,7 @@ func doSync() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSyncClean() error {
|
func doSyncClean() error {
|
||||||
if err := doAllCheckoutMaster(); err != nil {
|
log.Printf("todo: fix this?")
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, _, _, err := IsEverythingOnMaster(); err != nil {
|
|
||||||
log.Info("Not all repos are on the master branch")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// force everything
|
|
||||||
argv.Force = true
|
|
||||||
|
|
||||||
if err := doCleanUser(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := doCleanDevel(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
pullcount := me.forge.RillFuncError(rillPull)
|
|
||||||
count := me.forge.RillReload()
|
|
||||||
if count != 0 {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
total, count, nope, _ := IsEverythingOnMaster()
|
|
||||||
log.Printf("doSyncClean() ok. %d total repos. (%d git pulled) (%d not on master branch) (%s) git pull total=%d\n", total, count, nope, shell.FormatDuration(time.Since(now)), pullcount)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,3 +76,4 @@ func syncDevelBranches() error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
25
doc.go
25
doc.go
|
@ -1,23 +1,16 @@
|
||||||
/*
|
/*
|
||||||
forge -- a tool to git repos at go.wit.com
|
forge -- a tool to manage lots of git repos. forge includes a GUI and TUI.
|
||||||
|
|
||||||
but you can probably use it for other things
|
forge only executes the 'git' command. Everything it does, you can run by hand with 'git'.
|
||||||
|
|
||||||
A video demonstration of the terminal UI is available at:
|
|
||||||
https://mirrors.wit.com/guidemo/forge-gocui-demo.webm
|
|
||||||
|
|
||||||
forge v0.22.124-2-g8c25ed1 Built on 2025.07.21_1348
|
|
||||||
Usage: forge [--debugger] [--logger] [--no-gui] [--gui GUI] [--gui-file GUI-FILE] [--gui-test GUI-TEST] [--gui-verbose] [--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-test GUI-TEST test a specific plugin.so will load
|
|
||||||
--gui-verbose enable all logging
|
--gui-verbose enable all logging
|
||||||
|
--bash generate bash completion
|
||||||
|
--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
|
||||||
|
@ -25,24 +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
|
||||||
patch make patchsets
|
patch make patchsets
|
||||||
pull run 'git pull'
|
pull run 'git pull'
|
||||||
|
tag manage git tags
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
13
exit.go
13
exit.go
|
@ -6,27 +6,28 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/gui"
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func okExit(thing string) {
|
func okExit(thing string) {
|
||||||
if thing != "" {
|
gui.UnloadToolkits()
|
||||||
log.Info("forge exit:", thing, "ok")
|
|
||||||
}
|
|
||||||
if configSave {
|
if configSave {
|
||||||
me.forge.SetConfigSave(configSave)
|
me.forge.SetConfigSave(configSave)
|
||||||
}
|
}
|
||||||
// log.Info("Finished go-clean on", check.GetGoPath(), "ok")
|
if thing != "" {
|
||||||
|
log.Info("forge exit:", thing, "ok")
|
||||||
|
}
|
||||||
me.forge.Exit()
|
me.forge.Exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
// 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"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
|
"go.wit.com/lib/protobuf/gitpb"
|
||||||
|
"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 {
|
||||||
|
sync.Mutex
|
||||||
|
win *gadgets.GenericWindow // the machines gui window
|
||||||
|
box *gui.Node // the machines gui parent box widget
|
||||||
|
TB *forgepb.SetsTable // the gui table buffer
|
||||||
|
update bool // if the window should be updated
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *stdPatchsetTableWin) Toggle() {
|
||||||
|
if w == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if w.win == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.win.Toggle()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
etimef := func(e *forgepb.Set) string {
|
||||||
|
etime := e.Etime.AsTime()
|
||||||
|
s := etime.Format("2006/01/02 15:04")
|
||||||
|
if strings.HasPrefix(s, "1970/") {
|
||||||
|
// just show a blank if it's not set
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
t.AddStringFunc("etime", etimef)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
ctimef := func(p *forgepb.Set) string {
|
||||||
|
ctime := p.Ctime.AsTime()
|
||||||
|
return ctime.Format("2006/01/02 15:04")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func setPatchsetState(p *forgepb.Set) {
|
||||||
|
var bad bool
|
||||||
|
var good bool
|
||||||
|
var done bool = true
|
||||||
|
|
||||||
|
all := p.Patches.All()
|
||||||
|
for all.Scan() {
|
||||||
|
patch := all.Next()
|
||||||
|
// log.Info("patch:", patch.StartHash, patch.CommitHash, patch.Namespace, patch.Filename)
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("could not find repo", patch.Namespace)
|
||||||
|
bad = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := repo.GetHashName(patch.CommitHash); err == nil {
|
||||||
|
// this patch has been applied
|
||||||
|
patch.Applied = true
|
||||||
|
done = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if name, err := repo.GetHashName(patch.StartHash); err == nil {
|
||||||
|
// it might be possible to apply this patch
|
||||||
|
log.Info("patch may be good:", patch.Namespace, name, patch.CommitHash, patch.Filename)
|
||||||
|
good = true
|
||||||
|
} else {
|
||||||
|
// probably screwed up git trees
|
||||||
|
log.Info("patch with unknown origin:", patch.Namespace, name, err, patch.CommitHash, patch.Filename)
|
||||||
|
bad = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bad {
|
||||||
|
p.State = "BAD"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if good {
|
||||||
|
p.State = "TRY"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if done {
|
||||||
|
p.State = "DONE"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanSubject(line string) string {
|
||||||
|
// Regular expression to remove "Subject:" and "[PATCH...]" patterns
|
||||||
|
re := regexp.MustCompile(`(?i)^Subject:\s*(\[\s*PATCH[^\]]*\]\s*)?`)
|
||||||
|
cleaned := re.ReplaceAllString(line, "")
|
||||||
|
return strings.TrimSpace(cleaned)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jcarr@framebook:~/go/src/go.wit.com/lib/protobuf/forgepb$ git branch --contains 4a27e7702b9b975b066ec9d2ee7ac932d86552e3
|
||||||
|
// * jcarr
|
||||||
|
// jcarr@framebook:~/go/src/go.wit.com/lib/protobuf/forgepb$ git merge-base --is-ancestor "4a27e7702b9b975b066ec9d2ee7ac932d86552e3" "devel" ; echo $?
|
||||||
|
// 1
|
||||||
|
// jcarr@framebook:~/go/src/go.wit.com/lib/protobuf/forgepb$ git merge-base --is-ancestor "4a27e7702b9b975b066ec9d2ee7ac932d86552e3" "jcarr" ; echo $?
|
||||||
|
// 0
|
||||||
|
|
||||||
|
func findCommitByHash(hash string, subject string) (string, error) {
|
||||||
|
cmd := exec.Command("git", "log", "--pretty=format:%H %s")
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(out.String(), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(strings.ToLower(line), strings.ToLower(subject)) {
|
||||||
|
return strings.Fields(line)[0], nil // return the commit hash
|
||||||
|
}
|
||||||
|
if strings.Fields(line)[0] == hash {
|
||||||
|
return "", fmt.Errorf("start commit found: %s", hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("no commit found for subject: %s", subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func findCommitBySubject(subject string) (string, error) {
|
||||||
|
cmd := exec.Command("git", "log", "--pretty=format:%H %s", "--grep="+subject, "-i")
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(out.String(), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.Contains(strings.ToLower(line), strings.ToLower(subject)) {
|
||||||
|
return strings.Fields(line)[0], nil // return the commit hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("no commit found for subject: %s", subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if PB changed
|
||||||
|
func setNewCommitHash(patch *forgepb.Patch) error {
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
return log.Errorf("could not find repo %s", patch.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
os.Chdir(repo.GetFullPath())
|
||||||
|
newhash, err := findCommitBySubject(comment)
|
||||||
|
if err != nil {
|
||||||
|
return log.Errorf("patch: not found hash: %s %s %s %s %v", patch.CommitHash, patch.Namespace, comment, newhash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
patchId, err := repo.FindPatchId(newhash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
patch.PatchId = patchId
|
||||||
|
patch.NewHash = newhash
|
||||||
|
|
||||||
|
log.Info("patch: found hash:", patch.CommitHash, newhash, patch.Namespace, comment)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddAllPatches(notdone *forgepb.Patches, pset *forgepb.Set, full bool) {
|
||||||
|
for patch := range pset.Patches.IterAll() {
|
||||||
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
if found := notdone.FindByCommitHash(patch.CommitHash); found != nil {
|
||||||
|
log.Info("duplicate commit hash", patch.Namespace, "patch:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Info("adding patch:", patch.Namespace, patch.CommitHash, comment, newhash)
|
||||||
|
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddNotDonePatches(notdone *forgepb.Patches, pset *forgepb.Set, full bool) {
|
||||||
|
for patch := range pset.Patches.IterAll() {
|
||||||
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
if found := notdone.FindByCommitHash(patch.CommitHash); found != nil {
|
||||||
|
log.Info("duplicate notdone", patch.Namespace, "patch:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("could not find repo", patch.Namespace)
|
||||||
|
if full {
|
||||||
|
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if patch.NewHash != "" {
|
||||||
|
log.Info("already applied patch", patch.Namespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
os.Chdir(repo.GetFullPath())
|
||||||
|
newhash, err := findCommitByHash(patch.StartHash, comment)
|
||||||
|
if err != nil {
|
||||||
|
// this patch has not been applied yet
|
||||||
|
log.Info("patch: not found hash:", patch.Namespace, patch.CommitHash, comment, err)
|
||||||
|
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newhash, err = findCommitBySubject(comment)
|
||||||
|
if err == nil {
|
||||||
|
patch.NewHash = newhash
|
||||||
|
log.Info("patch: found hash:", patch.Namespace, "commit patch", patch.CommitHash, "new hash", newhash, "start hash", patch.StartHash, comment)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// this patch has not been applied yet
|
||||||
|
log.Info("patch: not found hash:", patch.Namespace, patch.CommitHash, comment, newhash, err)
|
||||||
|
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findExpired() *forgepb.Patches {
|
||||||
|
var pset *forgepb.Patches
|
||||||
|
for found := range me.forge.Patchsets.IterAll() {
|
||||||
|
if found.Name == "forge auto commit" {
|
||||||
|
pset = found.Patches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pset == nil {
|
||||||
|
log.Info("failed to find 'forge auto commit'")
|
||||||
|
return forgepb.NewPatches()
|
||||||
|
}
|
||||||
|
|
||||||
|
found := forgepb.NewPatches()
|
||||||
|
|
||||||
|
for patch := range pset.IterAll() {
|
||||||
|
comment := cleanSubject(patch.Comment)
|
||||||
|
|
||||||
|
repo := me.forge.FindByGoPath(patch.Namespace)
|
||||||
|
if repo == nil {
|
||||||
|
log.Info("could not find repo", patch.Namespace)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if patch.NewHash != "" {
|
||||||
|
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
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
os.Chdir(repo.GetFullPath())
|
||||||
|
_, err := findCommitByHash(patch.StartHash, comment)
|
||||||
|
if err == nil {
|
||||||
|
log.Info("found 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
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
newhash, err = findCommitBySubject(comment)
|
||||||
|
if err == nil {
|
||||||
|
patch.NewHash = newhash
|
||||||
|
log.Info("patch: found hash:", patch.Namespace, "commit patch", patch.CommitHash, "new hash", newhash, "start hash", patch.StartHash, comment)
|
||||||
|
found.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
func findApplied() *forgepb.Patches {
|
||||||
|
var pset *forgepb.Patches
|
||||||
|
for found := range me.forge.Patchsets.IterAll() {
|
||||||
|
if found.Name == "forge auto commit" {
|
||||||
|
pset = found.Patches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pset == nil {
|
||||||
|
log.Info("failed to find 'forge auto commit'")
|
||||||
|
return pset
|
||||||
|
}
|
||||||
|
|
||||||
|
found := forgepb.NewPatches()
|
||||||
|
|
||||||
|
for patch := range pset.IterAll() {
|
||||||
|
cmd := []string{"git", "merge-base", "--is-ancestor", patch.NewHash, "devel"}
|
||||||
|
repo := me.forge.Repos.FindByNamespace(patch.Namespace)
|
||||||
|
_, err := repo.RunStrict(cmd)
|
||||||
|
if err != nil {
|
||||||
|
// log.Info("NOT APPLIED", patch.Namespace, result, err)
|
||||||
|
// log.Info("NOT APPLIED newhash:", patch.NewHash, "commithash:", patch.CommitHash, "patch", patch.Namespace)
|
||||||
|
} else {
|
||||||
|
// log.Info("APPLIED newhash:", patch.NewHash, "commithash:", patch.CommitHash, "patch", patch.Namespace)
|
||||||
|
found.Append(patch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found
|
||||||
|
}
|
177
main.go
177
main.go
|
@ -7,12 +7,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.wit.com/dev/alexflint/arg"
|
"go.wit.com/lib/gui/prep"
|
||||||
"go.wit.com/gui"
|
|
||||||
"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"
|
||||||
|
@ -44,35 +41,18 @@ func getVersion(repo *gitpb.Repo, name string) string {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
me = new(mainType)
|
me = new(mainType)
|
||||||
gui.InitArg()
|
me.myGui = prep.Gui() // prepares the GUI package for go-args
|
||||||
me.pp = arg.MustParse(&argv)
|
me.auto = prep.Bash3(&argv) // this line should be: prep.Bash(&argv)
|
||||||
|
|
||||||
if argv.Bash {
|
// me.auto = prep.Bash3(argv.DoAutoComplete, &argv) // this line should be: prep.Bash(&argv)
|
||||||
argv.doBash()
|
// arg.MustParse(&argv) // these three lines are becoming terrible syntax
|
||||||
os.Exit(0)
|
// me.auto = prep.MustParse(&argv) // try to make this work?
|
||||||
}
|
|
||||||
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("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// load the ~/.config/forge/ config
|
// initialize patches
|
||||||
me.forge = forgepb.Init()
|
doPatchInit()
|
||||||
|
|
||||||
// first find the repos or gopaths to operate on
|
// first find the repos or gopaths to operate on
|
||||||
if argv.Config != nil {
|
if argv.Config != nil {
|
||||||
|
@ -112,16 +92,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Clean != nil {
|
if argv.Clean != nil {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -129,42 +99,70 @@ func main() {
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if argv.Help != nil {
|
||||||
|
doHelp()
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
if argv.Dirty != nil {
|
if argv.Dirty != nil {
|
||||||
doDirty()
|
doDirty()
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.GitFetch != nil {
|
if argv.Tag != nil {
|
||||||
doGitFetch()
|
doTag()
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if argv.Normal != nil {
|
||||||
|
if argv.Normal.On != nil {
|
||||||
|
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
||||||
|
log.Info("you are already in the normal state")
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
setForgeMode(forgepb.ForgeMode_NORMAL)
|
||||||
|
log.Info("normal mode on")
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if argv.Normal.Off != nil {
|
||||||
|
if me.forge.Config.Mode != forgepb.ForgeMode_NORMAL {
|
||||||
|
log.Info("you were aleady not in the normal state")
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
setForgeMode(forgepb.ForgeMode_DEVEL)
|
||||||
|
log.Info("normal mode off")
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if doNormal() {
|
||||||
|
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 {
|
||||||
|
log.Infof("Forge has set the mode to 'Normal'\n")
|
||||||
|
setForgeMode(forgepb.ForgeMode_NORMAL)
|
||||||
|
}
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if you are in "normal" mode, always run normal every time to catch accidental errors
|
||||||
|
// for example, if you accidentally changed branches from your user branch
|
||||||
|
if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL {
|
||||||
|
if doNormal() {
|
||||||
|
log.Infof("all your %d repos are in a normal stete for development\n", me.forge.Repos.Len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if argv.Merge != nil {
|
if argv.Merge != nil {
|
||||||
if argv.Merge.Devel != nil {
|
if err := doMerge(); err != nil {
|
||||||
if _, err := doMergeDevel(); err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
okExit("devel merge ok")
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Merge.Master != nil {
|
|
||||||
if _, err := doMergeMaster(); err != nil {
|
|
||||||
badExit(err)
|
|
||||||
}
|
|
||||||
okExit("master merge ok")
|
|
||||||
}
|
|
||||||
badExit(fmt.Errorf("merge what?"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if argv.Pull != nil {
|
|
||||||
if argv.Pull.Sync != nil {
|
|
||||||
if err := doSync(); err != nil {
|
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
doGitPullNew()
|
if argv.Pull != nil {
|
||||||
|
doPull()
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,29 +181,50 @@ func main() {
|
||||||
if err := doPatch(); err != nil {
|
if err := doPatch(); err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
okExit("patch list")
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: redo this logic using forgepb
|
|
||||||
if configSave {
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
configSave = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the user doesn't want to open the GUI and
|
|
||||||
// nothing else was specified to be done,
|
|
||||||
// then just list the table to stdout
|
|
||||||
if gui.NoGui() {
|
|
||||||
found := doFind()
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// open the gui unless the user performed some other
|
// open the gui unless the user performed some other
|
||||||
// basically, if you run just 'forge' it should open the GUI
|
// basically, if you run just 'forge' it should open the GUI
|
||||||
|
|
||||||
|
if argv.Gui != nil {
|
||||||
// if opening the GUI, always check git for dirty repos
|
// if opening the GUI, always check git for dirty repos
|
||||||
doCheckDirtyAndConfigSave()
|
me.forge.CheckDirty()
|
||||||
doGui()
|
|
||||||
|
me.myGui.Start() // loads the GUI toolkit
|
||||||
|
doGui() // start making our forge GUI
|
||||||
|
debug() // sits here forever
|
||||||
|
}
|
||||||
|
// got to the end with nothing to do (?)
|
||||||
|
if dumpWorkRepos() {
|
||||||
|
// found some repos at least
|
||||||
|
} else {
|
||||||
|
// every repo is in a really clean state. no extra files anywhere
|
||||||
|
// no dirty repos, no repos that need to be published
|
||||||
|
// nothing different between user and master branch version. not common
|
||||||
|
log.Info("All of your git repositories appear to be in perfect shape")
|
||||||
|
}
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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("")
|
||||||
|
okExit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func doHelpPatches() {
|
||||||
|
log.Info("TODO: ?")
|
||||||
okExit("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
14
structs.go
14
structs.go
|
@ -4,9 +4,9 @@
|
||||||
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/protobuf/forgepb"
|
"go.wit.com/lib/protobuf/forgepb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,12 +20,17 @@ func (b *mainType) Enable() {
|
||||||
b.mainbox.Enable()
|
b.mainbox.Enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the server to connect to
|
||||||
|
func myServer() string {
|
||||||
|
return me.forge.GetForgeURL()
|
||||||
|
}
|
||||||
|
|
||||||
// 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 *gui.Node // the gui toolkit handle
|
myGui *prep.GuiPrep // for initializing the GUI toolkits
|
||||||
psets *forgepb.Patchsets // the locally stored on disk patchsets
|
|
||||||
foundPaths []string // stores gopaths to act on (when doing go-clone)
|
foundPaths []string // stores gopaths to act on (when doing go-clone)
|
||||||
configSave bool // if the config file should be saved after finishing
|
configSave bool // if the config file should be saved after finishing
|
||||||
urlbase string // base URL
|
urlbase string // base URL
|
||||||
|
@ -34,6 +39,7 @@ type mainType struct {
|
||||||
mainbox *gui.Node // the main box. enable/disable this
|
mainbox *gui.Node // the main box. enable/disable this
|
||||||
autoDryRun *gui.Node // checkbox for --dry-run
|
autoDryRun *gui.Node // checkbox for --dry-run
|
||||||
goSrcPwd *gadgets.OneLiner // what is being used as primary directory for your work
|
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
|
gitAuthor *gadgets.OneLiner // ENV GIT_AUTHOR NAME and EMAIL
|
||||||
|
|
||||||
// these hold the branches that the user can switch all the repositories to them
|
// these hold the branches that the user can switch all the repositories to them
|
||||||
|
|
|
@ -1,164 +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
|
|
||||||
|
|
||||||
// this is the "main" patch window. The first one
|
|
||||||
// then you can dig down and examine the patchsets and the files
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"go.wit.com/lib/gadgets"
|
|
||||||
"go.wit.com/log"
|
|
||||||
|
|
||||||
"go.wit.com/gui"
|
|
||||||
)
|
|
||||||
|
|
||||||
type patchesWindow struct {
|
|
||||||
win *gadgets.BasicWindow // the patches window
|
|
||||||
stack *gui.Node // the top box set as vertical
|
|
||||||
grid *gui.Node // the list of available patches
|
|
||||||
reason *gadgets.BasicEntry // the name of the patchset
|
|
||||||
submitB *gui.Node // the submit patchet button
|
|
||||||
psetgrid *gui.Node // the list of each patchset
|
|
||||||
totalOL *gadgets.OneLiner
|
|
||||||
dirtyOL *gadgets.OneLiner
|
|
||||||
readonlyOL *gadgets.OneLiner
|
|
||||||
rw *gadgets.OneLiner
|
|
||||||
// checkB *gui.Node
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *patchesWindow) Hidden() bool {
|
|
||||||
return r.win.Hidden()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *patchesWindow) Toggle() {
|
|
||||||
if r.Hidden() {
|
|
||||||
r.Show()
|
|
||||||
} else {
|
|
||||||
r.Hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *patchesWindow) Show() {
|
|
||||||
r.win.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *patchesWindow) Hide() {
|
|
||||||
r.win.Hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
// you can only have one of these
|
|
||||||
func (r *patchesWindow) initWindow() {
|
|
||||||
r.win = gadgets.RawBasicWindow("Forge Patchesets")
|
|
||||||
r.win.Make()
|
|
||||||
|
|
||||||
r.stack = r.win.Box().NewBox("bw vbox", false)
|
|
||||||
// me.reposwin.Draw()
|
|
||||||
r.win.Custom = func() {
|
|
||||||
log.Warn("Patchset Window close. setting hidden=true")
|
|
||||||
// sets the hidden flag to false so Toggle() works
|
|
||||||
r.win.Hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
r.grid = r.stack.RawGrid()
|
|
||||||
r.submitPatchesBox()
|
|
||||||
|
|
||||||
// update the stats about the repos and patches
|
|
||||||
r.Update()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *patchesWindow) submitPatchesBox() {
|
|
||||||
// s := new(patchSummary)
|
|
||||||
group1 := r.stack.NewGroup("Repo Summary")
|
|
||||||
grid := group1.RawGrid()
|
|
||||||
|
|
||||||
// make the header table for repo stats
|
|
||||||
r.totalOL = gadgets.NewOneLiner(grid, "Total")
|
|
||||||
|
|
||||||
grid.NextRow()
|
|
||||||
r.dirtyOL = gadgets.NewOneLiner(grid, "dirty")
|
|
||||||
grid.NextRow()
|
|
||||||
r.readonlyOL = gadgets.NewOneLiner(grid, "read-only")
|
|
||||||
grid.NextRow()
|
|
||||||
r.rw = gadgets.NewOneLiner(grid, "r/w")
|
|
||||||
grid.NextRow()
|
|
||||||
|
|
||||||
// now, make the 'widget group' and the buttons at the bottom of the window
|
|
||||||
group1 = r.stack.NewGroup("Patchset Create")
|
|
||||||
grid = group1.RawGrid()
|
|
||||||
|
|
||||||
grid.NewButton("show current patches", func() {
|
|
||||||
r.Update()
|
|
||||||
pset, err := me.forge.MakeDevelPatchSet("current patches")
|
|
||||||
if err != nil {
|
|
||||||
log.Info("patchset creation failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if pset == nil {
|
|
||||||
log.Info("you have no current patches")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
win := makePatchWindow(pset)
|
|
||||||
win.Show()
|
|
||||||
*/
|
|
||||||
})
|
|
||||||
|
|
||||||
r.reason = gadgets.NewBasicEntry(grid, "Patchset name:")
|
|
||||||
r.reason.Custom = func() {
|
|
||||||
if r.reason.String() != "" {
|
|
||||||
log.Info("Forge: enable submit")
|
|
||||||
r.submitB.Enable()
|
|
||||||
} else {
|
|
||||||
log.Info("Forge: disable submit")
|
|
||||||
r.submitB.Disable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.submitB = grid.NewButton("Submit", func() {
|
|
||||||
if r.submitB.IsEnabled() {
|
|
||||||
log.Info("submit button is enabled")
|
|
||||||
} else {
|
|
||||||
log.Info("submit button is disabled. BAD GUI TOOLKIT ERROR")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// pset, err := me.forge.SubmitDevelPatchSet(r.reason.String())
|
|
||||||
// if err != nil {
|
|
||||||
// log.Info(err)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// r.addPatchsetNew(pset)
|
|
||||||
})
|
|
||||||
|
|
||||||
// disables the submit button until the user enters a name
|
|
||||||
r.submitB.Disable()
|
|
||||||
grid.NextRow()
|
|
||||||
}
|
|
||||||
|
|
||||||
// will update this from the current state of the protobuf
|
|
||||||
func (r *patchesWindow) Update() {
|
|
||||||
var total, dirty, readonly, rw int
|
|
||||||
|
|
||||||
// figure out the totals
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
total += 1
|
|
||||||
if repo.IsDirty() {
|
|
||||||
dirty += 1
|
|
||||||
}
|
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
|
||||||
readonly += 1
|
|
||||||
} else {
|
|
||||||
rw += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the values to the GUI toolkit
|
|
||||||
r.totalOL.SetText(strconv.Itoa(total) + " repos")
|
|
||||||
r.dirtyOL.SetText(strconv.Itoa(dirty) + " repos")
|
|
||||||
r.readonlyOL.SetText(strconv.Itoa(readonly) + " repos")
|
|
||||||
r.rw.SetText(fmt.Sprintf("%d repos", rw))
|
|
||||||
}
|
|
100
windowFound.go
100
windowFound.go
|
@ -1,100 +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
|
|
||||||
|
|
||||||
// shows a window of the 'found' repos
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go.wit.com/lib/gadgets"
|
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
|
|
||||||
"go.wit.com/gui"
|
|
||||||
)
|
|
||||||
|
|
||||||
type foundWindow struct {
|
|
||||||
win *gadgets.BasicWindow // the patches window
|
|
||||||
stack *gui.Node // the top box set as vertical
|
|
||||||
grid *gui.Node // the list of available patches
|
|
||||||
reason *gadgets.BasicEntry // the name of the patchset
|
|
||||||
submitB *gui.Node // the submit patchet button
|
|
||||||
psetgrid *gui.Node // the list of each patchset
|
|
||||||
totalOL *gadgets.OneLiner
|
|
||||||
dirtyOL *gadgets.OneLiner
|
|
||||||
readonlyOL *gadgets.OneLiner
|
|
||||||
rw *gadgets.OneLiner
|
|
||||||
found *gitpb.Repos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) Hidden() bool {
|
|
||||||
return r.win.Hidden()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) Toggle() {
|
|
||||||
if r.Hidden() {
|
|
||||||
r.Show()
|
|
||||||
} else {
|
|
||||||
r.Hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) Show() {
|
|
||||||
r.win.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) Hide() {
|
|
||||||
r.win.Hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
// you can only have one of these
|
|
||||||
func (r *foundWindow) initWindow() {
|
|
||||||
r.win = gadgets.RawBasicWindow("Found Repos")
|
|
||||||
r.win.Make()
|
|
||||||
|
|
||||||
r.stack = r.win.Box().NewBox("bw vbox", false)
|
|
||||||
// me.reposwin.Draw()
|
|
||||||
r.win.Custom = func() {
|
|
||||||
log.Warn("Found Window close. setting hidden=true")
|
|
||||||
// sets the hidden flag to false so Toggle() works
|
|
||||||
r.win.Hide()
|
|
||||||
}
|
|
||||||
group1 := r.stack.NewGroup("Repo Summary")
|
|
||||||
group1.NewButton("dirty", func() {
|
|
||||||
log.Info("find dirty here")
|
|
||||||
found := findDirty()
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
})
|
|
||||||
group1.NewButton("all", func() {
|
|
||||||
log.Info("find all here")
|
|
||||||
found := findAll()
|
|
||||||
me.forge.PrintHumanTable(found)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.grid = r.stack.RawGrid()
|
|
||||||
|
|
||||||
group1.NewButton("show", func() {
|
|
||||||
r.listRepos()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) listRepos() {
|
|
||||||
for repo := range r.found.IterAll() {
|
|
||||||
r.addRepo(repo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *foundWindow) addRepo(repo *gitpb.Repo) {
|
|
||||||
r.grid.NewButton("View", func() {
|
|
||||||
})
|
|
||||||
r.grid.NewLabel(repo.GetGoPath())
|
|
||||||
r.grid.NewLabel(repo.GetMasterVersion())
|
|
||||||
r.grid.NewLabel(repo.GetDevelVersion())
|
|
||||||
r.grid.NewLabel(repo.GetUserVersion())
|
|
||||||
r.grid.NewLabel(repo.GetCurrentBranchName())
|
|
||||||
r.grid.NextRow()
|
|
||||||
}
|
|
||||||
|
|
||||||
// will update this from the current state of the protobuf
|
|
||||||
func (r *foundWindow) Update() {
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
|
|
@ -1,148 +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 (
|
|
||||||
"go.wit.com/lib/gadgets"
|
|
||||||
"go.wit.com/lib/protobuf/gitpb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// An app to submit patches for the 30 GO GUI repos
|
|
||||||
|
|
||||||
func makeModeMasterWin() *gadgets.GenericWindow {
|
|
||||||
win := gadgets.NewGenericWindow("Release", "tools")
|
|
||||||
grid := win.Group.RawGrid()
|
|
||||||
|
|
||||||
checkout := grid.NewButton("git checkout master", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
})
|
|
||||||
gitpull := grid.NewButton("git pull", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
})
|
|
||||||
grid.NextRow()
|
|
||||||
|
|
||||||
cleanUser := grid.NewButton("Clean user branches", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
if err := doCleanUser(); err != nil {
|
|
||||||
log.Info("Clean user branches failed", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
cleanDevel := grid.NewButton("Clean devel branches", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
if err := doCleanDevel(); err != nil {
|
|
||||||
log.Info("Clean devel branches failed", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
grid.NextRow()
|
|
||||||
|
|
||||||
f := func() {
|
|
||||||
total, count, nope, err := IsEverythingOnMaster()
|
|
||||||
if nope == 0 {
|
|
||||||
checkout.Disable()
|
|
||||||
gitpull.Enable()
|
|
||||||
} else {
|
|
||||||
log.Printf("Master branch check. %d total repos. (%d ok) (%d not on master branch) err=%v\n", total, count, nope, err)
|
|
||||||
checkout.Enable()
|
|
||||||
}
|
|
||||||
|
|
||||||
var localuser bool // are there still local user branches
|
|
||||||
var localdevel bool // are there still local devel branches
|
|
||||||
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
if repo.IsLocalBranch(repo.GetUserBranchName()) {
|
|
||||||
localuser = true
|
|
||||||
}
|
|
||||||
if repo.IsLocalBranch(repo.GetDevelBranchName()) {
|
|
||||||
localdevel = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if localuser {
|
|
||||||
cleanUser.Enable()
|
|
||||||
} else {
|
|
||||||
cleanUser.Disable()
|
|
||||||
}
|
|
||||||
if localdevel {
|
|
||||||
cleanDevel.Enable()
|
|
||||||
} else {
|
|
||||||
cleanDevel.Disable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grid.NewButton("check repo state", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
|
|
||||||
f()
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("reset user branches (?)", func() {
|
|
||||||
resetUserBranchesWindow()
|
|
||||||
})
|
|
||||||
return win
|
|
||||||
}
|
|
||||||
|
|
||||||
func resetUserBranchesWindow() {
|
|
||||||
found := gitpb.NewRepos()
|
|
||||||
all := me.forge.Repos.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
uname := repo.GetUserBranchName()
|
|
||||||
dname := repo.GetDevelBranchName()
|
|
||||||
if repo.GetCurrentBranchName() == uname {
|
|
||||||
log.Info("Repo is on the user branch. Can't delete it.", repo.GetGoPath())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b1 := repo.CountDiffObjects(uname, dname)
|
|
||||||
b2 := repo.CountDiffObjects(dname, uname)
|
|
||||||
log.Info("user vs devel count", b1, b2)
|
|
||||||
if b1 == 0 && b2 == 0 {
|
|
||||||
cmd := []string{"git", "branch", "-D", uname}
|
|
||||||
log.Info(repo.GetGoPath(), cmd)
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
repo.Reload()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found.Append(repo)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
win := gadgets.RawBasicWindow("reset user branches")
|
|
||||||
win.Make()
|
|
||||||
win.Show()
|
|
||||||
win.Custom = func() {
|
|
||||||
// sets the hidden flag to false so Toggle() works
|
|
||||||
win.Hide()
|
|
||||||
}
|
|
||||||
box := win.Box().NewBox("bw vbox", false)
|
|
||||||
|
|
||||||
group := box.NewGroup("test buttons")
|
|
||||||
hbox := group.Box().Horizontal()
|
|
||||||
hbox.NewButton("force delete user branch", func() {
|
|
||||||
win.Disable()
|
|
||||||
defer win.Enable()
|
|
||||||
all := found.SortByFullPath()
|
|
||||||
for all.Scan() {
|
|
||||||
repo := all.Next()
|
|
||||||
brname := repo.GetUserBranchName()
|
|
||||||
cmd := []string{"git", "branch", "-D", brname}
|
|
||||||
log.Info(repo.GetGoPath(), cmd)
|
|
||||||
repo.RunVerbose(cmd)
|
|
||||||
repo.Reload()
|
|
||||||
}
|
|
||||||
me.forge.SetConfigSave(true)
|
|
||||||
me.forge.ConfigSave()
|
|
||||||
})
|
|
||||||
|
|
||||||
t := makeStandardReposGrid(found)
|
|
||||||
t.SetParent(box)
|
|
||||||
t.ShowTable()
|
|
||||||
}
|
|
128
windowPatches.go
128
windowPatches.go
|
@ -39,6 +39,7 @@ func makePatchesWin(patches *forgepb.Patches) *stdPatchTableWin {
|
||||||
dwin.win = gadgets.NewGenericWindow("current patches", "patching options")
|
dwin.win = gadgets.NewGenericWindow("current patches", "patching options")
|
||||||
dwin.win.Custom = func() {
|
dwin.win.Custom = func() {
|
||||||
log.Info("test delete window here")
|
log.Info("test delete window here")
|
||||||
|
dwin.win.Hide()
|
||||||
// dwin = nil
|
// dwin = nil
|
||||||
}
|
}
|
||||||
grid := dwin.win.Group.RawGrid()
|
grid := dwin.win.Group.RawGrid()
|
||||||
|
@ -51,54 +52,18 @@ func makePatchesWin(patches *forgepb.Patches) *stdPatchTableWin {
|
||||||
all := patches.All()
|
all := patches.All()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
patch := all.Next()
|
patch := all.Next()
|
||||||
repomap[patch.RepoNamespace] += 1
|
repomap[patch.Namespace] += 1
|
||||||
}
|
}
|
||||||
grid.NewLabel(fmt.Sprintf("%d", len(repomap)))
|
grid.NewLabel(fmt.Sprintf("%d", len(repomap)))
|
||||||
grid.NewLabel(fmt.Sprintf("total repos"))
|
grid.NewLabel(fmt.Sprintf("total repos"))
|
||||||
grid.NextRow()
|
grid.NextRow()
|
||||||
|
|
||||||
grid.NewButton("show all", func() {
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
notdone := new(forgepb.Patches)
|
|
||||||
|
|
||||||
all := me.psets.All()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
AddNotDonePatches(notdone, pset, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
for patch := range notdone.IterAll() {
|
|
||||||
comment := cleanSubject(patch.Comment)
|
|
||||||
log.Info("new patch:", patch.NewHash, "commithash:", patch.CommitHash, patch.RepoNamespace, comment)
|
|
||||||
}
|
|
||||||
dwin.doPatchesTable(notdone)
|
|
||||||
})
|
|
||||||
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()
|
||||||
rn := p.RepoNamespace
|
applyPatchNew(p)
|
||||||
repo := me.forge.FindByGoPath(rn)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("Could not figure out repo path", rn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
filename, err := savePatch(p)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("savePatch() failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count += 1
|
|
||||||
if err := applyPatch(repo, filename); 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)
|
||||||
})
|
})
|
||||||
|
@ -114,20 +79,16 @@ func makePatchesWin(patches *forgepb.Patches) *stdPatchTableWin {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyPatchNew(p *forgepb.Patch) error {
|
func applyPatchNew(p *forgepb.Patch) error {
|
||||||
rn := p.RepoNamespace
|
rn := p.Namespace
|
||||||
repo := me.forge.FindByGoPath(rn)
|
repo := me.forge.FindByGoPath(rn)
|
||||||
if repo == nil {
|
if repo == nil {
|
||||||
return fmt.Errorf("Could not figure out repo path %s", rn)
|
log.Info("Could not figure out repo path", rn)
|
||||||
|
return log.Errorf("%s namespace?\n", rn)
|
||||||
}
|
}
|
||||||
filename, err := savePatch(p)
|
if _, err := applyAndTrackPatch(repo, p); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Info("savePatch() failed", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := applyPatch(repo, filename); err != nil {
|
|
||||||
log.Info("warn user of git am error", err)
|
|
||||||
cmd := []string{"git", "am", "--abort"}
|
cmd := []string{"git", "am", "--abort"}
|
||||||
err := repo.RunVerbose(cmd)
|
err := repo.RunVerbose(cmd)
|
||||||
|
log.Info("warn user of git am error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -149,21 +110,20 @@ func (dwin *stdPatchTableWin) doPatchesTable(currentPatches *forgepb.Patches) {
|
||||||
dwin.TB.Custom(f)
|
dwin.TB.Custom(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// define what rows to have in the protobuf table
|
// used by the PB table
|
||||||
func AddPatchesPB(tbox *gui.Node, pb *forgepb.Patches) *forgepb.PatchesTable {
|
func applyPatchLabel(p *forgepb.Patch) string {
|
||||||
t := pb.NewTable("PatchesPB")
|
rn := p.Namespace
|
||||||
t.NewUuid()
|
|
||||||
t.SetParent(tbox)
|
|
||||||
|
|
||||||
gitam := t.AddButtonFunc("apply", func(p *forgepb.Patch) string {
|
|
||||||
rn := p.RepoNamespace
|
|
||||||
if repo := me.forge.FindByGoPath(rn); repo == nil {
|
if repo := me.forge.FindByGoPath(rn); repo == nil {
|
||||||
// log.Info("Could not figure out repo path", rn)
|
// log.Info("Could not figure out repo path", rn)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
if p.NewHash == "" {
|
||||||
return "git am"
|
return "git am"
|
||||||
})
|
}
|
||||||
gitam.Custom = func(p *forgepb.Patch) {
|
return "done"
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyPatchClick(p *forgepb.Patch) {
|
||||||
if err := applyPatchNew(p); err != nil {
|
if err := applyPatchNew(p); err != nil {
|
||||||
log.Info("git am failed on file", p.Filename, "with error", err)
|
log.Info("git am failed on file", p.Filename, "with error", err)
|
||||||
return
|
return
|
||||||
|
@ -171,8 +131,17 @@ func AddPatchesPB(tbox *gui.Node, pb *forgepb.Patches) *forgepb.PatchesTable {
|
||||||
log.Info("ran: git am", p.Filename, "ok")
|
log.Info("ran: git am", p.Filename, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// define what rows to have in the protobuf table
|
||||||
|
func AddPatchesPB(tbox *gui.Node, pb *forgepb.Patches) *forgepb.PatchesTable {
|
||||||
|
t := pb.NewTable("PatchesPB")
|
||||||
|
t.NewUuid()
|
||||||
|
t.SetParent(tbox)
|
||||||
|
|
||||||
|
gitam := t.AddButtonFunc("apply", applyPatchLabel)
|
||||||
|
gitam.Custom = applyPatchClick
|
||||||
|
|
||||||
t.AddCommitHash()
|
t.AddCommitHash()
|
||||||
t.AddRepoNamespace()
|
t.AddNamespace()
|
||||||
// t.AddFilename()
|
// t.AddFilename()
|
||||||
t.AddStringFunc("file", func(p *forgepb.Patch) string {
|
t.AddStringFunc("file", func(p *forgepb.Patch) string {
|
||||||
_, fname := filepath.Split(p.Filename)
|
_, fname := filepath.Split(p.Filename)
|
||||||
|
@ -203,3 +172,46 @@ func savePatch(p *forgepb.Patch) (string, error) {
|
||||||
|
|
||||||
return tmpname, nil
|
return tmpname, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyAndTrackPatch(repo *gitpb.Repo, p *forgepb.Patch) (string, error) {
|
||||||
|
_, filen := filepath.Split(p.Filename)
|
||||||
|
tmpname := filepath.Join("/tmp", filen)
|
||||||
|
log.Info("saving as", tmpname, p.Filename)
|
||||||
|
raw, err := os.OpenFile(tmpname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
raw.Write(p.Data)
|
||||||
|
raw.Close()
|
||||||
|
|
||||||
|
cmd := []string{"git", "am", tmpname}
|
||||||
|
err = repo.RunVerbose(cmd)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("git am failed. run 'git am --abort' here")
|
||||||
|
return "", log.Errorf("git am failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Try to find hash value now")
|
||||||
|
|
||||||
|
p.NewHash = "fixme applyAndTrack"
|
||||||
|
if setNewHash(p, p.NewHash) {
|
||||||
|
log.Info("setting NewHash worked", p.NewHash)
|
||||||
|
}
|
||||||
|
me.forge.SavePatchsets()
|
||||||
|
|
||||||
|
return p.NewHash, log.Errorf("did not lookup new hash")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNewHash(p *forgepb.Patch, hash string) bool {
|
||||||
|
for pset := range me.forge.Patchsets.IterAll() {
|
||||||
|
for patch := range pset.Patches.IterAll() {
|
||||||
|
if patch.CommitHash == hash {
|
||||||
|
patch.NewHash = hash
|
||||||
|
log.Info("found patch in repo")
|
||||||
|
me.forge.SavePatchsets()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -1,422 +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"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"go.wit.com/gui"
|
|
||||||
"go.wit.com/lib/gadgets"
|
|
||||||
"go.wit.com/lib/protobuf/forgepb"
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stdPatchsetTableWin struct {
|
|
||||||
sync.Mutex
|
|
||||||
win *gadgets.GenericWindow // the machines gui window
|
|
||||||
box *gui.Node // the machines gui parent box widget
|
|
||||||
TB *forgepb.PatchsetsTable // the gui table buffer
|
|
||||||
update bool // if the window should be updated
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *stdPatchsetTableWin) Toggle() {
|
|
||||||
if w == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if w.win == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.win.Toggle()
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadUpstreamPatchsets() {
|
|
||||||
psets, err := me.forge.GetPatchesets()
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Get Patchsets failed", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var foundnew bool
|
|
||||||
all := psets.All()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
found := me.psets.FindByUuid(pset.Uuid)
|
|
||||||
if found == nil {
|
|
||||||
log.Info("new patchset", pset.Name, pset.Uuid)
|
|
||||||
pset.State = "new"
|
|
||||||
foundnew = true
|
|
||||||
} else {
|
|
||||||
log.Info("patchset already on disk", found.Name, found.State)
|
|
||||||
pset.State = found.State
|
|
||||||
if pset.State == "" {
|
|
||||||
pset.State = "new"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if foundnew {
|
|
||||||
log.Info("should save these here")
|
|
||||||
me.psets = psets
|
|
||||||
savePatchsets()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makePatchsetsWin() *stdPatchsetTableWin {
|
|
||||||
dwin := new(stdPatchsetTableWin)
|
|
||||||
dwin.win = gadgets.NewGenericWindow("forge current patchsets", "patchset options")
|
|
||||||
dwin.win.Custom = func() {
|
|
||||||
log.Info("test delete window here")
|
|
||||||
}
|
|
||||||
grid := dwin.win.Group.RawGrid()
|
|
||||||
|
|
||||||
grid.NewButton("ondisk", func() {
|
|
||||||
openPatchsets()
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dwin.doPatchsetsTable(me.psets)
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("upstream", func() {
|
|
||||||
loadUpstreamPatchsets()
|
|
||||||
dwin.doPatchsetsTable(me.psets)
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("save", func() {
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
savePatchsets()
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("set patchset state", func() {
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
all := me.psets.All()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
if pset.State == "" {
|
|
||||||
log.Info("What is up with?", pset.Name)
|
|
||||||
setPatchsetState(pset)
|
|
||||||
} else {
|
|
||||||
log.Info("patchset already had state", pset.Name, pset.State)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
savePatchsets()
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("find commit hashes", func() {
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
all := me.psets.All()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
if pset.State != "new" {
|
|
||||||
log.Info("patchset already had state", pset.Name, pset.State)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if setNewCommitHash(pset) {
|
|
||||||
// everything in this patchset is applied
|
|
||||||
pset.State = "APPLIED"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
savePatchsets()
|
|
||||||
})
|
|
||||||
|
|
||||||
grid.NewButton("show pending patches", func() {
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("No Patchsets loaded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
notdone := new(forgepb.Patches)
|
|
||||||
|
|
||||||
all := me.psets.All()
|
|
||||||
for all.Scan() {
|
|
||||||
pset := all.Next()
|
|
||||||
AddNotDonePatches(notdone, pset, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
for patch := range notdone.IterAll() {
|
|
||||||
comment := cleanSubject(patch.Comment)
|
|
||||||
log.Info("new patch:", patch.NewHash, "commithash:", patch.CommitHash, patch.RepoNamespace, comment)
|
|
||||||
}
|
|
||||||
// savePatchsets()
|
|
||||||
makePatchesWin(notdone)
|
|
||||||
})
|
|
||||||
|
|
||||||
// make a box at the bottom of the window for the protobuf table
|
|
||||||
dwin.box = dwin.win.Bottom.Box().SetProgName("TBOX")
|
|
||||||
|
|
||||||
// load and show the current patch sets
|
|
||||||
openPatchsets()
|
|
||||||
if me.psets == nil {
|
|
||||||
log.Info("Open Patchsets failed")
|
|
||||||
return dwin
|
|
||||||
}
|
|
||||||
dwin.doPatchsetsTable(me.psets)
|
|
||||||
|
|
||||||
return dwin
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dwin *stdPatchsetTableWin) doPatchsetsTable(currentPatchsets *forgepb.Patchsets) {
|
|
||||||
dwin.Lock()
|
|
||||||
defer dwin.Unlock()
|
|
||||||
if dwin.TB != nil {
|
|
||||||
dwin.TB.Delete()
|
|
||||||
dwin.TB = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// display the protobuf
|
|
||||||
dwin.TB = AddPatchsetsPB(dwin.box, currentPatchsets)
|
|
||||||
f := func(pset *forgepb.Patchset) {
|
|
||||||
log.Info("Triggered. do something here", pset.Name)
|
|
||||||
/*
|
|
||||||
win := makePatchWindow(pset)
|
|
||||||
win.Show()
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
dwin.TB.Custom(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddPatchsetsPB(tbox *gui.Node, pb *forgepb.Patchsets) *forgepb.PatchsetsTable {
|
|
||||||
t := pb.NewTable("PatchsetsPB")
|
|
||||||
t.NewUuid()
|
|
||||||
t.SetParent(tbox)
|
|
||||||
|
|
||||||
t.AddStringFunc("#", func(p *forgepb.Patchset) string {
|
|
||||||
return fmt.Sprintf("%d", p.Patches.Len())
|
|
||||||
})
|
|
||||||
|
|
||||||
vp := t.AddButtonFunc("View Patchset", func(p *forgepb.Patchset) string {
|
|
||||||
return p.Name
|
|
||||||
})
|
|
||||||
vp.Custom = func(pset *forgepb.Patchset) {
|
|
||||||
log.Info("show patches here", pset.Name)
|
|
||||||
makePatchesWin(pset.Patches)
|
|
||||||
// patchwin := makePatchesWin()
|
|
||||||
// patchwin.doPatchesTable(pset.Patches)
|
|
||||||
/*
|
|
||||||
win := makePatchWindow(pset)
|
|
||||||
win.Show()
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
t.AddComment()
|
|
||||||
t.AddState()
|
|
||||||
t.AddHostname()
|
|
||||||
|
|
||||||
ctimef := func(p *forgepb.Patchset) string {
|
|
||||||
ctime := p.Ctime.AsTime()
|
|
||||||
return ctime.Format("2006/01/02 15:04")
|
|
||||||
}
|
|
||||||
t.AddStringFunc("ctime", ctimef)
|
|
||||||
|
|
||||||
/*
|
|
||||||
etimef := func(e *forgepb.Patchset) string {
|
|
||||||
etime := e.Etime.AsTime()
|
|
||||||
s := etime.Format("2006/01/02 15:04")
|
|
||||||
if strings.HasPrefix(s, "1970/") {
|
|
||||||
// just show a blank if it's not set
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
t.AddStringFunc("etime", etimef)
|
|
||||||
*/
|
|
||||||
|
|
||||||
t.AddStringFunc("Author", func(p *forgepb.Patchset) string {
|
|
||||||
return fmt.Sprintf("%s <%s>", p.GitAuthorName, p.GitAuthorEmail)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.AddUuid()
|
|
||||||
|
|
||||||
newCommit := t.AddButtonFunc("new hash", func(p *forgepb.Patchset) string {
|
|
||||||
return "find"
|
|
||||||
})
|
|
||||||
newCommit.Custom = func(pset *forgepb.Patchset) {
|
|
||||||
log.Info("find new commits here", pset.Name)
|
|
||||||
// makePatchesWin(pset.Patches)
|
|
||||||
setNewCommitHash(pset)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.ShowTable()
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func setPatchsetState(p *forgepb.Patchset) {
|
|
||||||
var bad bool
|
|
||||||
var good bool
|
|
||||||
var done bool = true
|
|
||||||
|
|
||||||
all := p.Patches.All()
|
|
||||||
for all.Scan() {
|
|
||||||
patch := all.Next()
|
|
||||||
// log.Info("patch:", patch.StartHash, patch.CommitHash, patch.RepoNamespace, patch.Filename)
|
|
||||||
repo := me.forge.FindByGoPath(patch.RepoNamespace)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("could not find repo", patch.RepoNamespace)
|
|
||||||
bad = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := repo.GetHashName(patch.CommitHash); err == nil {
|
|
||||||
// this patch has been applied
|
|
||||||
patch.Applied = true
|
|
||||||
done = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name, err := repo.GetHashName(patch.StartHash); err == nil {
|
|
||||||
// it might be possible to apply this patch
|
|
||||||
log.Info("patch may be good:", patch.RepoNamespace, name, patch.CommitHash, patch.Filename)
|
|
||||||
good = true
|
|
||||||
} else {
|
|
||||||
// probably screwed up git trees
|
|
||||||
log.Info("patch with unknown origin:", patch.RepoNamespace, name, err, patch.CommitHash, patch.Filename)
|
|
||||||
bad = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if bad {
|
|
||||||
p.State = "BAD"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if good {
|
|
||||||
p.State = "TRY"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if done {
|
|
||||||
p.State = "DONE"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanSubject(line string) string {
|
|
||||||
// Regular expression to remove "Subject:" and "[PATCH...]" patterns
|
|
||||||
re := regexp.MustCompile(`(?i)^Subject:\s*(\[\s*PATCH[^\]]*\]\s*)?`)
|
|
||||||
cleaned := re.ReplaceAllString(line, "")
|
|
||||||
return strings.TrimSpace(cleaned)
|
|
||||||
}
|
|
||||||
|
|
||||||
func findCommitByHash(hash string, subject string) (string, error) {
|
|
||||||
cmd := exec.Command("git", "log", "--pretty=format:%H %s")
|
|
||||||
var out bytes.Buffer
|
|
||||||
cmd.Stdout = &out
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(out.String(), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.Contains(strings.ToLower(line), strings.ToLower(subject)) {
|
|
||||||
return strings.Fields(line)[0], nil // return the commit hash
|
|
||||||
}
|
|
||||||
if strings.Fields(line)[0] == hash {
|
|
||||||
return "", fmt.Errorf("start commit found: %s", hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("no commit found for subject: %s", subject)
|
|
||||||
}
|
|
||||||
|
|
||||||
func findCommitBySubject(subject string) (string, error) {
|
|
||||||
cmd := exec.Command("git", "log", "--pretty=format:%H %s", "--grep="+subject, "-i")
|
|
||||||
var out bytes.Buffer
|
|
||||||
cmd.Stdout = &out
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(out.String(), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.Contains(strings.ToLower(line), strings.ToLower(subject)) {
|
|
||||||
return strings.Fields(line)[0], nil // return the commit hash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("no commit found for subject: %s", subject)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setNewCommitHash(p *forgepb.Patchset) bool {
|
|
||||||
var done bool = true
|
|
||||||
for patch := range p.Patches.IterAll() {
|
|
||||||
// parts := strings.Fields(patch.Comment)
|
|
||||||
|
|
||||||
repo := me.forge.FindByGoPath(patch.RepoNamespace)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("could not find repo", patch.RepoNamespace)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
comment := cleanSubject(patch.Comment)
|
|
||||||
|
|
||||||
if patch.NewHash != "na" {
|
|
||||||
log.Info("patch: newhash:", patch.NewHash, "commithash:", patch.CommitHash, patch.RepoNamespace, comment)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
done = false
|
|
||||||
os.Chdir(repo.GetFullPath())
|
|
||||||
newhash, err := findCommitBySubject(comment)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("patch: not found hash:", patch.CommitHash, patch.RepoNamespace, comment, newhash, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
patch.NewHash = newhash
|
|
||||||
log.Info("patch: found hash:", patch.CommitHash, newhash, patch.RepoNamespace, comment)
|
|
||||||
}
|
|
||||||
|
|
||||||
return done
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddNotDonePatches(notdone *forgepb.Patches, pset *forgepb.Patchset, full bool) {
|
|
||||||
for patch := range pset.Patches.IterAll() {
|
|
||||||
comment := cleanSubject(patch.Comment)
|
|
||||||
|
|
||||||
if found := notdone.FindByCommitHash(patch.CommitHash); found != nil {
|
|
||||||
log.Info("duplicate notdone", patch.RepoNamespace, "patch:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := me.forge.FindByGoPath(patch.RepoNamespace)
|
|
||||||
if repo == nil {
|
|
||||||
log.Info("could not find repo", patch.RepoNamespace)
|
|
||||||
if full {
|
|
||||||
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if patch.NewHash != "na" {
|
|
||||||
log.Info("already applied patch", patch.RepoNamespace, ": newhash:", patch.NewHash, "commithash:", patch.CommitHash, comment)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
os.Chdir(repo.GetFullPath())
|
|
||||||
newhash, err := findCommitByHash(patch.StartHash, comment)
|
|
||||||
if err != nil {
|
|
||||||
// this patch has not been applied yet
|
|
||||||
log.Info("patch: not found hash:", patch.RepoNamespace, patch.CommitHash, comment, err)
|
|
||||||
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
newhash, err = findCommitBySubject(comment)
|
|
||||||
if err == nil {
|
|
||||||
patch.NewHash = newhash
|
|
||||||
log.Info("patch: found hash:", patch.RepoNamespace, "commit patch", patch.CommitHash, "new hash", newhash, "start hash", patch.StartHash, comment)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// this patch has not been applied yet
|
|
||||||
log.Info("patch: not found hash:", patch.RepoNamespace, patch.CommitHash, comment, newhash, err)
|
|
||||||
notdone.AppendByCommitHash(patch) // double check to ensure the commit hash isn't added twice
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// 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 (
|
||||||
|
"go.wit.com/lib/gadgets"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Publish Window
|
||||||
|
func makePublishWindow() *gadgets.GenericWindow {
|
||||||
|
pubWin := gadgets.NewGenericWindow("publish code", "tasks for merging, versioning and publishing code")
|
||||||
|
|
||||||
|
grid := pubWin.Group.RawGrid()
|
||||||
|
|
||||||
|
grid.NewButton("merge all patches to master", func() {
|
||||||
|
/*
|
||||||
|
pubWin.Disable()
|
||||||
|
defer pubWin.Enable()
|
||||||
|
|
||||||
|
if err := doAllCheckoutDevel(); err != nil {
|
||||||
|
log.Info("checkout error:", err)
|
||||||
|
} else {
|
||||||
|
log.Info("checkout was ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeUserToDevel(true)
|
||||||
|
|
||||||
|
if err := doAllCheckoutMaster(); err != nil {
|
||||||
|
log.Info("checkout error:", err)
|
||||||
|
} else {
|
||||||
|
log.Info("checkout was ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeDevelToMaster(true)
|
||||||
|
*/
|
||||||
|
})
|
||||||
|
|
||||||
|
return pubWin
|
||||||
|
}
|
|
@ -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()
|
||||||
|
@ -218,6 +218,7 @@ func makeHackModeWindow(stdwin *stdReposTableWin) {
|
||||||
group2 := stdwin.win.Top.NewGroup("Merge")
|
group2 := stdwin.win.Top.NewGroup("Merge")
|
||||||
grid = group2.RawGrid()
|
grid = group2.RawGrid()
|
||||||
|
|
||||||
|
/*
|
||||||
grid.NewButton("merge to devel", func() {
|
grid.NewButton("merge to devel", func() {
|
||||||
stdwin.win.Disable()
|
stdwin.win.Disable()
|
||||||
defer stdwin.win.Enable()
|
defer stdwin.win.Enable()
|
||||||
|
@ -252,10 +253,11 @@ func makeHackModeWindow(stdwin *stdReposTableWin) {
|
||||||
|
|
||||||
mergeDevelToMaster(true)
|
mergeDevelToMaster(true)
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
grid.NewButton("show dirty repos on win.Bottom", func() {
|
grid.NewButton("show dirty repos on win.Bottom", func() {
|
||||||
log.Info("try to show dirty repos on bottom")
|
log.Info("try to show dirty repos on bottom")
|
||||||
found := findDirty()
|
found := me.forge.FindDirty()
|
||||||
stdwin.doReposTable(found)
|
stdwin.doReposTable(found)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -279,7 +281,7 @@ func develBehindMasterProblem() *gitpb.Repos {
|
||||||
if repo.GetDevelVersion() == repo.GetMasterVersion() {
|
if repo.GetDevelVersion() == repo.GetMasterVersion() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
|
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
@ -292,7 +294,7 @@ func remoteUserBranchProblem() *gitpb.Repos {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
username := repo.GetUserBranchName()
|
username := repo.GetUserBranchName()
|
||||||
if repo.IsBranchRemote(username) {
|
if repo.IsBranchRemote(username) {
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -314,13 +316,13 @@ func develRemoteProblem() *gitpb.Repos {
|
||||||
// log.Info(lhash, rhash, repo.GetGoPath())
|
// log.Info(lhash, rhash, repo.GetGoPath())
|
||||||
if lhash == "" || rhash == "" {
|
if lhash == "" || rhash == "" {
|
||||||
// something is wrong if either of these are blank
|
// something is wrong if either of these are blank
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lhash == rhash {
|
if lhash == rhash {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
|
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
@ -341,13 +343,13 @@ func masterRemoteProblem() *gitpb.Repos {
|
||||||
// log.Info(lhash, rhash, repo.GetGoPath())
|
// log.Info(lhash, rhash, repo.GetGoPath())
|
||||||
if lhash == "" || rhash == "" {
|
if lhash == "" || rhash == "" {
|
||||||
// something is wrong if either of these are blank
|
// something is wrong if either of these are blank
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lhash == rhash {
|
if lhash == rhash {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
|
|
||||||
}
|
}
|
||||||
return found
|
return found
|
||||||
|
|
|
@ -53,7 +53,7 @@ func makeReposWinNew() *gadgets.GenericWindow {
|
||||||
t.Delete()
|
t.Delete()
|
||||||
t = nil
|
t = nil
|
||||||
}
|
}
|
||||||
found := findDirty()
|
found := me.forge.FindDirty()
|
||||||
|
|
||||||
// display the protobuf
|
// display the protobuf
|
||||||
t = addWindowPB(insertWin, found)
|
t = addWindowPB(insertWin, found)
|
||||||
|
@ -93,7 +93,7 @@ func makeReposWinNew() *gadgets.GenericWindow {
|
||||||
if !me.forge.Config.IsFavorite(repo.GetGoPath()) {
|
if !me.forge.Config.IsFavorite(repo.GetGoPath()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the window for the first time
|
// make the window for the first time
|
||||||
|
@ -117,7 +117,7 @@ func makeReposWinNew() *gadgets.GenericWindow {
|
||||||
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
if me.forge.Config.IsReadOnly(repo.GetGoPath()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the window for the first time
|
// make the window for the first time
|
||||||
|
@ -138,7 +138,7 @@ func makeReposWinNew() *gadgets.GenericWindow {
|
||||||
all := me.forge.Repos.SortByFullPath()
|
all := me.forge.Repos.SortByFullPath()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
repo := all.Next()
|
repo := all.Next()
|
||||||
found.AppendByGoPath(repo)
|
found.AppendByFullPath(repo)
|
||||||
|
|
||||||
}
|
}
|
||||||
// display the protobuf
|
// display the protobuf
|
||||||
|
|
|
@ -22,7 +22,7 @@ type repoPatchWindow struct {
|
||||||
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)
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ func (r *repoPatchWindow) addPatchset(grid *gui.Node, pset *forgepb.Patchset) {
|
||||||
all := pset.Patches.SortByFilename()
|
all := pset.Patches.SortByFilename()
|
||||||
for all.Scan() {
|
for all.Scan() {
|
||||||
p := all.Next()
|
p := all.Next()
|
||||||
s := p.RepoNamespace
|
s := p.Namespace
|
||||||
repo := me.forge.FindByGoPath(s)
|
repo := me.forge.FindByGoPath(s)
|
||||||
if repo == nil {
|
if repo == nil {
|
||||||
log.Info("COULD NOT FIND", s)
|
log.Info("COULD NOT FIND", s)
|
||||||
|
|
Loading…
Reference in New Issue