aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-04-05 20:57:01 +0900
committerOphestra <cat@gensokyo.uk>2026-04-05 23:58:08 +0900
commita69273ab2a7040ba906876e6d7888b4edeb74ebc (patch)
tree0379e49590110d6f4505e0de1671506a46da47b7
parent4cd0f57e48c94e7f628446d050027165fdd9e315 (diff)
cmd/dist: replace dist/release.sh
This is much more robust than a shell script. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--.gitignore31
-rwxr-xr-xall.sh6
-rw-r--r--cmd/dist/comp/_hakurei (renamed from dist/comp/_hakurei)0
-rw-r--r--cmd/dist/main.go232
-rw-r--r--dist/hsurc.default1
-rwxr-xr-xdist/install.sh12
-rwxr-xr-xdist/release.sh36
-rw-r--r--flake.nix2
-rw-r--r--package.nix2
9 files changed, 244 insertions, 78 deletions
diff --git a/.gitignore b/.gitignore
index ed10d54f..fe160921 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,27 +1,7 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-*.pkg
-/hakurei
-
-# Test binary, built with `go test -c`
+# produced by tools and text editors
+*.qcow2
*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
*.out
-
-# Dependency directories (remove the comment below to include it)
-# vendor/
-
-# Go workspace file
-go.work
-go.work.sum
-
-# env file
-.env
.idea
.vscode
@@ -30,8 +10,5 @@ go.work.sum
/internal/pkg/testdata/testtool
/internal/rosa/hakurei_current.tar.gz
-# release
-/dist/hakurei-*
-
-# interactive nixos vm
-nixos.qcow2 \ No newline at end of file
+# cmd/dist default destination
+/dist
diff --git a/all.sh b/all.sh
new file mode 100755
index 00000000..17b6b862
--- /dev/null
+++ b/all.sh
@@ -0,0 +1,6 @@
+#!/bin/sh -e
+
+TOOLCHAIN_VERSION="$(go version)"
+cd "$(dirname -- "$0")/"
+echo "# Building cmd/dist using ${TOOLCHAIN_VERSION}."
+go run -v --tags=dist ./cmd/dist
diff --git a/dist/comp/_hakurei b/cmd/dist/comp/_hakurei
index 11424612..11424612 100644
--- a/dist/comp/_hakurei
+++ b/cmd/dist/comp/_hakurei
diff --git a/cmd/dist/main.go b/cmd/dist/main.go
new file mode 100644
index 00000000..d3555e86
--- /dev/null
+++ b/cmd/dist/main.go
@@ -0,0 +1,232 @@
+//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) {
+ 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)
+ }
+
+ mustWriteHeader(dst, fi.Size(), fi.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")
+ mustWriteFile("hsurc.default", []byte("1000 0"), 0400)
+ for _, name := range []string{
+ "hsu",
+ "hakurei",
+ "sharefs",
+ } {
+ mustWriteFromPath(
+ filepath.Join("bin", name),
+ filepath.Join(s, name),
+ )
+ }
+
+ 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)
+ }
+}
diff --git a/dist/hsurc.default b/dist/hsurc.default
deleted file mode 100644
index f770d5ef..00000000
--- a/dist/hsurc.default
+++ /dev/null
@@ -1 +0,0 @@
-1000 0 \ No newline at end of file
diff --git a/dist/install.sh b/dist/install.sh
deleted file mode 100755
index a4352288..00000000
--- a/dist/install.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-cd "$(dirname -- "$0")" || exit 1
-
-install -vDm0755 "bin/hakurei" "${DESTDIR}/usr/bin/hakurei"
-install -vDm0755 "bin/sharefs" "${DESTDIR}/usr/bin/sharefs"
-
-install -vDm4511 "bin/hsu" "${DESTDIR}/usr/bin/hsu"
-if [ ! -f "${DESTDIR}/etc/hsurc" ]; then
- install -vDm0400 "hsurc.default" "${DESTDIR}/etc/hsurc"
-fi
-
-install -vDm0644 "comp/_hakurei" "${DESTDIR}/usr/share/zsh/site-functions/_hakurei" \ No newline at end of file
diff --git a/dist/release.sh b/dist/release.sh
deleted file mode 100755
index 1cfcc721..00000000
--- a/dist/release.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh -e
-cd "$(dirname -- "$0")/.."
-VERSION="${HAKUREI_VERSION:-untagged}"
-prefix="${PREFIX:-/usr}"
-pname="hakurei-${VERSION}-$(go env GOARCH)"
-out="${DESTDIR:-dist}/${pname}"
-
-destroy_workdir() {
- rm -rf "${out}"
-}
-trap destroy_workdir EXIT
-
-echo '# Preparing distribution files.'
-mkdir -p "${out}"
-cp -v "README.md" "dist/hsurc.default" "dist/install.sh" "${out}"
-cp -rv "dist/comp" "${out}"
-echo
-
-echo '# Building hakurei.'
-go generate ./...
-go build -trimpath -v -o "${out}/bin/" -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" ./...
-echo
-
-echo '# Testing hakurei.'
-go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
-echo
-
-echo '# Creating distribution.'
-rm -f "${out}.tar.gz" && tar -C "${out}/.." -vczf "${out}.tar.gz" "${pname}"
-(cd "${out}/.." && sha512sum "${pname}.tar.gz" > "${pname}.tar.gz.sha512")
-echo
diff --git a/flake.nix b/flake.nix
index 48cf3421..3cca5975 100644
--- a/flake.nix
+++ b/flake.nix
@@ -141,7 +141,7 @@
PATH="${pkgs.pkgsStatic.musl.bin}/bin:$PATH" \
DESTDIR="$out" \
HAKUREI_VERSION="v${hakurei.version}" \
- ./dist/release.sh
+ ./all.sh
'';
}
);
diff --git a/package.nix b/package.nix
index 32a2a884..bde2f0c9 100644
--- a/package.nix
+++ b/package.nix
@@ -116,7 +116,7 @@ buildGo126Module rec {
];
in
''
- install -D --target-directory=$out/share/zsh/site-functions dist/comp/*
+ install -D --target-directory=$out/share/zsh/site-functions cmd/dist/comp/*
mkdir "$out/libexec"
mv "$out"/bin/* "$out/libexec/"