main
forget_the_bright 2 years ago
parent 96f38075da
commit 4a0f9516a3

19
.gitignore vendored

@ -0,0 +1,19 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
downloads
java
versions
bin
j
# Dependency directories (remove the comment below to include it)
# vendor/

@ -0,0 +1,16 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"args": ["ls-remote" ]
}
]
}

@ -0,0 +1,44 @@
# j
Gradle_Version_Manager
## 安装
[下载](https://github.com/forget-the-bright/j/releases) 下载自己需要的版本, 到自己自定义的目录 修改可执行文件名称为j
默认文件下载安装在用户目录下 ```.grvm```目录,目录下 ```versions```, ```downloads```, ```gradle``` 分别是本地安装目录安装包下载目录当前使用的java版本目录
将 JAVA_HOME 配置为 ```USER_HOME\.grvm\gradle```
指定安装目录需要 添加环境变量 ```GRVM_HOME```
## 命令
### 列出
列出所有可安装版本
```
grvm ls-remote
```
列出本地安装版本
```
grvm ls
```
### 下载
```
grvm install 8
```
### 切换版本
```
grvm use 17
```

@ -0,0 +1,24 @@
package cli
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/urfave/cli/v2"
)
func clean(ctx *cli.Context) (err error) {
entries, err := ioutil.ReadDir(downloadsDir)
if err != nil {
return cli.Exit(errstring(err), 1)
}
for i := range entries {
if err = os.RemoveAll(filepath.Join(downloadsDir, entries[i].Name())); err == nil {
fmt.Println("Remove", entries[i].Name())
}
}
return nil
}

@ -0,0 +1,164 @@
package cli
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"time"
"github.com/Masterminds/semver"
"github.com/fatih/color"
"github.com/forget-the-bright/j/internal/build"
"github.com/urfave/cli/v2"
)
var (
ghomeDir string
downloadsDir string
versionsDir string
goroot string
)
func init() {
/* ghomeDir, _ = os.Getwd()
fmt.Println(ghomeDir)
goroot = filepath.Join(ghomeDir, "java")
fmt.Println(goroot)
downloadsDir = filepath.Join(ghomeDir, "downloads")
os.MkdirAll(downloadsDir, 0755)
versionsDir = filepath.Join(ghomeDir, "versions")
os.MkdirAll(versionsDir, 0755) */
cli.AppHelpTemplate = fmt.Sprintf(`NAME:
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .Commands}} command{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
%s{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{end}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
`, build.ShortVersion)
}
// Run 运行g命令行
func Run() {
app := cli.NewApp()
app.Name = "grvm"
app.Usage = "Gradle Version Manager"
app.Version = build.Version()
app.Copyright = fmt.Sprintf("Copyright (c) 2019-%d, forget-the-bright. All rights reserved.", time.Now().Year())
app.Authors = []*cli.Author{
{Name: "wh", Email: "helloworldwh@163.com"},
}
app.Before = func(ctx *cli.Context) (err error) {
ghomeDir = ghome()
goroot = filepath.Join(ghomeDir, "gradle")
downloadsDir = filepath.Join(ghomeDir, "downloads")
if err = os.MkdirAll(downloadsDir, 0755); err != nil {
return err
}
versionsDir = filepath.Join(ghomeDir, "versions")
return os.MkdirAll(versionsDir, 0755)
}
app.Commands = commands
if err := app.Run(os.Args); err != nil {
os.Exit(1)
}
}
const (
homeEnv = "GRVM_HOME"
mirrorEnv = "GRVM_MIRROR"
)
// ghome 返回g根目录
func ghome() (dir string) {
//fmt.Println(os.Getenv(homeEnv))
/* path, _ := os.Getwd()
return path */
if dir = os.Getenv(homeEnv); dir != "" {
return dir
}
homeDir, _ := os.UserHomeDir()
return filepath.Join(homeDir, ".j")
}
// inuse 返回当前的go版本号
func inuse(goroot string) (version string) {
p, _ := os.Readlink(goroot)
return filepath.Base(p)
}
// render 渲染go版本列表
func render(curV string, items []*semver.Version, out io.Writer) {
sort.Sort(semver.Collection(items))
for i := range items {
fields := strings.SplitN(items[i].String(), "-", 2)
v := strings.TrimSuffix(strings.TrimSuffix(fields[0], ".0"), ".0")
if len(fields) > 1 {
v += fields[1]
}
if v == curV {
color.New(color.FgGreen).Fprintf(out, "* %s\n", v)
} else {
fmt.Fprintf(out, " %s\n", v)
}
}
}
// errstring 返回统一格式的错误信息
func errstring(err error) string {
if err == nil {
return ""
}
return wrapstring(err.Error())
}
func wrapstring(str string) string {
if str == "" {
return str
}
words := strings.Fields(str)
if len(words) > 0 {
words[0] = strings.Title(words[0])
}
return fmt.Sprintf("[grvm] %s", strings.Join(words, " "))
}
func mkSymlink(oldname, newname string) (err error) {
if runtime.GOOS == "windows" {
// Windows 10下无特权用户无法创建符号链接优先调用mklink /j创建'目录联接'
if err = exec.Command("cmd", "/c", "mklink", "/j", newname, oldname).Run(); err == nil {
return nil
}
}
return os.Symlink(oldname, newname)
}

@ -0,0 +1,50 @@
package cli
import "github.com/urfave/cli/v2"
var (
commands = []*cli.Command{
{
Name: "ls",
Usage: "List installed versions",
UsageText: "grvm ls",
Action: list,
},
/* {
Name: "ls-all",
Usage: "List All versions",
UsageText: "j ls-all",
Action: listAll,
}, */
{
Name: "ls-remote",
Usage: "List Remote versions",
UsageText: "grvm ls-remote",
Action: listRemote,
},
{
Name: "install",
Usage: "install versions",
UsageText: "grvm install <version>",
Action: install,
},
{
Name: "use",
Usage: "Switch to specified version",
UsageText: "grvm use <version>",
Action: use,
},
{
Name: "uninstall",
Usage: "Uninstall a version",
UsageText: "grvm uninstall <version>",
Action: uninstall,
},
{
Name: "clean",
Usage: "Remove files from the package download directory",
UsageText: "grvm clean",
Action: clean,
},
}
)

