diff options
| author | Shulhan <ms@kilabit.info> | 2025-07-06 16:24:17 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-04-13 19:24:38 +0700 |
| commit | f461d701925c6cb5331a50dc6a7fefc8985160b4 (patch) | |
| tree | 32fcaa37f6eb37676fe3a9ff9c3e3803104ed05c /beku.go | |
| parent | 565c279322e4a26f51718d53ad0e7c18e514279a (diff) | |
| download | beku-f461d701925c6cb5331a50dc6a7fefc8985160b4.tar.xz | |
[wip] all: implement function to install Go toolsdev
Diffstat (limited to 'beku.go')
| -rw-r--r-- | beku.go | 151 |
1 files changed, 151 insertions, 0 deletions
@@ -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 +} |
