aboutsummaryrefslogtreecommitdiff
path: root/beku.go
diff options
context:
space:
mode:
Diffstat (limited to 'beku.go')
-rw-r--r--beku.go151
1 files changed, 151 insertions, 0 deletions
diff --git a/beku.go b/beku.go
index 9ca8500..fe1796d 100644
--- a/beku.go
+++ b/beku.go
@@ -6,7 +6,13 @@ package beku
import (
"errors"
+ "fmt"
+ "go/build"
"os"
+ "path/filepath"
+ "strings"
+
+ libhttp "git.sr.ht/~shulhan/pakakeh.go/lib/http"
)
const (
@@ -87,3 +93,148 @@ var (
defStdout = os.Stdout //nolint: gochecknoglobals
defStderr = os.Stderr //nolint: gochecknoglobals
)
+
+type Beku struct {
+ env *Env
+ httpc *libhttp.Client
+}
+
+func NewBeku(env *Env) (beku *Beku) {
+ beku = &Beku{
+ env: env,
+ }
+ return beku
+}
+
+// Install the Go binary or a module.
+func (beku *Beku) Install(module string) (err error) {
+ module = strings.ToLower(module)
+
+ var (
+ nameVersion = strings.Split(module, "@")
+ modName = nameVersion[0]
+ modVersion string
+ )
+
+ if len(nameVersion) > 1 {
+ modVersion = nameVersion[1]
+ }
+
+ if modName == "go" {
+ if len(modVersion) == 0 {
+ return beku.installGoFromSource()
+ }
+ return beku.installGo(modVersion)
+ }
+
+ return nil
+}
+
+// checkInstalledGo check if specific Go tools version already installed.
+// It will return nil if it not exist.
+func (beku *Beku) checkInstalledGo(version string) (err error) {
+ pathGo := filepath.Join(beku.env.prefix, "beku", "share", "go"+version)
+ _, err = os.Stat(pathGo)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return err
+ }
+ return fmt.Errorf("%s already installed", pathGo)
+}
+
+func (beku *Beku) downloadGo(version string) (err error) {
+ var (
+ logp = "downloadGo"
+ compression = "tar.gz"
+ )
+
+ if build.Default.GOOS == "windows" {
+ compression = "zip"
+ }
+
+ goDownload := fmt.Sprintf("go%s.%s-%s.%s", version,
+ build.Default.GOOS, build.Default.GOARCH,
+ compression)
+
+ pathCache := filepath.Join(beku.env.prefix, "beku", "cache", goDownload)
+
+ fi, err := os.Stat(pathCache)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return fmt.Errorf("%s: %w", logp, err)
+ }
+ err = nil
+ }
+ if fi != nil {
+ // The downloaded file already exist on cache directory.
+ return nil
+ }
+
+ fout, err := os.Create(pathCache)
+ if err != nil {
+ return fmt.Errorf("%s: %w", logp, err)
+ }
+
+ beku.initHttpClient()
+
+ downloadReq := libhttp.DownloadRequest{
+ ClientRequest: libhttp.ClientRequest{
+ Path: "/dl/" + goDownload,
+ },
+ Output: fout,
+ }
+
+ _, err = beku.httpc.Download(downloadReq)
+ if err != nil {
+ errClose := fout.Close()
+ if errClose != nil {
+ err = fmt.Errorf("%s: %w: %s", logp, err, errClose)
+ } else {
+ err = fmt.Errorf("%s: %w", logp, err)
+ }
+ return err
+ }
+
+ err = fout.Close()
+ if err != nil {
+ return fmt.Errorf("%s: %w", logp, err)
+ }
+
+ return nil
+}
+
+func (beku *Beku) initHttpClient() {
+ if beku.httpc != nil {
+ return
+ }
+ opts := libhttp.ClientOptions{
+ ServerURL: "https://go.dev",
+ }
+ beku.httpc = libhttp.NewClient(opts)
+}
+
+// installGo install specific Go tools version by downloading the binary from
+// official server and extract it into $GOPATH/beku/share/go{version}.
+func (beku *Beku) installGo(version string) (err error) {
+ var (
+ logp = "installGo " + version
+ )
+
+ err = beku.checkInstalledGo(version)
+ if err != nil {
+ return fmt.Errorf("%s: %w", logp, err)
+ }
+
+ err = beku.downloadGo(version)
+ if err != nil {
+ return fmt.Errorf("%s: %w", logp, err)
+ }
+
+ return nil
+}
+
+func (beku *Beku) installGoFromSource() (err error) {
+ return nil
+}