@ -0,0 +1,95 @@
package cli
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/forget-the-bright/j/internal/pkg/archiver"
"github.com/forget-the-bright/j/internal/pkg/check"
"github.com/forget-the-bright/j/internal/pkg/collector"
"github.com/forget-the-bright/j/internal/pkg/config"
"github.com/forget-the-bright/j/internal/pkg/download"
//"github.com/mholt/archiver/v3"
"github.com/urfave/cli/v2"
)
func fundVersion(version string) *config.UrlItem {
config.Url_Items = collector.ConvertCollectorToUrlItem(collector.GetOpenJDKArchiveReleasesInfo(), false)
for _, v := range config.Url_Items {
if v.SimpleName == version { //strings.Contains(v.SimpleName, version)
if version != "8" {
v.In.Sha256 = collector.GetSha256ByUrl(v.In.Sha256, true)
}
return v
}
}
return nil
}
func downloadAndInstall(version string) (err error) {
ui := fundVersion(version)
if ui == nil {
return cli.Exit(errors.New(version+" version is not supported"), 1)
}
filename := filepath.Join(downloadsDir, ui.In.FileName)
//判断本地有没有安装包 没有就进入下载
if _, err := os.Stat(filename); err != nil {
DownloadWithProgress(ui.In.URL, filename)
} else {
if ui.In.Sha256 != check.PrintSha256(filename) {
DownloadWithProgress(ui.In.URL, filename)
}
}
//获取解压目标目录
targetV := filepath.Join(versionsDir, ui.SimpleName)
// 检查版本是否已经安装
if finfo, err := os.Stat(targetV); err == nil && finfo.IsDir() {
return cli.Exit(fmt.Sprintf("[grvm] %q version has been installed.", version), 1)
}
// 解压安装包
if err = archiver.Unarchive(filename, targetV, true); err != nil {
return cli.Exit(errstring(err), 1)
}
/* // 解压安装包
if err = archiver.Unarchive(filename, versionsDir); err != nil {
fmt.Println(err.Error())
return cli.Exit(errstring(err), 1)
}
// 目录重命名
if err = os.Rename(filepath.Join(versionsDir, ui.Expected), targetV); err != nil {
fmt.Println(err.Error())
return cli.Exit(errstring(err), 1)
} */
// 重新建立软链接
_ = os.Remove(goroot)
if err = mkSymlink(targetV, goroot); err != nil {
return cli.Exit(errstring(err), 1)
}
fmt.Printf("Now using %s\n", ui.Expected)
return nil
}
func install(ctx *cli.Context) (err error) {
version := ctx.Args().First()
if version == "" {
return cli.ShowSubcommandHelp(ctx)
}
return downloadAndInstall(version)
}
func Install(version string) (err error) {
return downloadAndInstall(version)
}
// DownloadWithProgress 下载版本另存为指定文件且显示下载进度
func DownloadWithProgress(url, dst string) (size int64, err error) {
return download.Download(url, dst, os.O_CREATE|os.O_WRONLY, 0644, true)
}

@ -0,0 +1,33 @@
package cli
import (
"fmt"
"github.com/fatih/color"
"github.com/forget-the-bright/j/internal/pkg/collector"
"github.com/k0kubun/go-ansi"
"github.com/urfave/cli/v2"
)
func remoteVersionLength(version string) string {
yu := 8 - len(version)
for i := 0; i < yu; i++ {
version += " "
}
return version
}
func listRemote(*cli.Context) (err error) {
use_version := inuse(goroot)
out := ansi.NewAnsiStdout()
rs := collector.ConvertCollectorToUrlItem(collector.GetOpenJDKArchiveReleasesInfo(), false)
color.New(color.FgGreen).Fprintf(out, " %s\n", " version info")
for _, v := range rs {
if v.SimpleName == use_version { //strings.Contains(v.SimpleName, version)
color.New(color.FgGreen).Fprintf(out, "* %s\n", remoteVersionLength(v.SimpleName)+" "+v.Expected)
} else {
fmt.Fprintf(out, " %s\n", remoteVersionLength(v.SimpleName)+" "+v.Expected)
}
}
return nil
}

@ -0,0 +1,47 @@
package cli
import (
"fmt"
"io/ioutil"
"strings"
"github.com/Masterminds/semver"
"github.com/k0kubun/go-ansi"
"github.com/urfave/cli/v2"
)
func list(*cli.Context) (err error) {
infos, err := ioutil.ReadDir(versionsDir)
if err != nil || len(infos) <= 0 {
fmt.Printf("No version installed yet\n\n")
return nil
}
items := make([]*semver.Version, 0, len(infos))
for i := range infos {
if !infos[i].IsDir() {
continue
}
vname := infos[i].Name()
var idx int
if strings.Contains(vname, "alpha") {
idx = strings.Index(vname, "alpha")
} else if strings.Contains(vname, "beta") {
idx = strings.Index(vname, "beta")
} else if strings.Contains(vname, "rc") {
idx = strings.Index(vname, "rc")
}
if idx > 0 {
vname = vname[:idx] + "-" + vname[idx:]
}
v, err := semver.NewVersion(vname)
if err != nil || v == nil {
continue
}
items = append(items, v)
}
render(inuse(goroot), items, ansi.NewAnsiStdout())
return nil
}

@ -0,0 +1,30 @@
package cli
import (
"fmt"
"github.com/fatih/color"
"github.com/forget-the-bright/j/internal/pkg/config"
"github.com/k0kubun/go-ansi"
"github.com/urfave/cli/v2"
)
func mathVersionLength(version string) string {
if len(version) <= 1 {
return version + " "
}
return version
}
func listAll(*cli.Context) (err error) {
use_version := inuse(goroot)
out := ansi.NewAnsiStdout()
color.New(color.FgGreen).Fprintf(out, " %s\n", "version info")
for _, v := range config.ReverseArray(config.Url_Items) {
if v.SimpleName == use_version { //strings.Contains(v.SimpleName, version)
color.New(color.FgGreen).Fprintf(out, "* %s\n", mathVersionLength(v.SimpleName)+" "+v.Expected)
} else {
fmt.Fprintf(out, " %s\n", mathVersionLength(v.SimpleName)+" "+v.Expected)
}
}
return nil
}

@ -0,0 +1,27 @@
package cli
import (
"fmt"
"os"
"path/filepath"
"github.com/urfave/cli/v2"
)
func uninstall(ctx *cli.Context) (err error) {
vname := ctx.Args().First()
if vname == "" {
return cli.ShowSubcommandHelp(ctx)
}
targetV := filepath.Join(versionsDir, vname)
if finfo, err := os.Stat(targetV); err != nil || !finfo.IsDir() {
return cli.Exit(fmt.Sprintf("[j] %q version is not installed", vname), 1)
}
if err = os.RemoveAll(targetV); err != nil {
return cli.Exit(wrapstring(fmt.Sprintf("Uninstall failed: %s", err.Error())), 1)
}
fmt.Printf("Uninstalled java %s\n", vname)
return nil
}

@ -0,0 +1,32 @@
package cli
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"github.com/urfave/cli/v2"
)
func use(ctx *cli.Context) (err error) {
vname := ctx.Args().First()
if vname == "" {
return cli.ShowSubcommandHelp(ctx)
}
targetV := filepath.Join(versionsDir, vname)
if finfo, err := os.Stat(targetV); err != nil || !finfo.IsDir() {
return cli.Exit(fmt.Sprintf("[j] The %q version does not exist, please install it first.", vname), 1)
}
_ = os.Remove(goroot)
if err = mkSymlink(targetV, goroot); err != nil {
return cli.Exit(errstring(err), 1)
}
if output, err := exec.Command(filepath.Join(goroot, "bin", "java"), "--version").Output(); err == nil {
fmt.Print(string(output))
}
return nil
}

@ -0,0 +1,29 @@
module github.com/forget-the-bright/j
go 1.20
require (
github.com/Masterminds/semver v1.5.0
github.com/PuerkitoBio/goquery v1.8.1
github.com/fatih/color v1.15.0
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213
github.com/schollz/progressbar/v3 v3.13.1
github.com/urfave/cli/v2 v2.25.0
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
)
require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.8.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
)

