Compare commits

...

57 Commits

Author SHA1 Message Date
Jeff Carr 6d670cc64f fix for root file permissions 2025-09-21 23:22:09 -05:00
Jeff Carr 475e72018e fixes for wierd package names 2025-09-11 19:08:15 -05:00
Jeff Carr aedb5a3bef make sure arch is set 2025-09-11 18:53:40 -05:00
Jeff Carr cc75c2dd6c fixes for packages without control files 2025-09-11 18:39:59 -05:00
Jeff Carr 95d1f6fc7c more fixes. almost works again 2025-09-11 17:41:59 -05:00
Jeff Carr d011972b70 change around the gui 2025-09-11 16:42:02 -05:00
Jeff Carr 887811f788 try to refector to work against git.Repo 2025-09-11 16:07:19 -05:00
Jeff Carr fecb3ed9c1 work on update 2025-09-11 15:42:03 -05:00
Jeff Carr 7b84ddd64b add Namespace 2025-09-11 15:33:17 -05:00
Jeff Carr 6acc0b4f8b mv 2025-09-11 15:26:29 -05:00
Jeff Carr ec661807da switch over to using gitpb.Repo directly 2025-09-11 15:23:17 -05:00
Jeff Carr 127f36ca1f refactor to store info 2025-09-11 15:03:44 -05:00
Jeff Carr b05b706d8b raw gitpb Repo() scan 2025-09-11 14:21:09 -05:00
Jeff Carr fd199a4404 common forge.Init() 2025-09-11 04:42:36 -05:00
Jeff Carr 572ef15ab1 new forge init() 2025-09-11 03:27:56 -05:00
Jeff Carr 2677e5c0cd fixes. needs a refactor 2025-09-09 09:25:10 -05:00
Jeff Carr 8edefa6dad fix something 2025-09-09 08:40:49 -05:00
Jeff Carr 18422baceb new GUI codebase 2025-09-09 06:02:35 -05:00
Jeff Carr 1418fcb0d1 new GUI interface 2025-09-09 05:54:51 -05:00
Jeff Carr af5205fb36 add bash support 2025-09-08 16:18:30 -05:00
Jeff Carr 6f8349ce5b new func name 2025-09-04 10:32:54 -05:00
Jeff Carr b405cbc7e0 fixes to new ENV common code 2025-09-03 20:50:12 -05:00
Jeff Carr 1970e40d0b wrong paths 2025-02-22 07:35:37 -06:00
Jeff Carr cf2f07f273 new autogenpb 2025-02-20 09:39:16 -06:00
Jeff Carr 8e315cc238 forge this! 2025-02-14 20:41:57 -06:00
Jeff Carr 31eac3d915 try to fix 'release' builds 2025-02-14 17:11:48 -06:00
Jeff Carr da425cfb0f more standard timestamp 2025-01-19 16:07:31 -06:00
Jeff Carr d51f5b385a attempt to fix when not using forge 2025-01-18 07:29:44 -06:00
Jeff Carr 1e5fac4cd8 minor 2025-01-08 10:10:41 -06:00
Jeff Carr d16f36fe56 stuff 2024-12-18 18:11:57 -06:00
Jeff Carr 5694d40fa3 fixes for new gitpb 2024-12-17 07:02:57 -06:00
Jeff Carr 2141737e7c actually implement --dir 2024-12-16 01:08:56 -06:00
Jeff Carr 4f27202bce attempt clean gui plugin builds 2024-12-14 22:14:52 -06:00
Jeff Carr 9ecbaaac0d TRUNC new file 2024-12-11 13:51:27 -06:00
Jeff Carr 7b9f4389c2 dumb error 2024-12-04 03:14:05 -06:00
Jeff Carr bcd19ae72b terminate build correctly on failure 2024-12-04 02:24:34 -06:00
Jeff Carr afe21d3c62 change to use gitpb 2024-12-01 00:48:07 -06:00
Jeff Carr b1cdb841bc more example ideas 2024-11-24 06:19:40 -06:00
Jeff Carr c8bbe3c298 minor 2024-11-21 02:23:59 -06:00
Jeff Carr 9ce1554c88 add GoPath: to .deb files 2024-11-21 00:14:12 -06:00
Jeff Carr 4bf2379357 better control file value handling 2024-11-19 05:30:56 -06:00
Jeff Carr 1c2246e709 add Conflicts: 2024-11-19 04:37:20 -06:00
Jeff Carr 891a4cada9 more examples
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-18 18:21:56 -06:00
Jeff Carr 79dd86306e lame error. fix this when I get to riscv 2024-11-17 17:46:54 -06:00
Jeff Carr 53ca277ca1 add gocomplete example 2024-11-17 04:16:24 -06:00
Jeff Carr 064b6d0005 update docs and arch dropdown menu 2024-11-16 13:51:51 -06:00
Jeff Carr df17901f47 fix arch 'all' example 2024-11-16 11:00:46 -06:00
Jeff Carr fbf9f4e802 add mirrors.wit.com example. add noarch 2024-11-16 10:30:30 -06:00
Jeff Carr 526605ff87 add an example to build a custom .deb 2024-11-16 09:49:49 -06:00
Jeff Carr d45037dee9 allow the .deb package to be a different name 2024-11-16 04:56:58 -06:00
Jeff Carr 350d5e5860 fix makefile 2024-11-16 00:05:07 -06:00
Jeff Carr ff564380a7 fix ldflags 2024-11-15 10:51:45 -06:00
Jeff Carr 2101ed1ae9 use go-cmd/cmd 2024-11-08 06:41:29 -06:00
Jeff Carr 54b9acef69 switch to using go-cmd/cmd
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-08 04:07:53 -06:00
Jeff Carr 38e55b2609 arches from aptly 2024-11-07 16:53:19 -06:00
Jeff Carr 5535418b64 include all the toolkits
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-11-07 13:48:49 -06:00
Jeff Carr 3961caa179 attempt to make a fake control file 2024-11-07 07:03:13 -06:00
40 changed files with 1211 additions and 720 deletions

View File

