main
15128022404 2 years ago
parent d1fca0aa05
commit f17742409a

4
.gitignore vendored

@ -10,6 +10,8 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
downloads
go
versions
# Dependency directories (remove the comment below to include it)
# vendor/

@ -0,0 +1,156 @@
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()
goroot = filepath.Join(ghomeDir, "go")
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 = "g"
app.Usage = "Golang Version Manager"
app.Version = build.Version()
app.Copyright = fmt.Sprintf("Copyright (c) 2019-%d, voidint. 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, "go")
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)
}
}
// ghome 返回g根目录
func ghome() (dir string) {
/* if experimental := os.Getenv(experimentalEnv); experimental == "true" {
if dir = os.Getenv(homeEnv); dir != "" {
return dir
}
}
homeDir, _ := os.UserHomeDir()
return filepath.Join(homeDir, ".g") */
path, _ := os.Getwd()
return path
}
// 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("[g] %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,20 @@
package cli
import "github.com/urfave/cli/v2"
var (
commands = []*cli.Command{
{
Name: "ls",
Usage: "List installed versions",
UsageText: "g ls",
Action: list,
},
{
Name: "use",
Usage: "Switch to specified version",
UsageText: "g use <version>",
Action: use,
},
}
)

@ -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,33 @@
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 nil
//return cli.ShowSubcommandHelp(ctx)
}
targetV := filepath.Join(versionsDir, vname)
if finfo, err := os.Stat(targetV); err != nil || !finfo.IsDir() {
return cli.Exit(fmt.Sprintf("[g] 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", "go"), "version").Output(); err == nil {
fmt.Print(string(output))
}
return nil
}

@ -0,0 +1,19 @@
module github.com/forget-the-bright/j
go 1.20
require (
github.com/Masterminds/semver v1.5.0
github.com/fatih/color v1.15.0
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213
github.com/urfave/cli/v2 v2.25.0
)
require (
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/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.6.0 // indirect
)

@ -0,0 +1,22 @@
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
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/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/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/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/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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=

@ -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,14 @@
package main
import "github.com/forget-the-bright/j/cli"
func main() {
/* dir, _ := os.Getwd()
fmt.Println(dir)
cli.List(dir)
if len(os.Args) > 1 {
fmt.Println(os.Args[1])
cli.Use(os.Args[1]) //"1.17.9"
} */
cli.Run()
}
Loading…
Cancel
Save