@ -0,0 +1,85 @@
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE=
github.com/schollz/progressbar/v3 v3.13.1/go.mod h1:xvrbki8kfT1fzWzBT/UZd9L6GA+jdL7HAgq2RFnO6fQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -0,0 +1,41 @@
package build
import "strings"
const (
// ShortVersion 短版本号
ShortVersion = "1.0.0"
)
// The value of variables come form `gb build -ldflags '-X "build.Build=xxxxx" -X "build.CommitID=xxxx"' `
var (
// Build build time
Build string
// Branch current git branch
Branch string
// Commit git commit id
Commit string
)
// Version 生成版本信息
func Version() string {
var buf strings.Builder
buf.WriteString(ShortVersion)
if Build != "" {
buf.WriteByte('\n')
buf.WriteString("build: ")
buf.WriteString(Build)
}
if Branch != "" {
buf.WriteByte('\n')
buf.WriteString("branch: ")
buf.WriteString(Branch)
}
if Commit != "" {
buf.WriteByte('\n')
buf.WriteString("commit: ")
buf.WriteString(Commit)
}
return buf.String()
}

@ -0,0 +1,29 @@
package archiver
import (
"errors"
"strings"
)
func Run_unzip(src string, dst string, strip bool) error {
return Unarchive(src, dst, strip)
}
func Unarchive(src string, dst string, strip bool) (err error) {
fileTypes := strings.Split(src, ".")
if len(fileTypes) == 0 {
return errors.New("fileType is not supported")
}
//fmt.Println(fileTypes[len(fileTypes)-1])
switch fileTypes[len(fileTypes)-1] {
case "gz":
err = untgz(src, dst, strip)
case "gx":
err = untgx(src, dst, strip)
case "zip":
err = unzip(src, dst, strip)
default:
err = errors.New(fileTypes[len(fileTypes)-1] + " is not supported")
}
return err
}

@ -0,0 +1,117 @@
package archiver
import (
"archive/tar"
"io"
"os"
"path/filepath"
"strings"
"github.com/xi2/xz"
)
func untgx(src string, dst string, strip bool) error {
xzFile, err := os.Open(src)
if err != nil {
return err
}
defer xzFile.Close()
var prefixToStrip string
if strip {
xzr, err := xz.NewReader(xzFile, 0)
if err != nil {
return err
}
r := tar.NewReader(xzr)
var prefix []string
for {
header, err := r.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
var dir string
if header.Typeflag != tar.TypeDir {
dir = filepath.Dir(header.Name)
} else {
continue
}
if prefix != nil {
dirSplit := strings.Split(dir, string(filepath.Separator))
i, e, dse := 0, len(prefix), len(dirSplit)
if dse < e {
e = dse
}
for i < e {
if prefix[i] != dirSplit[i] {
prefix = prefix[0:i]
break
}
i++
}
} else {
prefix = strings.Split(dir, string(filepath.Separator))
}
}
prefixToStrip = strings.Join(prefix, string(filepath.Separator))
}
xzFile.Seek(0, 0)
xzr, err := xz.NewReader(xzFile, 0)
if err != nil {
return err
}
r := tar.NewReader(xzr)
dirCache := make(map[string]bool) // todo: radix tree would perform better here
if err := os.MkdirAll(dst, 0755); err != nil {
return err
}
for {
header, err := r.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
var dir string
if header.Typeflag != tar.TypeDir {
dir = filepath.Dir(header.Name)
} else {
dir = filepath.Clean(header.Name)
if !strings.HasPrefix(dir, prefixToStrip) {
continue
}
}
dir = strings.TrimPrefix(dir, prefixToStrip)
if dir != "" && dir != "." {
cached := dirCache[dir]
if !cached {
if err := os.MkdirAll(filepath.Join(dst, dir), 0755); err != nil {
return err
}
dirCache[dir] = true
}
}
target := filepath.Join(dst, dir, filepath.Base(header.Name))
switch header.Typeflag {
case tar.TypeReg:
d, err := os.OpenFile(target,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode|0600)&0777)
if err != nil {
return err
}
_, err = io.Copy(d, r)
d.Close()
if err != nil {
return err
}
case tar.TypeSymlink:
if err = os.Symlink(header.Linkname, target); err != nil {
return err
}
}
}
return nil
}

@ -0,0 +1,118 @@
package archiver
import (
"archive/tar"
"compress/gzip"
"io"
"os"
"path/filepath"
"strings"
)
func untgz(src string, dst string, strip bool) error {
gzFile, err := os.Open(src)
if err != nil {
return err
}
defer gzFile.Close()
var prefixToStrip string
if strip {
gzr, err := gzip.NewReader(gzFile)
if err != nil {
return err
}
defer gzr.Close()
r := tar.NewReader(gzr)
var prefix []string
for {
header, err := r.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
var dir string
if header.Typeflag != tar.TypeDir {
dir = filepath.Dir(header.Name)
} else {
continue
}
if prefix != nil {
dirSplit := strings.Split(dir, string(filepath.Separator))
i, e, dse := 0, len(prefix), len(dirSplit)
if dse < e {
e = dse
}
for i < e {
if prefix[i] != dirSplit[i] {
prefix = prefix[0:i]
break
}
i++
}
} else {
prefix = strings.Split(dir, string(filepath.Separator))
}
}
prefixToStrip = strings.Join(prefix, string(filepath.Separator))
}
gzFile.Seek(0, 0)
gzr, err := gzip.NewReader(gzFile)
if err != nil {
return err
}
defer gzr.Close()
r := tar.NewReader(gzr)
dirCache := make(map[string]bool) // todo: radix tree would perform better here
if err := os.MkdirAll(dst, 0755); err != nil {
return err
}
for {
header, err := r.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
var dir string
if header.Typeflag != tar.TypeDir {
dir = filepath.Dir(header.Name)
} else {
dir = filepath.Clean(header.Name)
if !strings.HasPrefix(dir, prefixToStrip) {
continue
}
}
dir = strings.TrimPrefix(dir, prefixToStrip)
if dir != "" && dir != "." {
cached := dirCache[dir]
if !cached {
if err := os.MkdirAll(filepath.Join(dst, dir), 0755); err != nil {
return err
}
dirCache[dir] = true
}
}
target := filepath.Join(dst, dir, filepath.Base(header.Name))
switch header.Typeflag {
case tar.TypeReg:
d, err := os.OpenFile(target,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(header.Mode|0600)&0777)
if err != nil {
return err
}
_, err = io.Copy(d, r)
d.Close()
if err != nil {
return err
}
case tar.TypeSymlink:
if err = os.Symlink(header.Linkname, target); err != nil {
return err
}
}
}
return nil
}