@ -1,23 +1,32 @@
.PHONY: debian
run: build
./go-deb --repo go.wit.com/apps/autotypist
VERSION = $(shell git describe --tags)
DATE = $(shell date +%Y.%m.%d)
run: clean goimports vet install
go-deb --gui andlabs gui
junk:
#go-deb --release go.wit.com/apps/go-mod-clean --dir /tmp/
#go-deb go.wit.com/apps/autotypist
#ls -lth /tmp/*deb
vet:
@GO111MODULE=off go vet
@echo this go library package builds okay
no-gui: build
./go-deb --no-gui --repo go.wit.com/apps/autotypist
auto-build: build
./go-deb --repo go.wit.com/apps/autotypist
build:
build: goimports vet
-rm resources/*.so
# embed the andlabs plugin
-cp -a ~/go/src/go.wit.com/toolkits/andlabs.so resources/
GO111MODULE="off" go build -v
touch resources/blank.so
GO111MODULE="off" go build -v \
-ldflags "-X main.VERSION=${VERSION} -X main.DATE=${DATE} -X gui.GUIVERSION=${VERSION}"
install:
GO111MODULE="off" go install -v
install: goimports
GO111MODULE="off" go install -v \
-ldflags "-X main.VERSION=${VERSION} -X main.DATE=${DATE} -X gui.GUIVERSION=${VERSION}"
goimports:
goimports -w *.go
@ -31,49 +40,34 @@ reset:
# clear your terminal
reset
gocui: build
# use the ncurses gui (only kinda works still)
ncurses: build
reset
./go-deb --gui gocui >/tmp/witgui.log.stderr 2>&1
./go-deb --gui gocui
nocui: reset build
./go-deb --gui nocui
clean:
-rm go-deb
rm -f go.*
rm -f go-deb
rm -f resources/*.so
touch resources/blank.so
build-go-gui-toolkits: build
./go-deb --release --no-gui --repo go.wit.com/apps/go-gui-toolkits
./go-deb --release --repo go.wit.com/apps/go-gui-toolkits
build-test-failure: build
./go-deb --release --no-gui --repo go.wit.com/apps/junk
./go-deb --release --repo go.wit.com/apps/junk
build-test-keep-files: build
./go-deb --no-gui --keep-files --repo go.wit.com/apps/go-deb
./go-deb --keep-files --repo go.wit.com/apps/go-deb
build-all:
go-deb --no-gui --repo go.wit.com/apps/autotypist
go-deb --no-gui --repo go.wit.com/apps/control-panel-digitalocean
go-deb --no-gui --repo go.wit.com/apps/control-panel-vpn
go-deb --no-gui --repo go.wit.com/apps/go-gui-toolkits
go-deb --no-gui --repo go.wit.com/apps/guireleaser
go-deb --no-gui --repo go.wit.com/apps/control-panel-cloudflare
go-deb --no-gui --repo go.wit.com/apps/control-panel-dns
go-deb --no-gui --repo go.wit.com/apps/go-deb
go-deb --no-gui --repo go.wit.com/apps/go.wit.com
go-deb --no-gui --repo go.wit.com/apps/helloworld
go-deb --no-gui --repo golang.org/x/tools/cmd/goimports
build-releases:
-go-deb --release --no-gui --repo go.wit.com/apps/autotypist
-go-deb --release --no-gui --repo go.wit.com/apps/control-panel-dns
-go-deb --release --no-gui --repo go.wit.com/apps/control-panel-digitalocean
-go-deb --release --no-gui --repo go.wit.com/apps/control-panel-cloudflare
-go-deb --release --no-gui --repo go.wit.com/apps/control-panel-vpn
-go-deb --release --no-gui --repo go.wit.com/apps/go-gui-toolkits
-go-deb --release --no-gui --repo go.wit.com/apps/guireleaser
-go-deb --release --no-gui --repo go.wit.com/apps/go.wit.com
-go-deb --release --no-gui --repo go.wit.com/apps/helloworld
-go-deb --release --no-gui --repo go.wit.com/apps/go-deb
build-release:
go-deb --release --repo go.wit.com/apps/go-deb
debian: build
./go-deb --no-gui --keep-files --repo go.wit.com/apps/go-deb
./go-deb --keep-files --repo go.wit.com/apps/go-deb
test2:
go-deb go.wit.com/apps/utils/go-gui-toolkits --dir /tmp

View File

@ -1,16 +1,38 @@
# go-deb
# go-deb - package things to make it easier on everyone else
Makes a debian package from a go git repository
Makes a debian package from a go git repository, but also arbitrary things.
Usage (puts .deb in ~/incoming/) :
# Usage
* go-deb --no-gui --repo go.wit.com/apps/go-clone
* go-deb --auto --repo go.wit.com/apps/go-clone # just make the .deb file already
* go-deb ---repo go.wit.com/apps/go-clone # will try to open a gtk gui
* go-deb --repo . # can be used for packaging anything. looks for a 'control' and 'build' file
Notes
# examples/
Make a 'control' file for the debian package. You can also make a custom 'build' script to run to place additional files in the debian package. Compiles go with ldflags for main.VERSION.
See the examples/ directory for custom 'control' and 'build' files for packaging arbitrary projects.
TODO:
# Notes
* Make the sources
* Make it compatible with debuild
Make a 'control' file for the debian package.
You can also make a custom 'build' script to run to place additional files in the debian package.
.deb files are actually a smart and very simple file format based off of tar. This was
a smart design decision in the early days when, if things went wrong, your system
could break when updating things like glibc. This would mean that you couldn't even
figure out what is what. Having a very primitive file format is a bonus. That also
means, it is simple to make them! This can be non-intuitive however. This tool
tries to simpilfy that process.
Basically a .deb file is based off of 'tar' and 'ar' (I can only assume 'ar' is a
precurser to tar, but I don't know for sure and will ask maddog!)
Inside the .deb file are some control files and debian specific files and then
a tarball of all the files to extract.
# Todo
* make .rpm, gentoo, arch, etc file formats also
* make whatever the macos needs
* windows support I guess. golang needs plugin support on windows first.

View File

@ -1,103 +0,0 @@
package main
import (
"os"
"strings"
"time"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
"go.wit.com/log"
)
func RemoveFirstElement(slice []string) (string, []string) {
if len(slice) == 0 {
return "", slice // Return the original slice if it's empty
}
return slice[0], slice[1:] // Return the slice without the first element
}
// homeDir, _ := os.UserHomeDir()
func (c *controlBox) addRepo(path string) {
path = strings.Trim(path, "/") // trim any extranous '/' chars put in the config file by the user
if path == "" {
log.Warn("addRepo() got empty path", path)
return
}
// if repostatus.VerifyLocalGoRepo(path) {
// log.Verbose("path actually exists", path)
// } else {
// log.Warn("repostatus.VerifyLocalGoRepo() failed for for", path)
// return
// }
c.pathL = gadgets.NewOneLiner(c.grid, "path")
c.pathL.SetText(path)
c.grid.NextRow()
c.lastTag = gadgets.NewOneLiner(c.grid, "lastTag")
c.grid.NextRow()
c.dirtyL = gadgets.NewOneLiner(c.grid, "dirty")
c.grid.NextRow()
c.currentL = gadgets.NewOneLiner(c.grid, "current")
c.grid.NextRow()
c.buildDate = gadgets.NewOneLiner(c.grid, "Build Date")
c.grid.NextRow()
stamp := time.Now().UTC().Format("2006/01/02 15:04:05 UTC")
c.buildDate.SetText(stamp)
c.tagDate = gadgets.NewOneLiner(c.grid, "git tag Date")
c.grid.NextRow()
err, repo := repostatus.NewRepoStatusWindow(path)
if err != nil {
log.Info("path did not work", path, err)
return
}
if repo == nil {
log.Info("repo == nil", path, err)
os.Exit(-1)
return
}
c.status = repo
// c.status.SetMainWorkingName("master")
// c.status.SetDevelWorkingName("devel")
// c.status.SetUserWorkingName("jcarr")
c.status.Update()
cbname := c.status.GetCurrentBranchName()
cbversion := c.status.GetCurrentBranchVersion()
debversion := c.status.DebianCurrentVersion()
if c.status.CheckDirty() {
c.dirtyL.SetText("true")
} else {
c.dirtyL.SetText("false")
}
lasttag := c.status.GetLastTagVersion()
if argv.Release {
debversion = c.status.DebianReleaseVersion()
c.dirtyL.SetText("false")
}
c.Version.SetText(debversion)
c.lastTag.SetText(lasttag)
c.currentL.SetText(cbname + " " + cbversion)
tagDate := c.getDateStamp(lasttag)
c.tagDate.SetText(tagDate)
if s, ok := c.status.Changed(); ok {
log.Warn("should scan here", s)
}
return
}

68
argv.go
View File

@ -1,34 +1,62 @@
package main
import (
"fmt"
"os"
)
/*
this parses the command line arguements
this enables command line options from other packages like 'gui' and 'log'
*/
import (
"go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/debugger"
"go.wit.com/log"
)
var argv args
type args struct {
NoGui bool `arg:"--no-gui" help:"don't open the gui, just make the .deb"`
Ldflags []string `arg:"--ldflags" help:"flags to pass to go build"`
Repo string `arg:"--repo" help:"go get path to the repo"`
PkgDir string `arg:"--pkg-dir" help:"set default directory (~/incoming/)"`
Release bool `arg:"--release" help:"build a release from the last git tag"`
KeepFiles bool `arg:"--keep-files" help:"keep the build files/"`
Commit *EmptyCmd `arg:"subcommand:commit" help:"'git commit' but errors out if on wrong branch"`
Show *EmptyCmd `arg:"subcommand:show" help:"show what would be done"`
Gui *EmptyCmd `arg:"subcommand:gui" help:"open the gui"`
Dump *EmptyCmd `arg:"subcommand:dump" help:"dump out the future control file"`
Ldflags []string `arg:"--ldflags" help:"flags to pass to go build"`
OutDir string `arg:"--dir" help:"write .deb file into this directory"`
Release bool `arg:"--release" help:"build a release from the last git tag"`
KeepFiles bool `arg:"--keep-files" help:"keep the build files/"`
Force bool `arg:"--force" default:"false" help:"force overwrite an existing .deb file"`
Verbose bool `arg:"--verbose" help:"show more things"`
}
func init() {
arg.MustParse(&argv)
func (args) Version() string {
return "go-clone " + VERSION + " Built on " + DATE
}
if debugger.ArgDebug() {
log.Info("cmd line --debugger == true")
} else {
log.Info("cmd line --debugger == false")
type EmptyCmd struct {
}
func (a args) Description() string {
return `
Example usage:
guireleaser go.wit.com/apps/go-clone --increment --release --dry-run --reason "blerg"
This will pull down the go sources and
the repositories in the go.sum file using git clone`
}
/*
handles shell autocomplete
*/
func (a args) DoAutoComplete(argv []string) {
switch argv[0] {
case "arch":
fmt.Println("riscv64")
case "build":
fmt.Println("user devel release")
case "--gui":
fmt.Println("nocui andlabs")
default:
if argv[0] == ARGNAME {
// list the subcommands here
fmt.Println("arch build gui show --gui")
}
}
os.Exit(0)
}

244
build.go Normal file
View File

@ -0,0 +1,244 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
func buildPackage(repo *gitpb.Repo) (bool, error) {
// TODO: if dirty, set GO111MODULE
// also, if last tag != version
/*
go install -ldflags " \
-X main.GITCOMMIT=${GITCOMMIT} \
-X main.GOVERSION='${GOVERSION}' \
-X main.BUILDTIME='${BUILDTIME}' \
-X main.VERSION=${VERSION}"
*/
// ldflags := "main.GOTAG=" + repo.LastTag()
filename := repo.Control["Package"] // c.Package.String()
if filename == "" {
return false, errors.New("filename is blank")
}
arch := repo.Control["Architecture"] // c.Architecture.String()
if arch == "" {
arch = "amd64" // todo: detect what you are building on
}
version := repo.Control["Version"]
log.Info("version is:", version)
debname := filename + "_" + version + "_" + arch + ".deb"
var fulldebname string
if argv.OutDir == "" {
fulldebname = debname
} else {
fulldebname = filepath.Join(argv.OutDir, debname)
}
if shell.Exists(fulldebname) {
log.Info("debian package already built: " + fulldebname)
return true, errors.New("debian package already built: " + fulldebname)
}
var fullfilename string
_, fullfilename = filepath.Split(filename)
if fullfilename == "" {
log.Info("fullfilename =", fullfilename)
badExit(log.Errorf("binary name was blank"))
}
if fullfilename == "." {
log.Info("fullfilename =", fullfilename)
badExit(log.Errorf("binary name was ."))
}
if shell.Exists(fullfilename) {
repo.RunVerbose([]string{"rm", "-f", fullfilename})
}
if shell.Exists(fullfilename) {
// something wrong
return false, errors.New("binary existed before build")
}
if argv.Release {
os.Unsetenv("GO111MODULE")
cmd := []string{"go"}
cmd = append(cmd, "install")
if argv.Verbose {
cmd = append(cmd, "-v")
cmd = append(cmd, "-x")
}
/*
cmd = append(cmd, "some path"+"@v"+version)
if err := shell.PathExecVerbose("", cmd); err != nil {
badExit(err)
return false, fmt.Errorf("go build err %v", err)
}
*/
cmd = []string{"go"}
cmd = append(cmd, "build")
if argv.Verbose {
cmd = append(cmd, "-v")
cmd = append(cmd, "-x")
}
cmd = append(cmd, "this should be the path")
if err := shell.PathExecVerbose("", cmd); err != nil {
badExit(err)
return false, fmt.Errorf("go build err %v", err)
}
log.Warn("build worked")
} else {
// set the GO111 build var to true. pass the versions to the compiler manually
os.Setenv("GO111MODULE", "off")
cmd := []string{"go", "build"}
// set standard ldflag options
now := time.Now()
datestamp := now.UTC().Format("2006/01/02_1504_UTC")
log.Info("datestamp =", datestamp)
// add some standard golang flags
ldflags := "-X main.VERSION=" + version + " "
ldflags += "-X main.BUILDTIME=" + datestamp + " "
ldflags += "-X main.GUIVERSION=" + version + "" // todo: git this from the filesystem
cmd = append(cmd, "-ldflags", ldflags)
// add any flags from the command line
// this might not actually work
// todo: test this
for _, flag := range argv.Ldflags {
cmd = append(cmd, "-ldflags", "-X "+flag)
}
err := repo.RunVerbose(cmd)
if err != nil {
return false, fmt.Errorf("go build err %v", err)
}
log.Warn("go build worked")
}
filebase := filepath.Base(repo.Control["pathL"]) // c.pathL.String())
if fullfilename != filebase {
// this exception is for when you want to override a package name
// sometimes that's the best option. This way you can keep your
// name, but the .deb package name can be different so you can
// still apt-get it. For an example, look at the gozookeeper package
fullfilename = filebase
}
if !shell.Exists(fullfilename) {
log.Warn("build failed. filename does not exist", fullfilename)
return false, errors.New("missing " + fullfilename)
}
if shell.Exists("files") {
repo.RunVerbose([]string{"rm", "-rf", "files"})
// log.Info("running sync")
repo.RunVerbose([]string{"sync"})
if shell.Exists("files") {
log.Warn("rm failed for some reason")
return false, errors.New("rm files/")
}
}
repo.RunVerbose([]string{"sync"}) // for some reason the next check fails sometimes?
if shell.Exists("files") {
// probably the 'shell' package id being stupid and not waiting for the process to actually exit
log.Warn("rm failed. files/ still exists. is golang doing these in parallel?")
return false, errors.New("rm files/")
}
if err := os.MkdirAll("files/DEBIAN", os.ModePerm); err != nil {
return false, errors.New("mkdir files/DEBIAN")
}
if err := os.MkdirAll("files/usr/bin", os.ModePerm); err != nil {
log.Warn("mkdir failed")
return false, errors.New("mkdir files/usr/bin")
}
if os.Getenv("GO_DEB_CUSTOM") == "true" {
// skip cp & strip on custom 'control' files
// probably deprecate this
log.Info("REPO GO_DEB_CUSTOM=true means binary is not copied")
} else {
_, fname := filepath.Split(repo.GetFullPath())
cmd := []string{"cp", fname, "files/usr/bin"}
log.Info("REPO FILENAME cp", cmd)
if err := repo.RunVerbose(cmd); err != nil {
log.Warn("cp failed")
return false, err
}
cmd = []string{"strip", "files/usr/bin/" + fname}
if err := repo.RunVerbose(cmd); err != nil {
log.Warn("strip failed")
return false, err
}
}
// put the README in there (if missing, generate it?)
var readme string = ""
if shell.Exists("README.md") {
readme = "README.md"
}
if shell.Exists("README") {
readme = "README"
}
if readme != "" {
path := filepath.Join("files/usr/lib/" + filename)
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return false, errors.New("no files/usr/lib")
}
if err := repo.RunVerbose([]string{"cp", readme, path}); err != nil {
return false, err
}
}
if !writeDebianControlFile(repo) {
return false, errors.New("write control file")
}
if shell.Exists("postinst") {
repo.RunVerbose([]string{"cp", "postinst", "files/DEBIAN/"})
}
// experiment for the toolkit package
// if the git repo has a "./build" script run it before packaging
// this way the user can put custom files in the .deb package
if shell.Exists("build") {
log.Info(repo.FullPath, "FOUND ./build HERE")
repo.RunVerbose([]string{"./build"})
} else {
log.Info(repo.FullPath, "NOT FOUND ./build HERE")
}
cmd := []string{"dpkg-deb", "--root-owner-group", "--build", "files", fulldebname}
result := repo.RunVerbose(cmd)
if shell.Exists(fulldebname) {
} else {
log.Warn("CMD FAILED", cmd, result)
log.Warn("build failed: full name was not created:", fulldebname)
return false, errors.New("dpkg-deb --build failed")
}
repo.RunVerbose([]string{"dpkg-deb", "-I", fulldebname})
repo.RunVerbose([]string{"dpkg-deb", "-c", fulldebname})
// cleanup files
if shell.Exists("files") {
if argv.KeepFiles {
log.Info("keeping the build files/")
} else {
repo.RunVerbose([]string{"rm", "-rf", "files"})
// log.Info("running sync")
repo.RunVerbose([]string{"sync"})
if shell.Exists("files") {
log.Warn("rm -rf files/ failed. Run() returned false")
return false, errors.New("rm files/")
}
}
}
return true, nil
}

View File

@ -1,268 +0,0 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
func (c *controlBox) buildPackage() (bool, error) {
// TODO: if dirty, set GO111MODULE
// also, if last tag != version
/*
go install -ldflags " \
-X main.GITCOMMIT=${GITCOMMIT} \
-X main.GOVERSION='${GOVERSION}' \
-X main.BUILDTIME='${BUILDTIME}' \
-X main.VERSION=${VERSION}"
*/
// ldflags := "main.GOTAG=" + repo.LastTag()
filename := c.Package.String()
if filename == "" {
return false, errors.New("filename is blank")
}
homeDir, err := os.UserHomeDir()
if err != nil {
return false, err
}
arch := c.Architecture.String()
version := c.Version.String()
log.Info("version is:", version)
debname := filename + "_" + version + "_" + arch + ".deb"
fulldebname := filepath.Join(homeDir, "incoming", debname)
if shell.Exists(fulldebname) {
log.Info("debian package already built: " + fulldebname)
return true, errors.New("debian package already built: " + fulldebname)
}
var fullfilename string
if argv.Release {
fullfilename = filepath.Join(homeDir, "go/bin", filename)
} else {
fullfilename = filename
}
shell.Run([]string{"rm", "-f", fullfilename})
if shell.Exists(fullfilename) {
// something wrong
return false, errors.New("binary existed before build")
}
if argv.Release {
os.Unsetenv("GO111MODULE")
path := c.pathL.String() + "@latest"
cmd := []string{"go", "install", "-v", "-x", path}
if shell.Run(cmd) {
log.Warn("go install worked")
} else {
return false, errors.New("go install")
}
} else {
// set the GO111 build var to true. pass the versions to the compiler manually
os.Setenv("GO111MODULE", "off")
cmd := []string{"go", "build", "-v", "-x"}
// add some standard golang flags
vldflag := "-X main.VERSION=" + version
gldflag := "-X main.GUIVERSION=" + version // todo: git this from the filesystem
// timeflag := "-X main.BUILDTIME='${BUILDTIME}'"
cmd = append(cmd, "-ldflags", vldflag)
cmd = append(cmd, "-ldflags", gldflag)
// add any flags from the command line
for _, flag := range argv.Ldflags {
cmd = append(cmd, "-ldflags", "-X "+flag)
}
if shell.Run(cmd) {
log.Warn("go build worked")
} else {
return false, errors.New("go build")
}
}
if !shell.Exists(fullfilename) {
log.Warn("build failed. filename does not exist", fullfilename)
return false, errors.New("missing" + fullfilename)
}
if shell.Exists("files") {
shell.Run([]string{"rm", "-rf", "files"})
if shell.Exists("files") {
log.Warn("rm failed for some reason")
return false, errors.New("rm files/")
}
}
shell.Run([]string{"sync"}) // for some reason the next check fails sometimes?
if shell.Exists("files") {
// probably the 'shell' package id being stupid and not waiting for the process to actually exit
log.Warn("rm failed. files/ still exists. is golang doing these in parallel?")
return false, errors.New("rm files/")
}
if !shell.Mkdir("files/DEBIAN") {
return false, errors.New("mkdir files/DEBIAN")
}
if !shell.Mkdir("files/usr/bin") {
log.Warn("mkdir failed")
return false, errors.New("mkdir files/usr/bin")
}
if !shell.Run([]string{"cp", fullfilename, "files/usr/bin"}) {
log.Warn("cp failed")
return false, errors.New("cp " + fullfilename)
}
if !shell.Run([]string{"strip", "files/usr/bin/" + filename}) {
log.Warn("strip failed")
return false, errors.New("strip " + filename)
}
// put the README in there (if missing, generate it?)
var readme string = ""
if shell.Exists("README.md") {
readme = "README.md"
}
if shell.Exists("README") {
readme = "README"
}
if readme != "" {
path := filepath.Join("files/usr/lib/" + filename)
if !shell.Mkdir(path) {
return false, errors.New("no files/usr/lib")
}
if !shell.Run([]string{"cp", readme, path}) {
return false, errors.New("cp readme")
}
}
if !c.writeDebianControlFile() {
return false, errors.New("write control file")
}
if shell.Exists("postinst") {
shell.Run([]string{"cp", "postinst", "files/DEBIAN/"})
}
if c.status == nil {
log.Warn("c.status == nil")
panic(-1)
}
// experiment for the toolkit package
// if the git repo has a "./build" script run it before packaging
// this way the user can put custom files in the .deb package
if c.status.Exists("build") {
if argv.Release {
os.Unsetenv("GO111MODULE")
} else {
os.Setenv("GO111MODULE", "off")
}
shell.Run([]string{"./build"})
}
shell.Run([]string{"dpkg-deb", "--build", "files", fulldebname})
if shell.Exists(fulldebname) {
} else {
log.Warn("build failed")
return false, errors.New("dpkg-deb --build failed")
}
shell.Run([]string{"dpkg-deb", "-I", fulldebname})
shell.Run([]string{"dpkg-deb", "-c", fulldebname})
// cleanup files
if shell.Exists("files") {
if argv.KeepFiles {
log.Info("keeping the build files/")
} else {
shell.Run([]string{"rm", "-rf", "files"})
if shell.Exists("files") {
log.Warn("rm -rf files/ failed. Run() returned false")
return false, errors.New("rm files/")
}
}
}
return true, nil
}
func (c *controlBox) writeDebianControlFile() bool {
cf, err := os.OpenFile("files/DEBIAN/control", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Info("open control file failed", err)
return false
}
fmt.Fprintln(cf, "Package:", c.Package.String())
fmt.Fprintln(cf, "Source:", c.Source.String())
fmt.Fprintln(cf, "Version:", c.Version.String())
fmt.Fprintln(cf, "Architecture:", c.Architecture.String())
fmt.Fprintln(cf, "Depends:", c.Depends.String())
fmt.Fprintln(cf, "Build-Depends:", c.BuildDepends.String())
stamp := time.Now().UTC().Format("2006/01/02 15:04:05 UTC")
// update to now now despite what the GUI is showing
fmt.Fprintln(cf, "Package-Build-Date:", stamp)
fmt.Fprintln(cf, "Git-Tag-Date:", c.tagDate.String())
fmt.Fprintln(cf, "Maintainer:", c.Maintainer.String())
desc := c.Description.String()
parts := strings.Split(desc, "\n")
fmt.Fprintln(cf, "Description:", strings.Join(parts, "\n "))
return true
}
// try to guess or figure out the config file values
// if there is not a control file
func (c *controlBox) computeControlValues() bool {
if c.Package.String() == "" {
// get the package name from the repo name
path := c.pathL.String()
parts := strings.Split(path, "/")
name := parts[len(parts)-1]
c.Package.SetText(name)
}
if c.Source.String() == "" {
c.Source.SetText(c.Package.String())
}
if c.BuildDepends.String() == "" {
c.BuildDepends.SetText("golang")
}
if c.Recommends.String() == "" {
c.Recommends.SetText("go-gui-toolkits")
}
// TODO: get this from the git log
if c.Maintainer.String() == "" {
c.Maintainer.SetText("Jeff Carr <jcarr@wit.com>")
}
// TODO: get this from gitea (or gitlab or github, etc)
// or from the README.md ?
if c.Description.String() == "" {
path := c.pathL.String()
c.Description.SetText("GO binary of " + path)
}
return true
}
// stamp := time.Now().UTC().Format("2006/01/02 15:04:05 UTC")
func (c *controlBox) getDateStamp(tag string) string {
_, out := c.status.RunCmd([]string{"git", "log", "-1", "--format=%at", tag})
out = strings.TrimSpace(out)
// Convert the string to an integer
gitTagTimestampInt, err := strconv.ParseInt(out, 10, 64)
if err != nil {
fmt.Println("Error converting timestamp:", err)
return "git tag " + tag + " unknown"
}
// Parse the Unix timestamp into a time.Time object
gitTagDate := time.Unix(gitTagTimestampInt, 0)
return gitTagDate.UTC().Format("2006/01/02 15:04:05 UTC")
}

View File

@ -4,9 +4,10 @@ Package: go-deb
Maintainer: Jeff Carr <jcarr@wit.com>
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
Depends: go-gui-toolkits
URL: https://go.wit.com/
Recommends: go-gui-toolkits
Recommends:
Conflicts: testingoldstuff
Description: create distribution packages for golang repositories
Hopefully, this can make compatible and correct source
packages for things like debuild or the incoming queue since

145
control.read.go Normal file
View File

@ -0,0 +1,145 @@
package main
import (
"bufio"
"os"
"path/filepath"
"strings"
"unicode"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
func trimNonNumericPrefix(s string) string {
// Find the index of the first character that IS a digit.
firstDigitIndex := strings.IndexFunc(s, unicode.IsDigit)
// If no digit is found, IndexFunc returns -1.
// In this case, the result should be an empty string.
if firstDigitIndex == -1 {
return ""
}
// Return the substring starting from the first digit.
return s[firstDigitIndex:]
}
// readGitConfig reads and parses the control file
func readControlFile(repo *gitpb.Repo) error {
pairs := make(map[string]string)
var key string
file, err := os.Open("control")
if err != nil {
log.Warn("readControlFile() could not find the file")
// return errors.New("'control': file not found")
// if this happens, make up a fake control file
pairs["Architecture"] = "amd64" // TODO: figure this out
pairs["Recommends"] = ""
pairs["Source"] = "notsure"
if me.repo == nil {
pairs["Description"] = "put something here"
} else {
pairs["Description"] = me.repo.GetGoPath()
}
if repo.Control == nil {
repo.Control = make(map[string]string)
}
for key, value := range pairs {
repo.Control[key] = value
}
if os.Getenv("GIT_AUTHOR_NAME") != "" {
author := log.Sprintf("%s <%s>", os.Getenv("GIT_AUTHOR_NAME"), os.Getenv("GIT_AUTHOR_EMAIL"))
repo.Control["Packager"] = author
}
_, fname := filepath.Split(repo.GetFullPath())
repo.Control["Package"] = fname
repo.Control["Version"] = trimNonNumericPrefix(repo.GetCurrentVersion())
repo.Control["URL"] = repo.URL
return nil
}
defer file.Close()
pairs["Version"] = trimNonNumericPrefix(repo.GetCurrentVersion())
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// Skip empty lines and comments
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
continue
}
// if line starts with a space, it's part of the last key
if strings.HasPrefix(line, " ") {
pairs[key] = pairs[key] + "\n" + strings.TrimSpace(line)
continue
}
partsNew := strings.SplitN(line, ":", 2)
if len(partsNew) < 2 {
log.Warn("error on line:", line)
continue
}
key = strings.TrimSpace(partsNew[0])
value := strings.TrimSpace(partsNew[1])
pairs[key] = value
}
if repo.Control == nil {
repo.Control = make(map[string]string)
}
for key, value := range pairs {
repo.Control[key] = value
/*
switch key {
case "Source":
c.Source.SetText(value)
case "Build-Depends":
c.BuildDepends.SetText(value)
case "Description":
c.Description.SetText(value)
case "Maintainer":
c.Maintainer.SetText(value)
case "Packager":
c.Packager.SetText(value)
case "GoPath":
c.GoPath.SetText(value)
case "URL":
c.URL.SetText(value)
case "Depends":
c.Depends.SetText(value)
case "Recommends":
c.Recommends.SetText(value)
case "Conflicts":
c.Conflicts.SetText(value)
case "Version":
c.Version.SetText(value)
case "Package":
c.Package.SetText(value)
// if c.Package.String() != value {
// log.Warn("not sure what to do with Package", c.Package.String(), value)
// }
case "Architecture":
// todo: add logic to find OS arch
if c.Architecture.String() != value {
log.Warn("attempting to set arch to", value)
c.Architecture.SetText(value)
}
default:
log.Warn("the 'control' file has a value I don't know about")
log.Warn("error unknown key", key, "value:", value)
}
*/
}
pairs["Architecture"] = "amd64" // TODO: figure this out
if err := scanner.Err(); err != nil {
return err
}
return nil
}

