All checks were successful
Test / Create distribution (push) Successful in 1m15s
Test / Sandbox (push) Successful in 3m1s
Test / Hakurei (push) Successful in 4m5s
Test / ShareFS (push) Successful in 4m14s
Test / Sandbox (race detector) (push) Successful in 5m27s
Test / Hakurei (race detector) (push) Successful in 6m30s
Test / Flake checks (push) Successful in 1m20s
This has no effect, but is nice to have. Signed-off-by: Ophestra <cat@gensokyo.uk>
238 lines
5.0 KiB
Go
238 lines
5.0 KiB
Go
//go:build dist
|
|
|
|
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"compress/gzip"
|
|
"context"
|
|
"crypto/sha512"
|
|
_ "embed"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// getenv looks up an environment variable, and returns fallback if it is unset.
|
|
func getenv(key, fallback string) string {
|
|
if v, ok := os.LookupEnv(key); ok {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
// mustRun runs a command with the current process's environment and panics
|
|
// on error or non-zero exit code.
|
|
func mustRun(ctx context.Context, name string, arg ...string) {
|
|
cmd := exec.CommandContext(ctx, name, arg...)
|
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
//go:embed comp/_hakurei
|
|
var comp []byte
|
|
|
|
func main() {
|
|
fmt.Println()
|
|
log.SetFlags(0)
|
|
log.SetPrefix("# ")
|
|
|
|
version := getenv("HAKUREI_VERSION", "untagged")
|
|
prefix := getenv("PREFIX", "/usr")
|
|
destdir := getenv("DESTDIR", "dist")
|
|
|
|
if err := os.MkdirAll(destdir, 0755); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
s, err := os.MkdirTemp(destdir, ".dist.*")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer func() {
|
|
var code int
|
|
|
|
if err = os.RemoveAll(s); err != nil {
|
|
code = 1
|
|
log.Println(err)
|
|
}
|
|
|
|
if r := recover(); r != nil {
|
|
code = 1
|
|
log.Println(r)
|
|
}
|
|
|
|
os.Exit(code)
|
|
}()
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
|
defer cancel()
|
|
|
|
log.Println("Building hakurei.")
|
|
mustRun(ctx, "go", "generate", "./...")
|
|
mustRun(
|
|
ctx, "go", "build",
|
|
"-trimpath",
|
|
"-v", "-o", s,
|
|
"-ldflags=-s -w "+
|
|
"-buildid= -linkmode external -extldflags=-static "+
|
|
"-X hakurei.app/internal/info.buildVersion="+version+" "+
|
|
"-X hakurei.app/internal/info.hakureiPath="+prefix+"/bin/hakurei "+
|
|
"-X hakurei.app/internal/info.hsuPath="+prefix+"/bin/hsu "+
|
|
"-X main.hakureiPath="+prefix+"/bin/hakurei",
|
|
"./...",
|
|
)
|
|
fmt.Println()
|
|
|
|
log.Println("Testing Hakurei.")
|
|
mustRun(
|
|
ctx, "go", "test",
|
|
"-ldflags=-buildid= -linkmode external -extldflags=-static",
|
|
"./...",
|
|
)
|
|
fmt.Println()
|
|
|
|
log.Println("Creating distribution.")
|
|
const suffix = ".tar.gz"
|
|
distName := "hakurei-" + version + "-" + runtime.GOARCH
|
|
var f *os.File
|
|
if f, err = os.OpenFile(
|
|
filepath.Join(s, distName+suffix),
|
|
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
|
|
0644,
|
|
); err != nil {
|
|
panic(err)
|
|
}
|
|
defer func() {
|
|
if f == nil {
|
|
return
|
|
}
|
|
if err = f.Close(); err != nil {
|
|
log.Println(err)
|
|
}
|
|
}()
|
|
|
|
h := sha512.New()
|
|
gw := gzip.NewWriter(io.MultiWriter(f, h))
|
|
tw := tar.NewWriter(gw)
|
|
|
|
mustWriteHeader := func(name string, size int64, mode os.FileMode) {
|
|
header := tar.Header{
|
|
Name: filepath.Join(distName, name),
|
|
Size: size,
|
|
Mode: int64(mode),
|
|
Uname: "root",
|
|
Gname: "root",
|
|
}
|
|
|
|
if mode&os.ModeDir != 0 {
|
|
header.Typeflag = tar.TypeDir
|
|
fmt.Printf("%s %s\n", mode, name)
|
|
} else {
|
|
header.Typeflag = tar.TypeReg
|
|
fmt.Printf("%s %s (%d bytes)\n", mode, name, size)
|
|
}
|
|
|
|
if err = tw.WriteHeader(&header); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
mustWriteFile := func(name string, data []byte, mode os.FileMode) {
|
|
mustWriteHeader(name, int64(len(data)), mode)
|
|
if mode&os.ModeDir != 0 {
|
|
return
|
|
}
|
|
if _, err = tw.Write(data); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
mustWriteFromPath := func(dst, src string, mode os.FileMode) {
|
|
var r *os.File
|
|
if r, err = os.Open(src); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var fi os.FileInfo
|
|
if fi, err = r.Stat(); err != nil {
|
|
_ = r.Close()
|
|
panic(err)
|
|
}
|
|
|
|
if mode == 0 {
|
|
mode = fi.Mode()
|
|
}
|
|
|
|
mustWriteHeader(dst, fi.Size(), mode)
|
|
if _, err = io.Copy(tw, r); err != nil {
|
|
_ = r.Close()
|
|
panic(err)
|
|
} else if err = r.Close(); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
mustWriteFile(".", nil, fs.ModeDir|0755)
|
|
mustWriteFile("comp/", nil, os.ModeDir|0755)
|
|
mustWriteFile("comp/_hakurei", comp, 0644)
|
|
mustWriteFile("install.sh", []byte(`#!/bin/sh -e
|
|
cd "$(dirname -- "$0")" || exit 1
|
|
|
|
install -vDm0755 "bin/hakurei" "${DESTDIR}`+prefix+`/bin/hakurei"
|
|
install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs"
|
|
|
|
install -vDm4511 "bin/hsu" "${DESTDIR}`+prefix+`/bin/hsu"
|
|
if [ ! -f "${DESTDIR}/etc/hsurc" ]; then
|
|
install -vDm0400 "hsurc.default" "${DESTDIR}/etc/hsurc"
|
|
fi
|
|
|
|
install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei"
|
|
`), 0755)
|
|
|
|
mustWriteFromPath("README.md", "README.md", 0)
|
|
mustWriteFile("hsurc.default", []byte("1000 0"), 0400)
|
|
mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511)
|
|
for _, name := range []string{
|
|
"hakurei",
|
|
"sharefs",
|
|
} {
|
|
mustWriteFromPath(
|
|
filepath.Join("bin", name),
|
|
filepath.Join(s, name),
|
|
0,
|
|
)
|
|
}
|
|
|
|
if err = tw.Close(); err != nil {
|
|
panic(err)
|
|
} else if err = gw.Close(); err != nil {
|
|
panic(err)
|
|
} else if err = f.Close(); err != nil {
|
|
panic(err)
|
|
}
|
|
f = nil
|
|
|
|
if err = os.WriteFile(
|
|
filepath.Join(destdir, distName+suffix+".sha512"),
|
|
append(hex.AppendEncode(nil, h.Sum(nil)), " "+distName+suffix+"\n"...),
|
|
0644,
|
|
); err != nil {
|
|
panic(err)
|
|
}
|
|
if err = os.Rename(
|
|
filepath.Join(s, distName+suffix),
|
|
filepath.Join(destdir, distName+suffix),
|
|
); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|