@ -0,0 +1,89 @@
package archiver
import (
"archive/zip"
"io"
"os"
"path/filepath"
"strings"
)
func unzip(src string, dst string, strip bool) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer r.Close()
var prefixToStrip string
if strip {
var prefix []string
for _, f := range r.File {
var dir string
if !f.Mode().IsDir() {
dir = filepath.Dir(f.Name)
} else {
continue
}
if prefix != nil {
dirSplit := strings.Split(dir, string(filepath.Separator))
i, e, dse := 0, len(prefix), len(dirSplit)
if dse < e {
e = dse
}
for i < e {
if prefix[i] != dirSplit[i] {
prefix = prefix[0:i]
break
}
i++
}
} else {
prefix = strings.Split(dir, string(filepath.Separator))
}
}
prefixToStrip = strings.Join(prefix, string(filepath.Separator))
}
dirCache := make(map[string]bool) // todo: radix tree would perform better here
if err := os.MkdirAll(dst, 0755); err != nil {
return err
}
for _, f := range r.File {
var dir string
if !f.Mode().IsDir() {
dir = filepath.Dir(f.Name)
} else {
dir = filepath.Clean(f.Name)
if !strings.HasPrefix(dir, prefixToStrip) {
continue
}
}
dir = strings.TrimPrefix(dir, prefixToStrip)
if dir != "" && dir != "." {
cached := dirCache[dir]
if !cached {
if err := os.MkdirAll(filepath.Join(dst, dir), 0755); err != nil {
return err
}
dirCache[dir] = true
}
}
if !f.Mode().IsDir() {
name := filepath.Base(f.Name)
fr, err := f.Open()
if err != nil {
return err
}
d, err := os.OpenFile(filepath.Join(dst, dir, name),
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, (f.Mode()|0600)&0777)
if err != nil {
return err
}
_, err = io.Copy(d, fr)
d.Close()
if err != nil {
return err
}
}
}
return nil
}

@ -0,0 +1,24 @@
package check
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io/ioutil"
)
func PrintSha256(path string) string {
strContent := readFileToStr(path)
sum := sha256.Sum256([]byte(strContent))
//fmt.Printf("sha256: %x\n", sum)
return hex.EncodeToString(sum[:])
}
func readFileToStr(path string) string {
content, err := ioutil.ReadFile(path)
if err != nil {
fmt.Println("read file failed, err:", err)
return ""
}
return string(content)
}

@ -0,0 +1,72 @@
package collector
import (
"io/ioutil"
"net/http"
"strings"
)
type Collector struct {
Version string
Windows_X64 *Op_Item
Linux_X64 *Op_Item
Linux_AArch64 *Op_Item
Mac_X64 *Op_Item
Mac_AArch64 *Op_Item
}
type Op_Item struct {
FileType string
Arch string
Url string
Sha256Url string
FileName string
}
var Archive_Releases_Collectors []*Collector
var Collectors []*Collector
var Collector_Archive_Url string = Collector_Url + "/archive/"
var Collector_Url string = "https://jdk.java.net"
func build_Op_Item(file_type, arch, download_url, sha256_url, file_name string) *Op_Item {
return &Op_Item{
FileType: file_type,
Arch: arch,
Url: download_url,
Sha256Url: sha256_url,
FileName: file_name,
}
}
func getFileNameByDownLoadUrl(url string) string {
downloads := strings.Split(url, "/")
file_name := downloads[len(downloads)-1]
return file_name
}
func getFileNameNoSuffix(file_name string) string {
return strings.ReplaceAll(file_name, "."+getFileTypeByFileName(file_name), "")
}
func GetSha256ByUrl(url string, isGetSha256 bool) string {
if isGetSha256 {
resp, _ := http.Get(url)
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
return string(bytes)
} else {
return url
}
}
func getFileTypeByFileName(filename string) string {
filenames := strings.Split(filename, ".")
switch filenames[len(filenames)-1] {
case "zip":
return "zip"
case "gz":
return "tar.gz"
default:
return filenames[len(filenames)-1]
}
}

@ -0,0 +1,87 @@
package collector
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"testing"
"github.com/PuerkitoBio/goquery"
)
func Test_GetGradleSha256ByUrl(t *testing.T) {
resp, _ := httpGetByProxy("https://downloads.gradle-dn.com/distributions/gradle-8.0.2-bin.zip.sha256")
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
t.Run("", func(t *testing.T) {
fmt.Println(string(bytes))
})
}
func Test_getCollectorVersionShaSum(t *testing.T) {
resp, _ := httpGetByProxy("https://gradle.org/release-checksums/")
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
versions := make([]*string, 0)
maps := make(map[string]string)
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
t.Run("", func(t *testing.T) {
docs := doc_selector.Find(".layout__main")
a_docs := docs.Find("a[name]")
a_docs.Each(func(j int, a_doc *goquery.Selection) {
version := a_doc.AttrOr("name", "")
if version != "" {
versions = append(versions, &version)
}
})
lis := docs.Find("ul[style]")
for i := 0; i < len(versions); i++ {
sha256 := lis.Eq(i).Find("li").Eq(i).Find("code").Text()
maps[*versions[i]] = sha256
fmt.Printf("version: %v , sha256: %v\n", *versions[i], sha256)
}
/* fmt.Printf("len(versions): %v\n", len(versions))
s := lis.Eq(0).Find("li").Eq(0).Find("code")
fmt.Printf("lis: %v\n", s.Text())
docs.Each(func(j int, doc *goquery.Selection) {
}) */
})
}
func Test_getCollectorVersion(t *testing.T) {
resp, _ := httpGetByProxy("https://gradle.org/releases/")
//resp, _ := http.Get("https://gradle.org/releases/")
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
t.Run("", func(t *testing.T) {
a_docs := doc_selector.Find(".resources-contents").Find("a[name]")
a_docs.Each(func(j int, a_doc *goquery.Selection) {
version := a_doc.AttrOr("name", "")
fmt.Printf("version: %v\n", version)
})
})
}
func httpGetByProxy(url string) (*http.Response, error) {
request, _ := http.NewRequest("GET", url, nil)
return getClientProxy().Do(request)
}
func getClientProxy() *http.Client {
proxyUrl, err := url.Parse("http://127.0.0.1:8000")
if err != nil {
panic(err)
}
return &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
}