106
control.write.go Normal file
View File

@ -0,0 +1,106 @@
package main
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/go-cmd/cmd"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
func writeDebianControlFile(repo *gitpb.Repo) bool {
filename := "files/DEBIAN/control"
cf, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Info("open control file failed", err)
return false
}
fmt.Fprintln(cf, "Package:", repo.Control["Package"]) // c.Package.String())
fmt.Fprintln(cf, "Source:", repo.Control["Source"]) // c.Source.String())
fmt.Fprintln(cf, "Version:", repo.Control["Version"])
if repo.Control["Architecture"] == "" {
repo.Control["Architecture"] = "amd64"
}
fmt.Fprintln(cf, "Architecture:", repo.Control["Architecture"]) // c.Architecture.String())
writeControlVar(cf, repo, "Depends")
writeControlVar(cf, repo, "Build-Depends")
writeControlVar(cf, repo, "Maintainer")
writeControlVar(cf, repo, "Packager")
writeControlVar(cf, repo, "GoPath")
writeControlVar(cf, repo, "URL")
writeControlVar(cf, repo, "Conflicts")
stamp := time.Now().UTC().Format("2006/01/02 15:04:05 UTC")
// update to now now despite what the GUI is showing
fmt.Fprintln(cf, "Package-Build-Date:", stamp)
fmt.Fprintln(cf, "Git-Tag-Date:", "todo: get from repo")
desc, _ := repo.Control["Description"] // c.Description.String()
parts := strings.Split(desc, "\n")
fmt.Fprintln(cf, "Description:", strings.Join(parts, "\n "))
log.Info("file written as:", filename)
return true
}
func writeControlVar(f *os.File, repo *gitpb.Repo, varname string) {
val, _ := repo.Control[varname]
if val == "" {
return
}
fmt.Fprintln(f, varname+":", val)
}
// try to guess or figure out the config file values
// if there is not a control file
func computeControlValues(repo *gitpb.Repo) bool {
if repo.Control["Package"] == "" {
// get the package name from the repo name
path := repo.Control["pathL"] // c.pathL.String()
parts := strings.Split(path, "/")
name := parts[len(parts)-1]
repo.Control["Package"] = name
}
if repo.Control["Source"] == "" {
repo.Control["Source"] = repo.Control["Package"]
}
if repo.Control["Build-Depends"] == "" {
repo.Control["Build-Depends"] = repo.Control["golang"]
}
if repo.Control["Recommends"] == "" {
repo.Control["Recommends"] = repo.Control["go-gui-toolkits"]
}
if repo.Control["Maintainer"] == "" {
repo.Control["Maintainer"] = "todo: get from ENV"
}
if repo.Control["Description"] == "" {
repo.Control["Description"] = "todo: put URL here"
}
return true
}
// stamp := time.Now().UTC().Format("2006/01/02 15:04:05 UTC")
func getDateStamp(tag string) string {
var r cmd.Status
r = me.repo.Run([]string{"git", "log", "-1", "--format=%at", tag})
out := strings.Join(r.Stdout, "\n")
out = strings.TrimSpace(out)
// Convert the string to an integer
gitTagTimestampInt, err := strconv.ParseInt(out, 10, 64)
if err != nil {
fmt.Println("Error converting timestamp:", err)
return "git tag " + tag + " unknown"
}
// Parse the Unix timestamp into a time.Time object
gitTagDate := time.Unix(gitTagTimestampInt, 0)
return gitTagDate.UTC().Format("2006-01-02_15:04:05_UTC") // close to RFC3339
}

