aboutsummaryrefslogtreecommitdiff
path: root/cmd/yeet/internal
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-04-01 22:33:36 -0400
committerXe Iaso <me@xeiaso.net>2025-04-01 22:33:36 -0400
commitf6166a6a9668ed7424514f43d7922990b7db7352 (patch)
tree0d1ceeea15974b24ea85591d314c0503e6eac31a /cmd/yeet/internal
parent6e622796547d01f59694687decf157a9f09dd51f (diff)
downloadx-1.13.0.tar.xz
x-1.13.0.zip
cmd/yeet: build tarball packagesv1.13.0
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd/yeet/internal')
-rw-r--r--cmd/yeet/internal/mkrpm/mkrpm.go7
-rw-r--r--cmd/yeet/internal/mktarball/mktarball.go157
-rw-r--r--cmd/yeet/internal/pkgmeta/package.go1
3 files changed, 163 insertions, 2 deletions
diff --git a/cmd/yeet/internal/mkrpm/mkrpm.go b/cmd/yeet/internal/mkrpm/mkrpm.go
index 679e2b3..3816e9c 100644
--- a/cmd/yeet/internal/mkrpm/mkrpm.go
+++ b/cmd/yeet/internal/mkrpm/mkrpm.go
@@ -34,6 +34,9 @@ func Build(p pkgmeta.Package) (foutpath string, err error) {
if p.Version == "" {
p.Version = internal.GitVersion()
}
+ if p.Platform == "" {
+ p.Platform = "linux"
+ }
dir, err := os.MkdirTemp("", "yeet-mkrpm")
if err != nil {
@@ -49,7 +52,7 @@ func Build(p pkgmeta.Package) (foutpath string, err error) {
os.Setenv("CGO_ENABLED", cgoEnabled)
}()
os.Setenv("GOARCH", p.Goarch)
- os.Setenv("GOOS", "linux")
+ os.Setenv("GOOS", p.Platform)
os.Setenv("CGO_ENABLED", "0")
p.Build(pkgmeta.BuildInput{
@@ -115,7 +118,7 @@ func Build(p pkgmeta.Package) (foutpath string, err error) {
Name: p.Name,
Version: p.Version,
Arch: p.Goarch,
- Platform: "linux",
+ Platform: p.Platform,
Description: p.Description,
Maintainer: fmt.Sprintf("%s <%s>", *internal.UserName, *internal.UserEmail),
Homepage: p.Homepage,
diff --git a/cmd/yeet/internal/mktarball/mktarball.go b/cmd/yeet/internal/mktarball/mktarball.go
new file mode 100644
index 0000000..5855403
--- /dev/null
+++ b/cmd/yeet/internal/mktarball/mktarball.go
@@ -0,0 +1,157 @@
+package mktarball
+
+import (
+ "archive/tar"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "log/slog"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "within.website/x/cmd/yeet/internal"
+ "within.website/x/cmd/yeet/internal/pkgmeta"
+)
+
+func Build(p pkgmeta.Package) (foutpath string, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch r.(type) {
+ case error:
+ err = r.(error)
+ slog.Error("mkrpm: error while building", "err", err)
+ default:
+ err = fmt.Errorf("%v", r)
+ slog.Error("mkrpm: error while building", "err", err)
+ }
+ }
+ }()
+
+ os.MkdirAll("./var", 0755)
+ os.WriteFile(filepath.Join("./var", ".gitignore"), []byte("*\n!.gitignore"), 0644)
+
+ if p.Version == "" {
+ p.Version = internal.GitVersion()
+ }
+ if p.Platform == "" {
+ p.Platform = "linux"
+ }
+
+ dir, err := os.MkdirTemp("", "yeet-mktarball")
+ if err != nil {
+ return "", fmt.Errorf("can't make temporary directory")
+ }
+ defer os.RemoveAll(dir)
+
+ pkgDir := filepath.Join(dir, fmt.Sprintf("%s-%s-%s-%s", p.Name, p.Version, p.Platform, p.Goarch))
+ os.MkdirAll(pkgDir, 0755)
+
+ fname := filepath.Join("var", fmt.Sprintf("%s-%s-%s-%s.tar.gz", p.Name, p.Version, p.Platform, p.Goarch))
+ fout, err := os.Create(fname)
+ if err != nil {
+ return "", fmt.Errorf("can't make output file: %w", err)
+ }
+ defer fout.Close()
+
+ gw, err := gzip.NewWriterLevel(fout, 9)
+ if err != nil {
+ return "", fmt.Errorf("can't make gzip writer: %w", err)
+ }
+ defer gw.Close()
+
+ tw := tar.NewWriter(gw)
+ defer tw.Close()
+
+ cgoEnabled := os.Getenv("CGO_ENABLED")
+ defer func() {
+ os.Setenv("GOARCH", runtime.GOARCH)
+ os.Setenv("GOOS", runtime.GOOS)
+ os.Setenv("CGO_ENABLED", cgoEnabled)
+ }()
+ os.Setenv("GOARCH", p.Goarch)
+ os.Setenv("GOOS", p.Platform)
+ os.Setenv("CGO_ENABLED", "0")
+
+ os.WriteFile(filepath.Join(pkgDir, "VERSION"), []byte(p.Version+"\n"), 0666)
+
+ bi := pkgmeta.BuildInput{
+ Output: pkgDir,
+ Bin: filepath.Join(pkgDir, "bin"),
+ Doc: filepath.Join(pkgDir, "doc"),
+ Etc: filepath.Join(pkgDir, "run"),
+ Man: filepath.Join(pkgDir, "man"),
+ Systemd: filepath.Join(pkgDir, "run"),
+ }
+
+ p.Build(bi)
+
+ for src, dst := range p.ConfigFiles {
+ if err := Copy(src, filepath.Join(bi.Etc, dst)); err != nil {
+ return "", fmt.Errorf("can't copy %s to %s: %w", src, dst, err)
+ }
+ }
+
+ for src, dst := range p.Documentation {
+ fname := filepath.Join(bi.Doc, dst)
+ if filepath.Base(fname) == "README.md" {
+ fname = filepath.Join(pkgDir, "README.md")
+ }
+
+ if err := Copy(src, fname); err != nil {
+ return "", fmt.Errorf("can't copy %s to %s: %w", src, dst, err)
+ }
+ }
+
+ root, err := os.OpenRoot(dir)
+ if err != nil {
+ return "", fmt.Errorf("can't open root FS %s: %w", dir, err)
+ }
+
+ if err := tw.AddFS(root.FS()); err != nil {
+ return "", fmt.Errorf("can't copy built files to tarball: %w", err)
+ }
+
+ slog.Info("built package", "name", p.Name, "arch", p.Goarch, "version", p.Version, "path", fout.Name())
+
+ return fname, nil
+}
+
+// Copy copies the contents of the file at srcpath to a regular file
+// at dstpath. If the file named by dstpath already exists, it is
+// truncated. The function does not copy the file mode, file
+// permission bits, or file attributes.
+func Copy(srcpath, dstpath string) (err error) {
+ r, err := os.Open(srcpath)
+ if err != nil {
+ return err
+ }
+ defer r.Close() // ignore error: file was opened read-only.
+
+ st, err := r.Stat()
+ if err != nil {
+ return err
+ }
+
+ os.MkdirAll(filepath.Dir(dstpath), 0755)
+
+ w, err := os.Create(dstpath)
+ if err != nil {
+ return err
+ }
+
+ if err := w.Chmod(st.Mode()); err != nil {
+ return err
+ }
+
+ defer func() {
+ // Report the error, if any, from Close, but do so
+ // only if there isn't already an outgoing error.
+ if c := w.Close(); err == nil {
+ err = c
+ }
+ }()
+
+ _, err = io.Copy(w, r)
+ return err
+}
diff --git a/cmd/yeet/internal/pkgmeta/package.go b/cmd/yeet/internal/pkgmeta/package.go
index 1aaa5a7..e7a9bb9 100644
--- a/cmd/yeet/internal/pkgmeta/package.go
+++ b/cmd/yeet/internal/pkgmeta/package.go
@@ -7,6 +7,7 @@ type Package struct {
Homepage string `json:"homepage"`
Group string `json:"group"`
License string `json:"license"`
+ Platform string `json:"platform"` // if not set, default to linux
Goarch string `json:"goarch"`
Replaces []string `json:"replaces"`
Depends []string `json:"depends"`