@ -0,0 +1,215 @@
package collector
import (
"fmt"
"net/http"
"runtime"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/forget-the-bright/j/internal/pkg/config"
)
func ConvertCollectorToUrlItem(colls []*Collector, isGetSha256 bool) []*config.UrlItem {
var rs = make([]*config.UrlItem, 0)
for _, coll := range colls {
var item *Op_Item
switch runtime.GOOS {
case "linux":
if runtime.GOARCH == "aarch64" {
item = coll.Linux_AArch64
} else {
item = coll.Linux_X64
}
case "windows":
item = coll.Windows_X64
case "darwin":
if runtime.GOARCH == "aarch64" {
item = coll.Mac_AArch64
} else {
item = coll.Mac_X64
}
default:
item = nil
}
if item != nil {
rs = append(rs, &config.UrlItem{
In: &config.JavaFileItem{
FileName: item.FileName,
URL: item.Url,
Sha256: GetSha256ByUrl(item.Sha256Url, isGetSha256),
},
SimpleName: coll.Version,
Expected: getFileNameNoSuffix(item.FileName),
})
}
}
switch runtime.GOOS {
case "windows":
rs = append(rs, &config.UrlItem{
In: &config.JavaFileItem{
FileName: "openjdk-8u42-b03-windows-i586-14_jul_2022.zip",
URL: "https://download.java.net/openjdk/jdk8u42/ri/openjdk-8u42-b03-windows-i586-14_jul_2022.zip",
Sha256: "0314134bd981db63c7ca68d262ef896383b5694307a14bac81af88b5ad926279",
},
Expected: "openjdk-8u42-b03-windows-i586-14_jul_2022",
SimpleName: "8",
})
case "linux":
rs = append(rs, &config.UrlItem{
In: &config.JavaFileItem{
FileName: "openjdk-8u42-b03-linux-x64-14_jul_2022.tar.gz",
URL: "https://download.java.net/openjdk/jdk8u42/ri/openjdk-8u42-b03-linux-x64-14_jul_2022.tar.gz",
Sha256: "dd5fc6ef5ebffb88cd66af5258226c31f6c719fdcd855d95464fdb2cab051baa",
},
Expected: "openjdk-8u42-b03-linux-x64-14_jul_2022",
SimpleName: "8",
})
}
return config.ReverseArray(rs)
}
func GetOpenJDKVesionUrlInfo() []*Collector {
resp, _ := http.Get(Collector_Archive_Url)
Collectors = make([]*Collector, 0)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
divs := doc_selector.Find("#sidebar").Find(".links")
divs.Each(func(j int, div *goquery.Selection) {
link_about := div.Find(".about").Text()
if link_about == "Reference Implementations" {
a_docs := div.Find("a")
a_docs.Each(func(j int, a_doc *goquery.Selection) {
info_url := a_doc.AttrOr("href", "")
versions := strings.Split(a_doc.Text(), " ")
version := versions[len(versions)-1]
version_url := Collector_Url + strings.ReplaceAll(info_url, ".", "")
Collectors = append(Collectors, getVersionByUrl(version, version_url))
//fmt.Println(version)
//fmt.Println(version_url)
})
}
//fmt.Printf("link_about: %v\n", link_about)
})
return Collectors
}
func GetOpenJDKArchiveReleasesInfo() []*Collector {
Archive_Releases_Collectors = make([]*Collector, 0)
resp, _ := http.Get(Collector_Archive_Url)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
docs, _ := goquery.NewDocumentFromReader(resp.Body)
tbody_docs := docs.Find(".builds").Find("tbody").Children()
var collector_Item *Collector
tbody_docs.Each(func(j int, tr *goquery.Selection) {
th := tr.Find("th")
if th.Length() == 1 {
val := th.Text()
if val != "Source" {
s2 := strings.Split(val, "(build ")
version_str := strings.Trim(strings.Trim(s2[0], " "), " GA")
//fmt.Println("\n" + version_str)
collector_Item = &Collector{
Version: version_str,
}
Archive_Releases_Collectors = append(Archive_Releases_Collectors, collector_Item)
}
}
if th.Length() == 2 {
a_item := tr.Find("td").Find("a")
file_type := strings.Trim(a_item.First().Text(), "\n")
download_url := a_item.First().AttrOr("href", "")
file_name := getFileNameByDownLoadUrl(download_url)
sha256_url := a_item.Last().AttrOr("href", "")
releases := strings.Split(th.First().Text(), "/")
switch releases[0] {
case "Windows":
collector_Item.Windows_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
case "Mac":
if len(releases) == 1 || releases[1] == "x64" {
collector_Item.Mac_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
} else {
collector_Item.Mac_AArch64 = build_Op_Item(file_type, releases[1], download_url, sha256_url, file_name)
}
case "Linux":
if len(releases) == 1 || releases[1] == "x64" {
collector_Item.Linux_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
} else {
collector_Item.Linux_X64 = build_Op_Item(file_type, releases[1], download_url, sha256_url, file_name)
}
}
}
})
return Archive_Releases_Collectors
}
func getVersionByUrl(version, url string) *Collector {
var coll = Collector{
Version: version,
}
resp, _ := http.Get(url)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
divs := doc_selector.Find("#main").Find("ul")
if divs.Length() <= 1 || version == "8" {
li_docs := divs.Find("li")
linux_x64_a := li_docs.Eq(0).Find("a")
windows_x64_a := li_docs.Eq(1).Find("a")
linux_url := linux_x64_a.Eq(0).AttrOr("href", "")
linux_file_name := getFileNameByDownLoadUrl(linux_url)
linux_file_type := getFileTypeByFileName(linux_file_name)
linux_sha256_url := linux_x64_a.Eq(1).AttrOr("href", "")
windows_url := windows_x64_a.Eq(0).AttrOr("href", "")
windows_file_name := getFileNameByDownLoadUrl(windows_url)
windows_file_type := getFileTypeByFileName(windows_file_name)
windows_sha256_url := windows_x64_a.Eq(1).AttrOr("href", "")
coll.Linux_X64 = &Op_Item{
Arch: "x64",
Url: linux_url,
Sha256Url: linux_sha256_url,
FileName: linux_file_name,
FileType: linux_file_type,
}
coll.Windows_X64 = &Op_Item{
Arch: "x64",
Url: windows_url,
Sha256Url: windows_sha256_url,
FileName: windows_file_name,
FileType: windows_file_type,
}
} else {
divs_eq0 := divs.Eq(0)
li_docs := divs_eq0.Find("li")
linux_x64_a := li_docs.Eq(0).Find("a")
linux_url := linux_x64_a.Eq(0).AttrOr("href", "")
linux_file_name := getFileNameByDownLoadUrl(linux_url)
linux_file_type := getFileTypeByFileName(linux_file_name)
linux_sha256_url := linux_x64_a.Eq(1).AttrOr("href", "")
coll.Linux_X64 = &Op_Item{
Arch: "x64",
Url: linux_url,
Sha256Url: linux_sha256_url,
FileName: linux_file_name,
FileType: linux_file_type,
}
}
return &coll
}