View File

@ -1,83 +0,0 @@
package main
import (
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/repostatus"
)
type controlBox struct {
group *gui.Node // the group
grid *gui.Node // the grid
Package *gadgets.OneLiner
Source *gadgets.OneLiner
Version *gadgets.OneLiner
Maintainer *gadgets.OneLiner
Architecture *gadgets.BasicDropdown
InstallPath *gadgets.BasicCombobox
Depends *gadgets.OneLiner
BuildDepends *gadgets.OneLiner
Recommends *gadgets.OneLiner
Description *gadgets.OneLiner
// repostatus things
pathL *gadgets.OneLiner
lastTag *gadgets.OneLiner
dirtyL *gadgets.OneLiner
currentL *gadgets.OneLiner
buildDate *gadgets.OneLiner
tagDate *gadgets.OneLiner
status *repostatus.RepoStatus
}
// This initializes the control box
func newControl(parent *gui.Node) *controlBox {
var c *controlBox
c = new(controlBox)
c.group = parent.NewGroup("choices")
c.grid = c.group.NewGrid("gridiron", 8, 1)
c.Package = gadgets.NewOneLiner(c.grid, "Package")
c.grid.NextRow()
c.Source = gadgets.NewOneLiner(c.grid, "Source")
c.grid.NextRow()
c.Version = gadgets.NewOneLiner(c.grid, "Version")
c.grid.NextRow()
c.Architecture = gadgets.NewBasicDropdown(c.grid, "Architecture")
c.Architecture.AddText("riscv")
c.Architecture.AddText("amd64")
c.Architecture.AddText("arm")
c.Architecture.AddText("noarch")
c.Architecture.AddText("src")
c.Architecture.SetText("amd64")
c.grid.NextRow()
c.InstallPath = gadgets.NewBasicCombobox(c.grid, "Install Path")
c.InstallPath.AddText("/usr/bin")
c.InstallPath.AddText("/usr/local/bin")
c.InstallPath.AddText("/bin")
c.InstallPath.AddText("/opt/<pkg>/bin")
c.InstallPath.SetText("/usr/bin")
c.grid.NextRow()
c.Maintainer = gadgets.NewOneLiner(c.grid, "Maintainer")
c.grid.NextRow()
c.Depends = gadgets.NewOneLiner(c.grid, "Depends")
c.grid.NextRow()
c.BuildDepends = gadgets.NewOneLiner(c.grid, "Build-Depends")
c.grid.NextRow()
c.Recommends = gadgets.NewOneLiner(c.grid, "Recommends")
c.grid.NextRow()
c.Description = gadgets.NewOneLiner(c.grid, "Description")
c.grid.NextRow()
return c
}

