aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2025-07-06 16:24:17 +0700
committerShulhan <ms@kilabit.info>2026-04-13 19:24:38 +0700
commitf461d701925c6cb5331a50dc6a7fefc8985160b4 (patch)
tree32fcaa37f6eb37676fe3a9ff9c3e3803104ed05c
parent565c279322e4a26f51718d53ad0e7c18e514279a (diff)
downloadbeku-dev.tar.xz
[wip] all: implement function to install Go toolsdev
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.adoc234
-rw-r--r--CHANGELOG.md194
-rw-r--r--README (renamed from README.md)203
l---------README.adoc1
l---------_doc/README.adoc1
-rw-r--r--_doc/index.adoc21
-rw-r--r--beku.go151
8 files changed, 516 insertions, 290 deletions
diff --git a/.gitignore b/.gitignore
index fd7e024..68026fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
*.html
/beku
/beku.test
-/cover.html
/cover.out
/cpu.prof
/mem.prof
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
new file mode 100644
index 0000000..938f921
--- /dev/null
+++ b/CHANGELOG.adoc
@@ -0,0 +1,234 @@
+= Change log for beku
+:toc:
+:sectanchors:
+:sectlinks:
+
+[#v0_7_1]
+== beku v0.7.1 (2022-01-30)
+
+This is the last release for v0 of beku.
+The next release will pivot the beku program to maintain Go versions.
+
+[#v0_7_1_chores]
+=== Chores
+
+go.mod: update all dependencies::
+This changes affect code that use lib/test.Assert().
+
+all: simplify running linter::
+Instead of enabling all linters, run the default linter provided by
+the latest golangci-lint.
+
+all: replace beku_test in testdata with gitsubmodule::
++
+--
+Previously, the beku_test is bare clone of git repository stored as is.
+This cause an initial clone of the beku repository itself does not
+recognize it as git repository, which make the test fail:
+
+----
+go test -v -coverprofile=cover.out ./... || rm -f cover.out
+fatal: '/home/ms/go/src/git.sr.ht/~shulhan/beku/testdata/beku_test.git' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+2022/01/30 10:56:19 gitInstall: Clone: exit status 128
+FAIL github.com/shuLhan/beku 0.008s
+----
+
+This changes make the testdata/beku_test.git as git submodule, to make
+the test run well.
+--
+
+[#v0_7_0]
+== Beku v0.7.0 (2019-06-28)
+
+[#v0_7_0_enhancements]
+=== Enhancements
+
+Do not auto cleanup unused repositories::
++
+--
+Previously, we remove all unused repositories from $GOPATH, which caused
+some important repositories that we forgot to track get removed during
+freeze operation.
+
+This commit remove the auto cleanup and only print the unused repositories
+to the screen.
+--
+
+Add $GOCACHE and $HOME to environments on GoInstall::
+The latest Go release will require $GOCACHE or $HOME environment variable
+upon running "go install" command.
+
+
+[#v0_6_0]
+== Beku v0.6.0 (2019-03-30)
+
+[#v0_6_0_new_features]
+=== New Features
+
+Make Go command works with Go v1.12 and later::
+This means turning off GO111MODULE when running Go command.
+
+Install package if missing when issuing SyncAll::
+
+[#v0_6_0_enhancements]
+=== Enhancement
+
+Use copy of "golang.org/x/tools/go/vcs"::
++
+--
+The indirect dependencies of package "golang.org/x/tools/go/vcs" is
+overwhelming. Using "go get" on this package alone will pull up all
+dependency of "golang.org/x/tools".
+
+To minimize unneeded download of unneeded packages we copy the package
+vcs to our own repository including their license file.
+--
+
+[#v0_5_2]
+== Beku v0.5.2 (2018-12-14)
+
+[#v0_5_2_enhancements]
+=== Enhancement
+
+No need to reinstall all packages after freezing::
+
+[#v0_5_2_enhancements]
+=== Bug Fix
+
+git: set package remote URL according to value in database::
+
+
+[#v0_5_1]
+== Beku v0.5.1 (2018-11-02)
+
+[#v0_5_1_bug_fix]
+=== Bug Fix
+
+Fix sync all that cause version set to true::
+
+
+[#v0_5_0]
+== Beku v0.5.0 (2018-11-01)
+
+[#v0_5_0_enhancements]
+=== Enhancements
+
+Refactoring test to clone from local directory::
+
+Get and save package remote branch in database::
+Some package does not have "master" branch. This will minimize parsing
+and filter operation to get default branch before checking out revision.
+
+Scan package only if its not exist on local system::
+This will minimize freeze operations, removing unneeded fetching revision
+(tag/commit) and parsing remote URL.
+
+Move all commons functions to shared package::
+"github.com/shuLhan/share/lib/{git,io}"
+
+[#v0_5_0_bug_fixes]
+=== Bug Fixes
+
+cmd/beku: fix parsing multiple subcommand on Sync::
+Sync operation should accept both update and no dependency options in one
+line as in "-Sud".
+
+Scan: Update package version only if current and new package both are tag::
+
+env: fix get package from database that return first match by prefix::
+In case two packages have the same prefix, for example "a" and "a-a",
+the GetPackageFromDB will always return "a" when the parameter importPath
+is "a-a".
+
+Fix sync "--into" command::
+
+[#v0_4_0]
+== Beku v0.4.0 (2018-09-04)
+
+[#v0_4_0_breaking_changes]
+=== Breaking Changes
+
+Remove vendor tools: gdm and govendor::
++
+--
+govendor [1], cannot handle transitive dependencies (error when building
+Consul)
+
+Turn out gdm [2] is not vendor tool, its use GOPATH the same as beku. Using
+`gdm` will result in inconsistent build if two or more package depends on the
+same dependency. For example, package A and B depends on X, package A
+depends on X v0.4.0 and package B depends on X v0.5.0, while our repository
+is depends on X v0.6.0. Running beku with the following order: `beku` on X,
+`gdm` on A, and then `gdm` on B, will result in package X will be set to
+v0.5.0, not v0.6.0.
+--
+
+Do not use "git stash" in pre and post version checking::
+Using "git stash" introduce many problems when rebuilding package after
+update.
+
+[1] https://github.com/kardianos/govendor/issues/348
+[2] https://github.com/sparrc/gdm
+
+[#v0_4_0_enhancements]
+=== Enhancements
+
+Add newline on each freeze commands and on each package when doing reinstall
+all::
+
+Add option "--version", to display current command version::
+
+
+[#v0_3_0]
+== Beku v0.3.0 (2018-06-06)
+
+[#v0_3_0_new_features]
+=== New Features
+
+* Use vendor tools to install dependencies. The following vendor tools is
+ known by beku: gdm, govendor, dep.
+* Add option "-d" or "--nodeps" to disable installing dependencies
+* Add common option "-V, --vendor" to work with vendor directory
+* Able to install missing dependencies
+* Handle custom import URL
+
+[#v0_3_0_bug_fixes]
+=== Bug Fixes
+
+* Fix panic if package not found in database
+* Clean non-empty directory on installation, after confirmed by user
+* Save database on first time sync
+
+
+[#v0_2_0]
+== Beku v0.2.0 (2018-05-31)
+
+[#v0_2_0_new_features]
+=== New Features
+
+* Add operation to exclude package from database
+* Add option "--noconfirm" to by pass confirmation
+
+[#v0_2_0_bug_fixes]
+=== Bug Fixes
+
+* Fetch new package commits before updating version
+* Fix scan on non-exist "$GOPATH/src" directory
+* package: GoInstall: set default PATH if it's empty
+
+
+[#v0_1_0]
+== Beku v0.1.0 (2018-05-27)
+
+In this version, beku can handle the following operations,
+
+* Scanning and saving all dependencies in GOPATH (-S)
+* Installing a package (-S <pkg>)
+* Updating a package (-S <pkg>)
+* Removing a package with or without dependencies (-R[-s] <pkg>)
+* Updating all packages in database (-Su)
+* Freezing all packages (-B)
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 0c83c10..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,194 +0,0 @@
-# Beku v0.7.1 (2022-01-30)
-
-This is the last release for v0 of beku.
-The next release will pivot the beku program to maintain Go versions.
-
-## Chores
-
-* go.mod: update all dependencies
-
- This changes affect code that use lib/test.Assert().
-
-* all: simplify running linter
-
- Instead of enabling all linters, run the default linter provided by
- the latest golangci-lint.
-
-* all: replace beku_test in testdata with gitsubmodule
-
- Previously, the beku_test is bare clone of git repository stored as is.
- This cause an initial clone of the beku repository itself does not
- recognize it as git repository, which make the test fail:
-
- go test -v -coverprofile=cover.out ./... || rm -f cover.out
- fatal: '/home/ms/go/src/git.sr.ht/~shulhan/beku/testdata/beku_test.git' does not appear to be a git repository
- fatal: Could not read from remote repository.
-
- Please make sure you have the correct access rights
- and the repository exists.
- 2022/01/30 10:56:19 gitInstall: Clone: exit status 128
- FAIL github.com/shuLhan/beku 0.008s
-
- This changes make the testdata/beku_test.git as git submodule, to make
- the test run well.
-
-
-# Beku v0.7.0 (2019-06-28)
-
-## Enhancements
-
-- Do not auto cleanup unused repositories.
-
- Previously, we remove all unused repositories from $GOPATH, which caused
- some important repositories that we forgot to track get removed during
- freeze operation.
-
- This commit remove the auto cleanup and only print the unused repositories
- to the screen.
-
-- Add $GOCACHE and $HOME to environments on GoInstall
-
- The latest Go release will require $GOCACHE or $HOME environment variable
- upon running "go install" command.
-
-
-# Beku v0.6.0 (2019-03-30)
-
-## New Features
-
-- Make Go command works with Go v1.12 and later.
- This means turning off GO111MODULE when running Go command.
-
-- Install package if missing when issuing SyncAll
-
-## Enhancement
-
-- Use copy of "golang.org/x/tools/go/vcs".
-
- The indirect dependencies of package "golang.org/x/tools/go/vcs" is
- overwhelming. Using "go get" on this package alone will pull up all
- dependency of "golang.org/x/tools".
-
- To minimize unneeded download of unneeded packages we copy the package
- vcs to our own repository including their license file.
-
-
-# Beku v0.5.2 (2018-12-14)
-
-## Enhancement
-
-- No need to reinstall all packages after freezing
-
-## Bug Fix
-
-- git: set package remote URL according to value in database
-
-
-# Beku v0.5.1 (2018-11-02)
-
-## Bug Fix
-
-- Fix sync all that cause version set to true
-
-
-# Beku v0.5.0 (2018-11-01)
-
-## Enhancements
-
-- Refactoring test to clone from local directory
-
-- Get and save package remote branch in database
- Some package does not have "master" branch. This will minimize parsing
- and filter operation to get default branch before checking out revision.
-
-- Scan package only if its not exist on local system.
- This will minimize freeze operations, removing unneeded fetching revision
- (tag/commit) and parsing remote URL.
-
-- Move all commons functions to shared package
- "github.com/shuLhan/share/lib/{git,io}"
-
-## Bug Fixes
-
-- cmd/beku: fix parsing multiple subcommand on Sync
- Sync operation should accept both update and no dependency options in one
- line as in "-Sud".
-
-- Scan: Update package version only if current and new package both are tag
-
-- env: fix get package from database that return first match by prefix
- In case two packages have the same prefix, for example "a" and "a-a",
- the GetPackageFromDB will always return "a" when the parameter importPath
- is "a-a".
-
-- Fix sync "--into" command
-
-# Beku v0.4.0 (2018-09-04)
-
-## Breaking Changes
-
-- Remove vendor tools: gdm and govendor
-
-govendor [1], cannot handle transitive dependencies (error when building
-Consul)
-
-Turn out gdm [2] is not vendor tool, its use GOPATH the same as beku. Using
-`gdm` will result in inconsistent build if two or more package depends on the
-same dependency. For example, package A and B depends on X, package A
-depends on X v0.4.0 and package B depends on X v0.5.0, while our repository
-is depends on X v0.6.0. Running beku with the following order: `beku` on X,
-`gdm` on A, and then `gdm` on B, will result in package X will be set to
-v0.5.0, not v0.6.0.
-
-- Do not use "git stash" in pre and post version checking. Using "git stash"
- introduce many problems when rebuilding package after update.
-
-[1] https://github.com/kardianos/govendor/issues/348
-[2] https://github.com/sparrc/gdm
-
-## Enhancements
-
-- Add newline on each freeze commands and on each package when doing reinstall
- all.
-- Add option "--version", to display current command version.
-
-# Beku v0.3.0 (2018-06-06)
-
-## New Features
-
-- Use vendor tools to install dependencies. The following vendor tools is
- known by beku: gdm, govendor, dep.
-- Add option "-d" or "--nodeps" to disable installing dependencies
-- Add common option "-V, --vendor" to work with vendor directory
-- Able to install missing dependencies
-- Handle custom import URL
-
-## Bug Fixes
-
-- Fix panic if package not found in database
-- Clean non-empty directory on installation, after confirmed by user
-- Save database on first time sync
-
-# Beku v0.2.0 (2018-05-31)
-
-## New Features
-
-- Add operation to exclude package from database
-- Add option "--noconfirm" to by pass confirmation
-
-## Bug Fixes
-
-- Fetch new package commits before updating version
-- Fix scan on non-exist "$GOPATH/src" directory
-- package: GoInstall: set default PATH if it's empty
-
-# Beku v0.1.0 (2018-05-27)
-
-In this version, beku can handle the following operations,
-
-- Scanning and saving all dependencies in GOPATH (-S)
-- Installing a package (-S <pkg>)
-- Updating a package (-S <pkg>)
-- Removing a package with or without dependencies (-R[-s] <pkg>)
-- Updating all packages in database (-Su)
-- Freezing all packages (-B)
diff --git a/README.md b/README
index c719057..ff934d9 100644
--- a/README.md
+++ b/README
@@ -1,33 +1,55 @@
-# Beku
+= Beku
+:toc:
+:sectanchors:
+:sectlinks:
-Beku is a library and program to manage packages in user's environment (GOPATH
-directory).
+Beku is a library and program to manage Go version and installed module,
+program, or source codes in user's GOPATH environment.
-For beku as library see the following
-[![GoDoc](https://godoc.org/github.com/shuLhan/beku?status.svg)](https://godoc.org/github.com/shuLhan/beku).
-For beku as program see the below documentation or at
-[![GoDoc](https://godoc.org/github.com/shuLhan/beku/cmd/beku?status.svg)](https://godoc.org/github.com/shuLhan/beku/cmd/beku).
+== Issues
-## Beku program
+This section describe list of issues trying to solve by this program.
-Beku is command line program to manage packages in user's environment (GOPATH
-directory). Beku provide syntax like `pacman`.
+Manage installation of Go tools binary.
+Manage installation of Go module, including its source code and installed
+binaries.
+
+
+== Workspace structure
+
+`${GOPATH}`:: This is the root of beku working directory.
+
+`${GOPATH}/beku/cache`:: A directory that store temporary files, for example
+downloaded Go tools binary in compressed format.
+
+`${GOPATH}/beku/share`:: Contains the extracted Go tools binary, using the
+following directory name format `goX.Y.Z`.
+
+`${GOPATH}/beku/go`:: Symlink to one of Go version in the share directory,
+indicated the active Go version.
+The path will be set as the value of ${GOROOT}.
+
+`${GOPATH}/beku/go_bootstrap`:: Symlink to one of Go version in the share
+directory, indicated the active Go version used for bootstrapping (building
+the Go from source).
+The path will be set as the value of ${GOROOT_BOOTSTRAP}.
+
+`${GOPATH}/beku/var/beku.db`:: Beku database file.
Beku read and write the package database into a file named "beku.db".
++
+At first execution, beku will try to open the database file.
+If the file does not exist, beku will scan entire "${GOPATH}/src" and record
+it into the database file.
-At first execution, beku will try to open the package database in current
-directory. If no file found, it will try to open
-"{prefix}/var/beku/beku.db". When both locations does not provide
-package database, beku will scan entire "{prefix}/src" and write the
-package database into "{prefix}/var/beku/beku.db".
-## Global Options
+== Global options
--noconfirm
-No confirmation will be asked on any operation. Useful when running beku
-inside a script.
+No confirmation will be asked on any operation.
+Useful when running beku inside a script.
-d, --nodeps
@@ -35,7 +57,62 @@ Do not install any missing dependencies. This options can be used on freeze
or sync operations.
-## Freeze Operation
+== Install operation
+
+ install <"go"|module>[@version]
+
+Install a Go tools or module.
+
+Given a parameter "go", it will download the Go tools from "https://go.dev/dl"
+using the current operating system and architecture (or values of $GOOS and
+$GOARCH) with version defined in parameter "version".
+If no version is given, it will clone the Go source code and build it.
+
+Given a module import path, beku will try to clone the module source code into
+source directory and checkout the tag defined in the "version".
+If no tag found, it will use the latest commit on master branch.
+
+If package already exist, it will reset the HEAD to the version that is set
+on database file.
+
+=== Options
+
+ [--into <destination>]
+
+This option will install the package import path into custom directory.
+It is useful if you have the fork of the main package but want to install
+it to the legacy directory.
+
+=== Examples
+
+ $ beku install go@1.17.6
+
+Download the Go tools version 1.17.6 into `${GOPATH}/beku/cache/`, and extract
+it into `${GOPATH}/beku/share/go1.17.6`.
+
+ $ beku install golang.org/x/text
+
+Download package `golang.org/x/text` into `${GOPATH}/src/golang.org/x/text`,
+and set their version to the latest commit on branch master.
+
+ $ beku -S github.com/golang/text --into golang.org/x/text
+
+Download package `github.com/golang/text` into
+`${GOPATH}/src/golang.org/x/text`, and set their version to the latest commit
+on branch master.
+
+ $ beku -S golang.org/x/text@v0.3.0
+
+Download package `golang.org/x/text` into `${GOPATH}/src/golang.org/x/text`
+and checkout the tag `v0.3.0` as the working version.
+
+ $ beku -S golang.org/x/text@5c1cf69
+
+Download package `golang.org/x/text` into `${GOPATH}/src/golang.org/x/text`
+and checkout the commit `5c1cf69` as the working version.
+
+
+== Freeze Operation
-B, --freeze
@@ -44,48 +121,50 @@ ensure that all packages listed on database file is installed with their
specific version. Also, all packages that are not registered will
be removed from "src" and "pkg" directories.
-## Database Operation
+== Database Operation
-D, --database
Modify the package database. This operation required one of the options
below.
-### Options
+=== Options
-e, --exclude <pkg ...>
Remove list of package by import path from database and add mark it as
excluded package. Excluded package will be ignored on future operations.
-### Examples
+=== Examples
$ beku -De github.com/shuLhan/beku
Exclude package "github.com/shuLhan/beku" from future scanning,
installation, or removal operations.
-## Query Operation
+
+== Query Operation
-Q, --query [pkg ...]
Query the package database.
-## Remove Operation
+
+== Remove Operation
-R, --remove [pkg]
Remove package from environment, including source and installed binaries and
archives.
-### Options
+=== Options
[-s,--recursive]
Also remove all target dependencies, as long as is not required by other
packages.
-### Examples
+=== Examples
$ beku -R github.com/shuLhan/beku
@@ -100,65 +179,7 @@ Remove package "github.com/shuLhan/beku" source in "{prefix}/src",
their installed binaries in "{prefix}/bin", their installed archives on
"{prefix}/pkg/{GOOS}\_{GOARCH}", and all their dependencies.
-## Sync Operation
-
- -S, --sync <pkg[@version]>
-
-Synchronizes package. Given a package import path, beku will try to clone
-the package into source directory and set the package version to
-latest the tag. If no tag found, it will use the latest commit on master
-branch. A specific version can be set using "@version" suffix.
-
-If package already exist, it will reset the HEAD to the version that is set
-on database file.
-
-If no parameter is given, beku will do a rescan, checking for new packages.
-
-Beku will install the package dependencies manually.
-
-### Options
-
- [--into <destination>]
-
-This option will install the package import path into custom directory.
-It is useful if you have the fork of the main package but want to install
-it to the legacy directory.
-
- [-u,--update]
-
-Fetch new tag or commit from remote repository. User will be asked for
-confirmation before upgrade.
-
-### Examples
-
- $ beku -S golang.org/x/text
-
-Download package `golang.org/x/text` into `{prefix}/src/golang.org/x/text`,
-and set their version to the latest commit on branch master.
-
- $ beku -S github.com/golang/text --into golang.org/x/text
-
-Download package `github.com/golang/text` into
-`{prefix}/src/golang.org/x/text`, and set their version to the latest commit
-on branch master.
-
- $ beku -S golang.org/x/text@v0.3.0
-
-Download package `golang.org/x/text` into `{prefix}/src/golang.org/x/text`
-and checkout the tag `v0.3.0` as the working version.
-
- $ beku -S golang.org/x/text@5c1cf69
-
-Download package `golang.org/x/text` into `{prefix}/src/golang.org/x/text`
-and checkout the commit `5c1cf69` as the working version.
-
- $ beku -Su
-
-Update all packages in database to new tag or commits with approval from
-user.
-
-
-## Development
+== Development
This repository use git submodules to test functionalities that use `git
clone`.
@@ -174,17 +195,9 @@ Then run `make` to make sure all test run well,
$ make
-## Known Limitations
+
+== Known Limitations
- Only work with package hosted with Git on HTTPS or SSH.
- Tested only on Git v2.17 or greater
-
-
-## References
-
-[1] https://www.archlinux.org/pacman/
-
-[2] https://github.com/kardianos/govendor/issues/348
-
-[3] https://github.com/sparrc/gdm
diff --git a/README.adoc b/README.adoc
new file mode 120000
index 0000000..100b938
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1 @@
+README \ No newline at end of file
diff --git a/_doc/README.adoc b/_doc/README.adoc
new file mode 120000
index 0000000..a7ab0b1
--- /dev/null
+++ b/_doc/README.adoc
@@ -0,0 +1 @@
+../README.adoc \ No newline at end of file
diff --git a/_doc/index.adoc b/_doc/index.adoc
new file mode 100644
index 0000000..0b3162e
--- /dev/null
+++ b/_doc/index.adoc
@@ -0,0 +1,21 @@
+= beku
+:toc:
+:sectanchors:
+:sectlinks:
+
+== Documentation
+
+link:CHANGELOG.html[CHANGELOG]:: History of release.
+
+link:README.html[README]:: Manual page for beku.
+
+== Development
+
+https://git.sr.ht/~shulhan/beku[Repository^]::
+Link to the source code.
+
+https://lists.sr.ht/~shulhan/beku[Mailing list^]::
+Place for discussion and sending patches.
+
+https://todo.sr.ht/~shulhan/beku[Issues^]::
+Link to open an issue or request for new feature.
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
+}