@ -0,0 +1,188 @@
package collector
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/PuerkitoBio/goquery"
)
func Test_GetSha256ByUrl(t *testing.T) {
resp, _ := http.Get("https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_windows-x64_bin.zip.sha256")
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
t.Run("", func(t *testing.T) {
fmt.Println(string(bytes))
})
}
func Test_getOpenJdkVersion(t *testing.T) {
resp, _ := http.Get(Collector_Archive_Url)
colls := make([]*Collector, 0)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
t.Run("", func(t *testing.T) {
divs := doc_selector.Find("#sidebar").Find(".links")
divs.Each(func(j int, div *goquery.Selection) {
link_about := div.Find(".about").Text()
if link_about == "Reference Implementations" {
a_docs := div.Find("a")
a_docs.Each(func(j int, a_doc *goquery.Selection) {
info_url := a_doc.AttrOr("href", "")
versions := strings.Split(a_doc.Text(), " ")
version := versions[len(versions)-1]
version_url := Collector_Url + strings.ReplaceAll(info_url, ".", "")
colls = append(colls, test_getVersionByUrl(version, version_url))
//fmt.Println(version)
//fmt.Println(version_url)
})
}
fmt.Printf("link_about: %v\n", link_about)
})
temp := colls
fmt.Printf("len(temp): %v\n", len(temp))
//fmt.Printf("divs.Length(): %v\n", divs.Length())
})
}
func test_getVersionByUrl(version, url string) *Collector {
var coll = Collector{
Version: version,
}
resp, _ := http.Get(url)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
doc_selector, _ := goquery.NewDocumentFromReader(resp.Body)
divs := doc_selector.Find("#main").Find("ul")
if divs.Length() <= 1 || version == "8" {
li_docs := divs.Find("li")
linux_x64_a := li_docs.Eq(0).Find("a")
windows_x64_a := li_docs.Eq(1).Find("a")
linux_url := linux_x64_a.Eq(0).AttrOr("href", "")
linux_file_name := getFileNameByDownLoadUrl(linux_url)
linux_file_type := getFileTypeByFileName(linux_file_name)
linux_sha256_url := linux_x64_a.Eq(1).AttrOr("href", "")
windows_url := windows_x64_a.Eq(0).AttrOr("href", "")
windows_file_name := getFileNameByDownLoadUrl(windows_url)
windows_file_type := getFileTypeByFileName(windows_file_name)
windows_sha256_url := windows_x64_a.Eq(1).AttrOr("href", "")
coll.Linux_X64 = &Op_Item{
Arch: "x64",
Url: linux_url,
Sha256Url: linux_sha256_url,
FileName: linux_file_name,
FileType: linux_file_type,
}
coll.Windows_X64 = &Op_Item{
Arch: "x64",
Url: windows_url,
Sha256Url: windows_sha256_url,
FileName: windows_file_name,
FileType: windows_file_type,
}
} else {
divs_eq0 := divs.Eq(0)
li_docs := divs_eq0.Find("li")
linux_x64_a := li_docs.Eq(0).Find("a")
linux_url := linux_x64_a.Eq(0).AttrOr("href", "")
linux_file_name := getFileNameByDownLoadUrl(linux_url)
linux_file_type := getFileTypeByFileName(linux_file_name)
linux_sha256_url := linux_x64_a.Eq(1).AttrOr("href", "")
coll.Linux_X64 = &Op_Item{
Arch: "x64",
Url: linux_url,
Sha256Url: linux_sha256_url,
FileName: linux_file_name,
FileType: linux_file_type,
}
}
return &coll
}
func Test_getArchiveVersion(t *testing.T) {
Archive_Releases_Collectors = make([]*Collector, 0)
resp, _ := http.Get(Collector_Archive_Url)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("false")
}
c, _ := goquery.NewDocumentFromReader(resp.Body)
t.Run("", func(t *testing.T) {
s := c.Find(".builds").Find("tbody").Children()
/* s.Each(func(j int, tr *goquery.Selection) {
th := tr.Find("th")
if th.Length() == 1 {
val := th.Text()
if val != "Source" {
s2 := strings.Split(val, "(build ")
fmt.Println(strings.Trim(strings.Trim(s2[0], " "), " GA"))
}
}
}) */
var collector_Item *Collector
//flag := false
s.Each(func(j int, tr *goquery.Selection) {
th := tr.Find("th")
if th.Length() == 1 {
val := th.Text()
if val != "Source" {
s2 := strings.Split(val, "(build ")
version_str := strings.Trim(strings.Trim(s2[0], " "), " GA")
fmt.Println("\n" + version_str)
collector_Item = &Collector{
Version: version_str,
}
Archive_Releases_Collectors = append(Archive_Releases_Collectors, collector_Item)
}
}
if th.Length() == 2 {
a_item := tr.Find("td").Find("a")
file_type := strings.Trim(a_item.First().Text(), "\n")
download_url := a_item.First().AttrOr("href", "")
file_name := getFileNameByDownLoadUrl(download_url)
sha256_url := a_item.Last().AttrOr("href", "")
releases := strings.Split(th.First().Text(), "/")
switch releases[0] {
case "Windows":
collector_Item.Mac_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
case "Mac":
if len(releases) == 1 || releases[1] == "x64" {
collector_Item.Mac_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
} else {
collector_Item.Mac_AArch64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
}
case "Linux":
if len(releases) == 1 || releases[1] == "x64" {
collector_Item.Linux_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
} else {
collector_Item.Linux_X64 = build_Op_Item(file_type, "x64", download_url, sha256_url, file_name)
}
}
//fmt.Printf("%v %v\n", strings.Trim(a_item.First().Text(), "\n"), a_item.Last().Text())
//fmt.Printf("%v %v\n", th.First().Text(), th.Last().Text())
//fmt.Printf("%v\n%v\n", a_item.First().AttrOr("href", ""), a_item.Last().AttrOr("href", ""))
//fmt.Printf("th.Text(): %v th.len:%v\n", th.Text(), thLen)
}
})
})
c2 := Archive_Releases_Collectors
fmt.Printf("len(c2): %v\n", len(c2))
fmt.Println(c2)
}

@ -0,0 +1,112 @@
package config
var linux_Url_Items = []*UrlItem{
{
In: &JavaFileItem{
FileName: "openjdk-19+36_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk19/ri/openjdk-19+36_linux-x64_bin.tar.gz",
Sha256: "f47aba585cfc9ecff1ed8e023524e8309f4315ed8b80100b40c7dcc232c12f96",
},
Expected: "jdk-19",
SimpleName: "19",
},
{
In: &JavaFileItem{
FileName: "openjdk-18+36_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk18/ri/openjdk-18+36_linux-x64_bin.tar.gz",
Sha256: "0f60aef7b8504983d6e374fe94d09a7bedcf05ec559e812d801a33bd4ebd23d0",
},
Expected: "jdk-18",
SimpleName: "18",
},
{
In: &JavaFileItem{
FileName: "openjdk-17+35_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz",
Sha256: "aef49cc7aa606de2044302e757fa94c8e144818e93487081c4fd319ca858134b",
},
Expected: "jdk-17",
SimpleName: "17",
},
{
In: &JavaFileItem{
FileName: "openjdk-16+36_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk16/ri/openjdk-16+36_linux-x64_bin.tar.gz",
Sha256: "e952958f16797ad7dc7cd8b724edd69ec7e0e0434537d80d6b5165193e33b931",
},
Expected: "jdk-16",
SimpleName: "16",
},
{
In: &JavaFileItem{
FileName: "openjdk-15+36_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk15/ri/openjdk-15+36_linux-x64_bin.tar.gz",
Sha256: "bb67cadee687d7b486583d03c9850342afea4593be4f436044d785fba9508fb7",
},
Expected: "jdk-15",
SimpleName: "15",
},
{
In: &JavaFileItem{
FileName: "openjdk-14+36_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk14/ri/openjdk-14+36_linux-x64_bin.tar.gz",
Sha256: "c7006154dfb8b66328c6475447a396feb0042608ee07a96956547f574a911c09",
},
Expected: "jdk-14",
SimpleName: "14",
},
{
In: &JavaFileItem{
FileName: "openjdk-13+33_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk13/ri/openjdk-13+33_linux-x64_bin.tar.gz",
Sha256: "5f547b8f0ffa7da517223f6f929a5055d749776b1878ccedbd6cc1334f4d6f4d",
},
Expected: "jdk-13",
SimpleName: "13",
},
{
In: &JavaFileItem{
FileName: "openjdk-12+32_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk12/ri/openjdk-12+32_linux-x64_bin.tar.gz",
Sha256: "4bf3d9f4bbbb8cb9a0d96ceade42df8b2ca85f7853fbcd08274df2b7d2cef074",
},
Expected: "jdk-12",
SimpleName: "12",
},
{
In: &JavaFileItem{
FileName: "openjdk-11+28_linux-x64_bin.tar.gz",
URL: "https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_linux-x64_bin.tar.gz",
Sha256: "3784cfc4670f0d4c5482604c7c513beb1a92b005f569df9bf100e8bef6610f2e",
},
Expected: "jdk-11",
SimpleName: "11",
},
{
In: &JavaFileItem{
FileName: "openjdk-10+44_linux-x64_bin_ri.tar.gz",
URL: "https://download.java.net/openjdk/jdk10/ri/openjdk-10+44_linux-x64_bin_ri.tar.gz",
Sha256: "0b0e778f2c935dae32c71dd78f3ad921e0972ffc536e64703f0e9855e570abe2",
},
Expected: "jdk-10",
SimpleName: "10",
},
{
In: &JavaFileItem{
FileName: "openjdk-9+181_linux-x64_ri.zip",
URL: "https://download.java.net/openjdk/jdk9/ri/openjdk-9+181_linux-x64_ri.zip",
Sha256: "f4f9c75f9f1f2d1888b9be013c96210e017fd22547366c8e0929085dfe8e38aa",
},
Expected: "jdk-9",
SimpleName: "9",
},
{
In: &JavaFileItem{
FileName: "openjdk-8u42-b03-linux-x64-14_jul_2022.tar.gz",
URL: "https://download.java.net/openjdk/jdk8u42/ri/openjdk-8u42-b03-linux-x64-14_jul_2022.tar.gz",
Sha256: "dd5fc6ef5ebffb88cd66af5258226c31f6c719fdcd855d95464fdb2cab051baa",
},
Expected: "jdk-8",
SimpleName: "8",
},
}