132
doGui.go Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
// Use of this source code is governed by the GPL 3.0
package main
import (
"os"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
// An app to submit patches for the 30 GO GUI repos
func doGui() {
log.Warn("init basicWindow state")
win := gadgets.NewGenericWindow("Create .deb files for GO applications", "things")
win.Custom = func() {
log.Info("got to close")
os.Exit(0)
}
var cbox *controlBox
vbox := win.Middle.Box().Horizontal()
group1 := vbox.NewGroup("controls").Horizontal() // Vertical()
group1.NewButton("go build", func() {
shell.Run([]string{"go", "build", "-v", "-x"})
})
group1.NewButton("read control file", func() {
readControlFile(me.repo)
})
group1.NewButton("write control file", func() {
writeDebianControlFile(me.repo)
})
group1.NewButton("dump repo.Control", func() {
// log.Info("CONTROL:", me.repo.Control)
for v := range me.repo.Control {
log.Infof("CONTROL: %s: %s\n", v, me.repo.Control[v])
}
})
group1.NewButton("Make .deb", func() {
win.Disable()
if ok, err := buildPackage(me.repo); ok {
log.Info("build worked")
os.Exit(0)
} else {
log.Warn("build failed with err:", err)
}
win.Enable()
})
grid := win.Middle.RawGrid()
cbox = newControl(grid)
updateControl(cbox)
}
// This initializes the control box
func newControl(grid *gui.Node) *controlBox {
c := new(controlBox)
c.grid = grid
c.Package = gadgets.NewOneLiner(c.grid, "Package")
c.grid.NextRow()
c.Source = gadgets.NewOneLiner(c.grid, "Source")
c.grid.NextRow()
c.Version = gadgets.NewOneLiner(c.grid, "Version")
c.grid.NextRow()
c.Architecture = gadgets.NewBasicDropdown(c.grid, "Architecture")
c.Architecture.AddText("all")
c.Architecture.AddText("riscv64")
c.Architecture.AddText("amd64")
c.Architecture.AddText("arm64")
c.Architecture.AddText("ppc64")
c.Architecture.AddText("i386")
c.Architecture.AddText("sparc64")
c.Architecture.AddText("alpha")
c.Architecture.SetText("riscv64")
c.grid.NextRow()
c.InstallPath = gadgets.NewBasicCombobox(c.grid, "Install Path")
c.InstallPath.AddText("/usr/bin")
c.InstallPath.AddText("/usr/local/bin")
c.InstallPath.AddText("/bin")
c.InstallPath.AddText("/opt/<pkg>/bin")
c.InstallPath.SetText("/usr/bin")
c.grid.NextRow()
c.Maintainer = gadgets.NewOneLiner(c.grid, "Maintainer")
c.grid.NextRow()
c.Packager = gadgets.NewBasicEntry(c.grid, "Packager")
c.grid.NextRow()
c.GoPath = gadgets.NewBasicEntry(c.grid, "GoPath")
c.grid.NextRow()
c.Namespace = gadgets.NewBasicEntry(c.grid, "Namespace")
c.grid.NextRow()
c.URL = gadgets.NewBasicEntry(c.grid, "URL")
c.grid.NextRow()
c.Depends = gadgets.NewOneLiner(c.grid, "Depends")
c.grid.NextRow()
c.BuildDepends = gadgets.NewOneLiner(c.grid, "Build-Depends")
c.grid.NextRow()
c.Recommends = gadgets.NewOneLiner(c.grid, "Recommends")
c.grid.NextRow()
c.Conflicts = gadgets.NewBasicEntry(c.grid, "Conflicts")
c.grid.NextRow()
c.Description = gadgets.NewOneLiner(c.grid, "Description")
c.Description.SetText("na")
c.grid.NextRow()
return c
}

View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
go-deb --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

8
examples/gocomplete/build Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash -x
# cmd github.com/posener/complete/gocomplete
# this is the awesome gocomplete from github.com/posener/complete
mkdir -p files/usr/bin
cp ~/go/src/github.com/posener/complete/gocomplete/gocomplete files/usr/bin/

View File

@ -0,0 +1,12 @@
Source:
Package: gocomplete
Build-Depends:
Maintainer: Jeff Carr <jcarr@wit.com>
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
GoPath: github.com/posener/complete
Recommends: golang
Version: 0.0.2
Description: gocomplete from posener
This was packaged with go-deb from go.wit.com

View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
go-deb --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

5
examples/goimports/build Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash -x
# do nothing. this package is just an 'alias'
# since I never remember where goimport is
# (it's in golang-golang-x-tools)

View File

@ -0,0 +1,13 @@
Source:
Package: goimports
Build-Depends:
Maintainer: Jeff Carr <jcarr@wit.com>
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends: golang-golang-x-tools
GoPath: golang.org/x/tools
Recommends: golang
Version: 0.0.1
Description: apt install's golang.org/x/tools
This doesn't do anything. it's just a shortcut.
This was packaged with go-deb from go.wit.com

View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
go-deb --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

8
examples/gomobile/build Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash -x
# gomobile binary from go
mkdir -p files/usr/bin
cd ~/go/bin/golang.org/x/mobile/cmd/gomobile/
go build
cp ~/go/src/golang.org/x/mobile/cmd/gomobile/gomobile files/usr/bin

11
examples/gomobile/control Normal file
View File

@ -0,0 +1,11 @@
Source:
Package: gomobile
Build-Depends:
Maintainer: golang <?@golang.org>
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
URL: golang.org/x/mobile
Version: 0.0.1
Description: gomobile
This was packaged with go-deb from go.wit.com

View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
go-deb --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

11
examples/mirrors.wit.com/build Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash -x
# these are the keys and files you need
#
# to be able to apt install packages from mirrors.wit.com
mkdir -p files/etc/apt/trusted.gpg.d/
cp wit-sid.asc files/etc/apt/trusted.gpg.d/
mkdir -p files/etc/apt/sources.list.d/
cp wit.list files/etc/apt/sources.list.d/

View File

@ -0,0 +1,12 @@
Source:
Package: mirrors.wit.com
Build-Depends:
Maintainer: Jeff Carr <jcarr@wit.com>
Packager: Jeff Carr <jcarr@wit.com>
Architecture: all
Depends:
URL: https://mirrors.wit.com/
Recommends:
Version: 0.0.7
Description: apt keys and source file
This was packaged with go-deb from go.wit.com

View File

@ -0,0 +1,41 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGJBGclv30BC+C8IqGbd/Nm875TnpTgDEtXUQEc31/NyLPmyJ3fuVlAWAscu6vA
vDiN7/THxilDSDgosKAb9q1lB5jjO9FB179yPOnaSWNsUAxeUXxOSkZmGlicnP/8
Ds+4ncwfiqBcUOMO/UBa3VRYuZJ2DUv4Pg9hapLXrEp58tKZpVloVbf1QYlMJ8XQ
NK72NLhbVGg3acjF1SBYQ5INFSD8pTJbnNFr2s0gvSAFLJHWw/UOFRi/pXSsH0YG
UXnR7TwTYDEcLtJOZ00u+CiSxWcA89a7Ga/1wn/Z9xEMnCMchU+ncAK21Di+QV3S
kDFeZNbQ3iUcTu5t2hYFzRXuIWaNLtbvudVbZc0Q16ahXAt569mTkw0ac8vqt7U3
EZkDf8WIJSgVNWh/4xDgk+0PvDYz3lPvaidY0Zbz69QrSPGkAmTLvFnknCxBFALo
gLfkaQBI+YPhsUI7uUmcA7Mwo31jR2nFx9Afn4xiImWGTxa1fo5z2x4Ed19wS98G
Wxq19efXpwARAQABtBpKZWZmIENhcnIgPGRlYmlhbkB3aXQuY29tPokB0AQTAQoA
PhYhBF18m+R4NtL6SPg8K0qFSur34OFtBQJnJb99AhsDBQkSzAMABQsJCAcCBhUK
CQgLAgQWAgMBAh4BAheAAAoJEEqFSur34OFtkZEL32JP0syL33Z50+pI4Er+NDIN
uosSLXkAcd3Y5HsRZi4VZGTwOKi85ThDkzm46oI3iEY9cEwrDBIw7Rh4fPhOF5iR
TC5BhTJ6De8OEwhzCSyErg53XHo+6+CSo/ozszzkW9jGoiphYPrfvbpHp0C7hPMn
odbO7/dr10mwaeLA2/P0HdEUSRL5nSfukWyyMrkQhyDatGle201IjHYGrDeMheyT
z09ErB4ZnlPocvOnsiuJVoL3HQLl7uodg6wSGxe2o2p0LlMgsCWfteefiBPwLf8F
1xDmHD1VbnyO+TuTBzob8c+0jF10KvLCAKFpy9p13wOKnLYsSfBub57bnpI31bBz
xO4nZXFTTCWP7cYJUHYQ5VxGqGViAn+3KzeESVNJGLcHiIUCXSyCJBjthE2cQz+V
fUqE2jveq297ZmB/hL33y1XtTqVaH5FQfSIv5LT6N+uJNS9XxGQw3aZEkMDJzhiw
RtQH+Zcmkq3Zv/+sC0/ok1dnydaVeLGJiF68uQGJBGclv30BC+C7HekD2YK4/Y8x
nFfJRUHUIDZ829hKnzKHDXqr3ao19PYS+41uCY1Q6wGOu268gWC6V99bGm2qgY/Q
e16sHo2UvWHB/sDvP2/pmj4gX30l1oZdvmTp9GnKffD8MxgwYUVLmnwxnNoKG/GB
pIRdSSakdV1oHX8qTrkhCLQDbD5ggFxxHJB9Q/P6bRGY3mC/RGERLo7wjuD1/bu+
bph+9Mm9cM1Vz7JGU3k9Ic8X2Oe4+jCx3sWKc0OdSnv3SxBfcNeQbVTO66mhk6D8
URUVjcIkTapq1rUIovXP2q7cHjV9ww/XLpruMZzD0ObPR7zF7ss+0jBeKE9tuT6d
4y/kMRNT4lksqdJLgTiH0obvY7JhDmhcKTuoo7wcSoBd0LOH7HKpWw+/6GwCDplr
hN3ULYU+x7lRrdNOpK5wVLwBVL/lbR++KRTcEZVgWuR1Me+rL7sQ5mvXjbmrjImt
B11erxZRw9WOXHRFL/hY/OP/hu3Xq4NS5v5uMX9tLKFb3wARAQABiQG4BBgBCgAm
FiEEXXyb5Hg20vpI+DwrSoVK6vfg4W0FAmclv30CGwwFCRLMAwAACgkQSoVK6vfg
4W0BCgveIkJOxcQhSDNffeB2omoZpesI5wTqDxq2/la/+Q1fKzDzcA3zZT8AMdaJ
YS8kJqKWE+AJrpNE1QCjOYxcyVCdbhqwwrcNNcQ971PPuNQz4nmCo/AictzEoI+v
Yf9ZeMTsi5AKR+vUzrgMql5FrHNyrGfji9bdeuLU7ppJ9EwZHxdnLsYfdX3NJP4B
Wo31QIh+km1Fj1sJVoi4URaRywKfTEk2fwopijYNWgryuwPjSwD2blY6zrH7JVTa
N7EqQ6pLm4opH7+cIPnmR4Bm4FXI3K0a0sPLwkP0avEJmpLRCEKZc16EcN7GWP8S
Its6iW5jTGIMpxSCjCY6Njryq9rsPqlQ+0B6BYJssnNepkYflhry7blY7VQH8yXX
Rp5qDMkDBXhwCYP6YTyHLMAfaizRjVC5kKCNguzyS6hjktnoOtxJdRkfLNjnYXCS
3qKufnc1RPb36s8a4LYBITKBHzxg+0/xmcU9idIK/i8eua3mXoLiQ2xzwPBF2GSw
yGA=
=tw/F
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,4 @@
deb http://mirrors.wit.com/wit/ sid main
# deb-src http://mirrors.wit.com/wit/ sid main
# cp apt-wit.list /etc/apt/sources.list.d/

13
examples/pkgsite/Makefile Normal file
View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
go-deb --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

9
examples/pkgsite/build Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash -x
# pkgsite binary from go
# go-clone golang.org/x/pkgsite
# cd ~/go/src/golang.org/x/pkgsite/cmd/pkgsite
# go build
mkdir -p files/usr/bin
cp ~/go/src/golang.org/x/pkgsite/cmd/pkgsite/pkgsite files/usr/bin/

10
examples/pkgsite/control Normal file
View File

@ -0,0 +1,10 @@
Package: pkgsite
Maintainer: https://golang.org/x/pkgsite
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
Source: go-clone golang.org/x/pkgsite
URL: https://golang.org/x/pkgsite
Version: 0.0.1
Description: pkgsite
This was packaged with go-deb from go.wit.com

View File

@ -0,0 +1,15 @@
.PHONY: build
all: build
build:
go-deb --repo .
# keep the files/ directory after the package is made
keep-files:
go-deb --keep-files --repo .
# use the ncurses gui (only kinda works still)
ncurses:
go-deb --gui gocui --repo .

10
examples/protoc-gen-go/build Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash -x
# this is the new protobuf generator
#
# go-clone google.golang.org/protobuf
# cd ~/go/src/google.golang.org/protobuf/cmd/protoc-gen-go
# go build
mkdir -p files/usr/bin
cp ~/go/src/google.golang.org/protobuf/cmd/protoc-gen-go/protoc-gen-go files/usr/bin/

View File

@ -0,0 +1,12 @@
Source: go-clone google.golang.org/protobuf
Build-Depends: golang
Package: protoc-gen-go-wit
Maintainer: https://google.golang.org/protobuf/
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends: protobuf-compiler
Conflicts: protoc-gen-go, protoc-gen-go-1-3, protoc-gen-go-1-5
Recommends:
Version: 1.35.1-devel
Description: protoc-gen-go from google.golang.org/protobuf
I didn't change anything, it's a straight build from the sources.

13
examples/x-tools/Makefile Normal file
View File

@ -0,0 +1,13 @@
.PHONY: build
# this is how the mirrors.wit.com debian package is created
all: build
build:
cp build control ~/go/src/golang.org/x/tools/
go-deb --auto --repo golang.org/x/tools
# use the ncurses gui (only kinda works still)
ncurses:
# go-deb --gui gocui --repo .

37
examples/x-tools/build Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash -x
# bin /usr/bin
# cmd golang.org/x/tools/cmd/benchcmp
# cmd golang.org/x/tools/cmd/godoc
# cmd golang.org/x/tools/cmd/goimports
#
# bin /usr/lib/golang.org/x/tools/
# cmd golang.org/x/tools/cmd/auth golang-authtest
# cmd golang.org/x/tools/cmd/bisect golang-bisect
# cmd golang.org/x/tools/cmd/bundle golang-bundle
# cmd golang.org/x/tools/cmd/callgraph
# cmd golang.org/x/tools/cmd/compilebench
# cmd golang.org/x/tools/cmd/deadcode
# cmd golang.org/x/tools/cmd/digraph
# cmd golang.org/x/tools/cmd/eg
# cmd golang.org/x/tools/cmd/file2fuzz
# cmd golang.org/x/tools/cmd/fiximports
# cmd golang.org/x/tools/cmd/go-contrib-init
# cmd golang.org/x/tools/cmd/godex
# cmd golang.org/x/tools/cmd/gomvpkg
# cmd golang.org/x/tools/cmd/gonew
# cmd golang.org/x/tools/cmd/gotype
# cmd golang.org/x/tools/cmd/goyacc
# cmd golang.org/x/tools/cmd/html2article
# cmd golang.org/x/tools/cmd/present
# cmd golang.org/x/tools/cmd/present2md
# cmd golang.org/x/tools/cmd/signature-fuzzer
# cmd golang.org/x/tools/cmd/splitdwarf
# cmd golang.org/x/tools/cmd/ssadump
# cmd golang.org/x/tools/cmd/stress
# cmd golang.org/x/tools/cmd/stringer
# cmd golang.org/x/tools/cmd/toolstash
# doc man1 benchcmp.1.gz
# normal bash stuff below still will run

14
examples/x-tools/control Normal file
View File

@ -0,0 +1,14 @@
Source:
Package: golang.org-x-tools
Build-Depends:
Maintainer: https://golang.org/issue/
Packager: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
GoPath: golang.org/x/tools
Recommends: golang
BuildIgnore:
Description: GO lang x/tools
Just an example of how it could be packaged using go-deb
incase that is of any use or not.
This was packaged with go-deb from go.wit.com

20
exit.go Normal file
View File

@ -0,0 +1,20 @@
package main
import (
"os"
"go.wit.com/log"
)
func okExit(thing string) {
if thing != "" {
log.Info(thing, "ok")
}
// log.Info("Finished go-clean on", check.GetGoPath(), "ok")
os.Exit(0)
}
func badExit(err error) {
log.Info("go-deb failed: ", err)
os.Exit(-1)
}

130
main.go
View File

@ -4,88 +4,96 @@ import (
"embed"
"os"
"path/filepath"
"time"
"go.wit.com/gui"
"go.wit.com/lib/debugger"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/shell"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/gitpb"
"go.wit.com/log"
)
// This is the beginning of the binary tree of GUI widgets
var myGui *gui.Node
var cBox *controlBox
// this is a basic window. the user can open and close it
var basicWindow *gadgets.BasicWindow
// sent from -ldflags
var VERSION string
var DATE string
//go:embed resources/*
var resources embed.FS
var ARGNAME string = "go-deb"
var argv args
func main() {
if argv.Repo == "" {
log.Info("You need to tell me what repo you want to work on")
println("")
println("go-deb --repo go.wit.com/apps/helloworld")
os.Exit(0)
}
myGui = gui.New()
if !argv.NoGui {
myGui.InitEmbed(resources)
myGui.Default()
me = new(mainType)
prep.Bash(ARGNAME, argv.DoAutoComplete) // this line should be: prep.Bash(argv)
me.myGui = prep.Gui() // prepares the GUI package for go-args
me.pp = arg.MustParse(&argv)
wd, err := os.Getwd()
if err != nil {
badExit(err)
}
basicWindow = makebasicWindow()
me.repo, err = gitpb.NewRepo(wd)
if err != nil {
badExit(err)
}
// todo: add the go.work file logic here
homeDir, _ := os.UserHomeDir()
filepath := filepath.Join(homeDir, "go/src", argv.Repo)
os.Chdir(filepath)
// build()
if argv.Show != nil {
log.Info("todo: show", me.repo.GetGoPath())
okExit("")
}
log.Info("Namespace:", me.repo.GetNamespace(), "Fullpath:", me.repo.GetFullPath())
// scan the repo
cBox.addRepo(argv.Repo)
// figure out where we are working from
// os.Chdir to that directory
var debpath string
if me.repo == nil {
os.Setenv("GO_DEB_CUSTOM", "true")
debpath, _ = os.Getwd()
} else {
debpath = me.repo.GetFullPath()
}
_, basename := filepath.Split(debpath)
me.goPath = basename
os.Chdir(debpath)
// look for a 'config' file in the repo
if cBox.readControlFile() == nil {
if readControlFile(me.repo) == nil {
log.Warn("scan worked")
} else {
log.Warn("scan failed")
}
cBox.computeControlValues()
// verify the values for the package
computeControlValues(me.repo)
if cBox.status == nil {
log.Info("argv.Repo =", argv.Repo)
log.Info("repo not found. Try:")
log.Info("")
log.Info(" go-clone", argv.Repo)
log.Info("")
if argv.Dump != nil {
for v := range me.repo.Control {
log.Infof("CONTROL: %s: %s\n", v, me.repo.Control[v])
}
okExit("")
}
if argv.Gui != nil {
// only load teh toolkit if you get this far
me.myGui.Start() // loads the GUI toolkit
doGui()
debug()
}
log.Info("go-deb: attempting to build package")
if ok, err := buildPackage(me.repo); ok {
log.Info("build worked")
} else {
log.Warn("build failed:", err)
os.Exit(-1)
}
if argv.NoGui {
shell.TestTerminalColor()
// basicWindow.Show() // broken gui package. convert to protobuf
if ok, err := cBox.buildPackage(); ok {
log.Info("build worked")
} else {
log.Warn("build failed:", err)
os.Exit(-1)
}
os.Exit(0)
}
// run the debugger if triggered from the commandline
if debugger.ArgDebug() {
go func() {
log.Sleep(2)
debugger.DebugWindow()
}()
}
basicWindow.Show()
// go will sit here until the window exits
gui.Watchdog()
os.Exit(0)
}
func debug() {
time.Sleep(2 * time.Second)
for {
log.Info("idle loop() todo: could check for things here")
time.Sleep(90 * time.Second)
}
}

View File

@ -1,82 +0,0 @@
package main
import (
"bufio"
"errors"
"os"
"strings"
"go.wit.com/log"
)
// readGitConfig reads and parses the control file
func (c *controlBox) readControlFile() error {
file, err := os.Open("control")
if err != nil {
log.Warn("readControlFile() could not find the file")
return errors.New("'control': file not found")
}
defer file.Close()
pairs := make(map[string]string)
var key string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// Skip empty lines and comments
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
continue
}
// if line starts with a space, it's part of the last key
if strings.HasPrefix(line, " ") {
pairs[key] = pairs[key] + "\n" + strings.TrimSpace(line)
continue
}
partsNew := strings.SplitN(line, ":", 2)
if len(partsNew) < 2 {
log.Warn("error on line:", line)
continue
}
key = strings.TrimSpace(partsNew[0])
value := strings.TrimSpace(partsNew[1])
pairs[key] = value
}
for key, value := range pairs {
switch key {
case "Source":
// log.Info("FOUND Source!", value) c.Source.SetText(value)
case "Build-Depends":
c.BuildDepends.SetText(value)
case "Description":
c.Description.SetText(value)
case "Maintainer":
c.Maintainer.SetText(value)
case "Depends":
c.Depends.SetText(value)
case "Recommends":
c.Recommends.SetText(value)
case "Package":
c.Package.SetText(value)
// if c.Package.String() != value {
// log.Warn("not sure what to do with Package", c.Package.String(), value)
// }
case "Architecture":
if c.Architecture.String() != value {
log.Warn("not sure what to do with Architecture", c.Architecture.String(), value)
}
default:
log.Warn("error unknown key", key, "value:", value)
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}

View File

@ -1,51 +0,0 @@
package main
import (
"os"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/shell"
"go.wit.com/log"
)
// This initializes the first window, a group and a button
func makebasicWindow() *gadgets.BasicWindow {
log.Warn("init basicWindow state")
basicWindow = gadgets.NewBasicWindow(myGui, "Create .deb files for GO applications")
basicWindow.Make()
basicWindow.Custom = func() {
log.Info("got to close")
os.Exit(0)
}
box1 := basicWindow.Box()
cBox = newControl(box1)
vbox := box1.Box().Horizontal()
group1 := vbox.NewGroup("controls").Horizontal() // Vertical()
group1.NewButton("go build", func() {
shell.Run([]string{"go", "build", "-v", "-x"})
})
group1.NewButton("read control file", func() {
cBox.readControlFile()
})
group1.NewButton("Make .deb", func() {
basicWindow.Disable()
if ok, err := cBox.buildPackage(); ok {
log.Info("build worked")
} else {
log.Warn("build failed", err)
}
basicWindow.Enable()
})
group1.NewButton("open repo", func() {
cBox.status.Update()
cBox.status.Toggle()
})
return basicWindow
}

52
structs.go Normal file
View File

@ -0,0 +1,52 @@
package main
import (
"go.wit.com/dev/alexflint/arg"
"go.wit.com/gui"
"go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/gitpb"
)
var me *mainType
// this app's variables
type mainType struct {
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
goSrc string // path to ~/go/src or go.work file
goPath string // the goPath to use for the package
hasWork bool // true if using go.work file
repo *gitpb.Repo // this is the repo we are in
myGui *prep.GuiPrep // the gui toolkit handle
}
type controlBox struct {
group *gui.Node // the group
grid *gui.Node // the grid
Package *gadgets.OneLiner
Source *gadgets.OneLiner
Version *gadgets.OneLiner
Maintainer *gadgets.OneLiner
Packager *gadgets.BasicEntry
GoPath *gadgets.BasicEntry
Namespace *gadgets.BasicEntry
URL *gadgets.BasicEntry
Architecture *gadgets.BasicDropdown
InstallPath *gadgets.BasicCombobox
Depends *gadgets.OneLiner
BuildDepends *gadgets.OneLiner
Recommends *gadgets.OneLiner
Conflicts *gadgets.BasicEntry
Test gui.Widget
Description *gadgets.OneLiner
// repostatus things
pathL *gadgets.OneLiner
lastTag *gadgets.OneLiner
dirtyL *gadgets.OneLiner
currentL *gadgets.OneLiner
buildDate *gadgets.OneLiner
tagDate *gadgets.BasicEntry
// status *repostatus.RepoStatus
}

16
update.go Normal file
View File

@ -0,0 +1,16 @@
package main
func updateControl(c *controlBox) {
c.Namespace.SetText(me.repo.Namespace)
c.URL.SetText(me.repo.URL)
c.Package.SetText(me.repo.Control["Package"])
c.Source.SetText(me.repo.Control["Source"])
c.Maintainer.SetText(me.repo.Control["Maintainer"])
c.Packager.SetText(me.repo.Control["Packager"])
c.Version.SetText(me.repo.Control["Version"])
c.Description.SetText(me.repo.Control["Description"])
c.Depends.SetText(me.repo.Control["Depends"])
c.Recommends.SetText(me.repo.Control["Recommends"])
c.Architecture.SetText("amd64")
}