@ -0,0 +1,39 @@
package config
import (
"errors"
"runtime"
cli "github.com/urfave/cli/v2"
)
type JavaFileItem struct {
FileName string
URL string
Sha256 string
}
type UrlItem struct {
In *JavaFileItem
Expected string
SimpleName string
}
var Url_Items []*UrlItem
func ReverseArray(arr []*UrlItem) []*UrlItem {
for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 {
arr[i], arr[j] = arr[j], arr[i]
}
return arr
}
func init() {
switch runtime.GOOS {
case "linux":
Url_Items = linux_Url_Items
case "windows":
Url_Items = windows_Url_Items
default:
cli.Exit(errors.New(runtime.GOOS+" OS is not supported"), 1)
}
}

@ -0,0 +1,103 @@
package config
var windows_Url_Items = []*UrlItem{
{
In: &JavaFileItem{
FileName: "openjdk-19+36_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk19/ri/openjdk-19+36_windows-x64_bin.zip",
Sha256: "8fabcee7c4e8d3b53486777ecd27bb906d67d7c1efd1bf22a8290cf659afa487",
},
Expected: "jdk-19",
SimpleName: "19",
},
{
In: &JavaFileItem{
FileName: "openjdk-18+36_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk18/ri/openjdk-18+36_windows-x64_bin.zip",
Sha256: "a5b91d4c12752d44aa75df70ae3e2311287b3e60c288b07dade106376c688277",
},
Expected: "jdk-18",
SimpleName: "18",
},
{
In: &JavaFileItem{
FileName: "openjdk-17+35_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_windows-x64_bin.zip",
Sha256: "e88b0df00021c9d266bb435c9a95fdc67d1948cce4518daf85c234907bd393c5",
},
Expected: "jdk-17",
SimpleName: "17",
},
{
In: &JavaFileItem{
FileName: "openjdk-16+36_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk16/ri/openjdk-16+36_windows-x64_bin.zip",
Sha256: "a78bdeaad186297601edac6772d931224d7af6f682a43372e693c37020bd37d6",
},
Expected: "jdk-16",
SimpleName: "16",
},
{
In: &JavaFileItem{
FileName: "openjdk-15+36_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk15/ri/openjdk-15+36_windows-x64_bin.zip",
Sha256: "764e39a71252a9791118a31ae56a4247c049463bda5eb72497122ec50b1d07f8",
},
Expected: "jdk-15",
SimpleName: "15",
},
{
In: &JavaFileItem{
FileName: "openjdk-14+36_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk14/ri/openjdk-14+36_windows-x64_bin.zip",
Sha256: "6b56c65c2ebb89eb361f47370359f88c4b87234dc073988a2c33e7d75c01e488",
},
Expected: "jdk-14",
SimpleName: "14",
},
{
In: &JavaFileItem{
FileName: "openjdk-13+33_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk13/ri/openjdk-13+33_windows-x64_bin.zip",
Sha256: "053d8c87bb34347478512911a6218a389720bffcde4e496be5a54d51ad7c9c2f",
},
Expected: "jdk-13",
SimpleName: "13",
},
{
In: &JavaFileItem{
FileName: "openjdk-12+32_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk12/ri/openjdk-12+32_windows-x64_bin.zip",
Sha256: "d6a550477754289e5bc0a635974b40bf5bc0515db441381414303ae954d8d6b8",
},
Expected: "jdk-12",
SimpleName: "12",
},
{
In: &JavaFileItem{
FileName: "openjdk-11+28_windows-x64_bin.zip",
URL: "https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip",
Sha256: "fde3b28ca31b86a889c37528f17411cd0b9651beb6fa76cac89a223417910f4b",
},
Expected: "jdk-11",
SimpleName: "11",
},
{
In: &JavaFileItem{
FileName: "jdk-9+181_windows-x64_ri.zip",
URL: "https://download.java.net/openjdk/jdk9/ri/jdk-9+181_windows-x64_ri.zip",
Sha256: "51948d69c7b770b376162ec5b88f6ec8a266bd3c9e6da21c4e834b6d0d661897",
},
Expected: "jdk-9",
SimpleName: "9",
},
{
In: &JavaFileItem{
FileName: "openjdk-8u42-b03-windows-i586-14_jul_2022.zip",
URL: "https://download.java.net/openjdk/jdk8u42/ri/openjdk-8u42-b03-windows-i586-14_jul_2022.zip",
Sha256: "0314134bd981db63c7ca68d262ef896383b5694307a14bac81af88b5ad926279",
},
Expected: "java-se-8u42-ri",
SimpleName: "8",
},
}

@ -0,0 +1,72 @@
package download
import (
"fmt"
"io"
"io/fs"
"io/ioutil"
"net/http"
"os"
"time"
"github.com/forget-the-bright/j/internal/pkg/errs"
"github.com/k0kubun/go-ansi"
"github.com/schollz/progressbar/v3"
)
// Download 下载资源并另存为
func Download(srcURL string, filename string, flag int, perm fs.FileMode, withProgress bool) (size int64, err error) {
resp, err := http.Get(srcURL)
if err != nil {
return 0, errs.NewDownloadError(srcURL, err)
}
defer resp.Body.Close()
f, err := os.OpenFile(filename, flag, perm)
if err != nil {
return 0, errs.NewDownloadError(srcURL, err)
}
defer f.Close()
var dst io.Writer
if withProgress {
bar := progressbar.NewOptions64(
resp.ContentLength,
progressbar.OptionEnableColorCodes(true),
progressbar.OptionSetTheme(progressbar.Theme{
Saucer: "=",
SaucerHead: ">",
SaucerPadding: " ",
BarStart: "[",
BarEnd: "]",
}),
progressbar.OptionSetWidth(15),
progressbar.OptionSetDescription("Downloading"),
progressbar.OptionSetWriter(ansi.NewAnsiStdout()),
progressbar.OptionShowBytes(true),
progressbar.OptionThrottle(65*time.Millisecond),
progressbar.OptionShowCount(),
progressbar.OptionOnCompletion(func() {
_, _ = fmt.Fprint(ansi.NewAnsiStdout(), "\n")
}),
// progressbar.OptionSpinnerType(35),
// progressbar.OptionFullWidth(),
)
_ = bar.RenderBlank()
dst = io.MultiWriter(f, bar)
} else {
dst = f
}
return io.Copy(dst, resp.Body)
}
// DownloadAsBytes 返回下载资源的原始字节切片
func DownloadAsBytes(srcURL string) (data []byte, err error) {
resp, err := http.Get(srcURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}

@ -0,0 +1,88 @@
package errs
import (
"errors"
"fmt"
"strings"
)
var (
// ErrVersionNotFound 版本不存在
ErrVersionNotFound = errors.New("version not found")
// ErrPackageNotFound 版本包不存在
ErrPackageNotFound = errors.New("installation package not found")
)
var (
// ErrUnsupportedChecksumAlgorithm 不支持的校验和算法
ErrUnsupportedChecksumAlgorithm = errors.New("unsupported checksum algorithm")
// ErrChecksumNotMatched 校验和不匹配
ErrChecksumNotMatched = errors.New("file checksum does not match the computed checksum")
// ErrChecksumFileNotFound 校验和文件不存在
ErrChecksumFileNotFound = errors.New("checksum file not found")
)
// URLUnreachableError URL不可达错误
type URLUnreachableError struct {
err error
url string
}
// NewURLUnreachableError 返回URL不可达错误实例
func NewURLUnreachableError(url string, err error) error {
return &URLUnreachableError{
err: err,
url: url,
}
}
func (e URLUnreachableError) Error() string {
var buf strings.Builder
buf.WriteString(fmt.Sprintf("URL %q is unreachable", e.url))
if e.err != nil {
buf.WriteString(" ==> " + e.err.Error())
}
return buf.String()
}
func (e URLUnreachableError) Err() error {
return e.err
}
func (e URLUnreachableError) URL() string {
return e.url
}
// DownloadError 下载失败错误
type DownloadError struct {
url string
err error
}
// NewDownloadError 返回下载失败错误实例
func NewDownloadError(url string, err error) error {
return &DownloadError{
url: url,
err: err,
}
}
// Error 返回错误字符串
func (e DownloadError) Error() string {
var buf strings.Builder
buf.WriteString(fmt.Sprintf("Resource(%s) download failed", e.url))
if e.err != nil {
buf.WriteString(" ==> " + e.err.Error())
}
return buf.String()
}
// Err 返回错误对象
func (e DownloadError) Err() error {
return e.err
}
// URL 返回资源URL
func (e DownloadError) URL() string {
return e.url
}

@ -0,0 +1,7 @@
package main
import "github.com/forget-the-bright/j/cli"
func main() {
cli.Run()
}

@ -0,0 +1,59 @@
GO = CGO_ENABLED=0 GO111MODULE=on GOPROXY=https://goproxy.cn,direct go
BUILD_DATE := $(shell date '+%Y-%m-%d %H:%M:%S')
GIT_BRANCH := $(shell git symbolic-ref --short -q HEAD)
GIT_COMMIT_HASH := $(shell git rev-parse HEAD|cut -c 1-8)
GO_FLAGS := -v -ldflags="-X 'github.com/forget-the-bright/j/internal/build.Build=$(BUILD_DATE)' -X 'github.com/forget-the-bright/j/internal/build.Commit=$(GIT_COMMIT_HASH)' -X 'github.com/forget-the-bright/j/internal/build.Branch=$(GIT_BRANCH)'"
all: install test clean
build:
$(GO) build $(GO_FLAGS)
install: build
$(GO) install $(GO_FLAGS)
build-myall: build-linux-amd64 build-windows-amd64
build-all: build-linux build-darwin build-windows
build-linux: build-linux-386 build-linux-amd64 build-linux-arm build-linux-arm64 build-linux-s390x
build-linux-386:
GOOS=linux GOARCH=386 $(GO) build $(GO_FLAGS) -o bin/linux-386/j
build-linux-amd64:
GOOS=linux GOARCH=amd64 $(GO) build $(GO_FLAGS) -o bin/linux-amd64/linux_amd_x86_64_j
build-linux-arm:
GOOS=linux GOARCH=arm $(GO) build $(GO_FLAGS) -o bin/linux-arm/j
build-linux-arm64:
GOOS=linux GOARCH=arm64 $(GO) build $(GO_FLAGS) -o bin/linux-arm64/j
build-linux-s390x:
GOOS=linux GOARCH=s390x $(GO) build $(GO_FLAGS) -o bin/linux-s390x/j
build-darwin: build-darwin-amd64 build-darwin-arm64
build-darwin-amd64:
GOOS=darwin GOARCH=amd64 $(GO) build $(GO_FLAGS) -o bin/darwin-amd64/j
build-darwin-arm64:
GOOS=darwin GOARCH=arm64 $(GO) build $(GO_FLAGS) -o bin/darwin-arm64/j
build-windows: build-windows-386 build-windows-amd64 build-windows-arm build-windows-arm64
build-windows-386:
GOOS=windows GOARCH=386 $(GO) build $(GO_FLAGS) -o bin/windows-386/j.exe
build-windows-amd64:
GOOS=windows GOARCH=amd64 $(GO) build $(GO_FLAGS) -o bin/windows-amd64/windows_amd_x86_64_j.exe
build-windows-arm:
GOOS=windows GOARCH=arm $(GO) build $(GO_FLAGS) -o bin/windows-arm/j.exe
build-windows-arm64:
GOOS=windows GOARCH=arm64 $(GO) build $(GO_FLAGS) -o bin/windows-arm64/j.exe
package:
sh ./package.sh
test:
$(GO) test -v ./...
clean:
$(GO) clean -x
rm -f sha256sum.txt
rm -rf bin
.PHONY: all build install test package clean build-linux build-darwin build-windows build-linux-386 build-linux-amd64 build-linux-arm build-linux-arm64 build-linux-s390x build-darwin-amd64 build-darwin-arm64 build-windows-386 build-windows-amd64 build-windows-arm build-windows-arm64
Loading…
Cancel
Save