1 Star 0 Fork 1

yss930819/gf-ex

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
cmd_install.go 5.92 KB
一键复制 编辑 原始数据 按行查看 历史
yss930819 提交于 2022-01-05 10:53 . style: 代码格式调整
package yscmd
import (
"gitee.com/kmyss/gf-ex/ysbuild"
"gitee.com/kmyss/gf-ex/yslog"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/container/gset"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gcmd"
"github.com/gogf/gf/os/genv"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/text/gstr"
"github.com/gogf/gf/util/gconv"
"runtime"
"strings"
)
const INSTALL = "install"
type CmdInstallBuilder struct {
CommandBuilderCore
}
func (b *CmdInstallBuilder) SetFlag(IFlagBuilder, ...string) bool {
return false
}
func (b *CmdInstallBuilder) Init() {
b.C = NewDefaultCommand()
b.C.Run = b.run
b.C.Use = INSTALL
b.C.Short = "将程序安装到指定文件夹"
}
func (b *CmdInstallBuilder) SetChildCommand(ICommandBuilder) bool {
return false
}
// installFolderPath contains installFolderPath-related data,
// such as path, writable, binaryFilePath, and installed.
type installFolderPath struct {
path string
writable bool
binaryFilePath string
installed bool
}
func (b *CmdInstallBuilder) run(*Command) {
yslog.Debug("CmdVersionBuilder Run")
// Ask where to install.
paths := getInstallPathsData()
if len(paths) <= 0 {
yslog.Printf("没有找到可以安装的目录,您需要手动将程序拷贝到 path 目录.")
return
}
yslog.Printf("我们通过 $PATH 在您电脑里找到如下路径 ")
yslog.Printf(" %2s | %4s | %5s | %s", "序号", "是否可写", "是否已安装", "路径")
// Print all paths status and determine the default selectedID value.
var (
selectedID = -1
pathSet = gset.NewStrSet() // Used for repeated items filtering.
)
for id, aPath := range paths {
if !pathSet.AddIfNotExist(aPath.path) {
continue
}
yslog.Printf(" %4d | %8t | %10t | %s", id, aPath.writable, aPath.installed, aPath.path)
if selectedID == -1 {
// Use the previously installed path as the most priority choice.
if aPath.installed {
selectedID = id
}
}
}
// If there's no previously installed path, use the first writable path.
if selectedID == -1 {
// Order by choosing priority.
commonPaths := garray.NewStrArrayFrom(g.SliceStr{
`/usr/local/bin`,
`/usr/bin`,
`/usr/sbin`,
`C:\Windows`,
`C:\Windows\system32`,
`C:\Go\bin`,
`C:\Program Files`,
`C:\Program Files (x86)`,
})
// Check the common installation directories.
commonPaths.Iterator(func(k int, v string) bool {
for id, aPath := range paths {
if strings.EqualFold(aPath.path, v) {
selectedID = id
return false
}
}
return true
})
if selectedID == -1 {
selectedID = 0
}
}
// GetSelectId
input := gcmd.Scanf("请选择一个序号 [默认: %d]: ", selectedID)
if input != "" {
selectedID = gconv.Int(input)
}
// Check if out of range.
if selectedID >= len(paths) || selectedID < 0 {
yslog.Printf("选择的序号有误: %d", selectedID)
return
}
// Get selected destination path.
dstPath := paths[selectedID]
// Install the new binary.
err := gfile.CopyFile(gfile.SelfPath(), dstPath.binaryFilePath)
if err != nil {
yslog.Printf("安装到 '%s' 失败: %v", dstPath.path, err)
yslog.Printf("您需要手动将程序拷贝到: %s", dstPath.path)
} else {
yslog.Printf("安装成功: %s", dstPath.path)
}
// Uninstall the old binary.
for _, aPath := range paths {
// Do not delete myself.
if aPath.binaryFilePath != "" &&
aPath.binaryFilePath != dstPath.binaryFilePath &&
gfile.SelfPath() != aPath.binaryFilePath {
_ = gfile.Remove(aPath.binaryFilePath)
}
}
}
// IsInstalled returns whether the binary is installed.
func IsInstalled() bool {
paths := getInstallPathsData()
for _, aPath := range paths {
if aPath.installed {
return true
}
}
return false
}
// GetInstallPathsData returns the installation paths data for the binary.
func getInstallPathsData() []installFolderPath {
var folderPaths []installFolderPath
// Pre generate binaryFileName.
binaryFileName := ysbuild.APPName + gfile.Ext(gfile.SelfPath())
switch runtime.GOOS {
case "darwin":
darwinInstallationCheckPaths := []string{"/usr/local/bin"}
for _, v := range darwinInstallationCheckPaths {
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, v, binaryFileName,
)
}
fallthrough
default:
// $GOPATH/bin
gopath := gfile.Join(runtime.GOROOT(), "bin")
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, gopath, binaryFileName,
)
// Search and find the writable directory path.
envPath := genv.Get("PATH", genv.Get("Path"))
if gstr.Contains(envPath, ";") {
for _, v := range gstr.SplitAndTrim(envPath, ";") {
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, v, binaryFileName,
)
}
} else if gstr.Contains(envPath, ":") {
for _, v := range gstr.SplitAndTrim(envPath, ":") {
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, v, binaryFileName,
)
}
} else if envPath != "" {
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, envPath, binaryFileName,
)
} else {
folderPaths = checkPathAndAppendToInstallFolderPath(
folderPaths, "/usr/local/bin", binaryFileName,
)
}
}
return folderPaths
}
// checkPathAndAppendToInstallFolderPath checks if `path` is writable and already installed.
// It adds the `path` to `folderPaths` if it is writable or already installed, or else it ignores the `path`.
func checkPathAndAppendToInstallFolderPath(folderPaths []installFolderPath, path string, binaryFileName string) []installFolderPath {
var (
binaryFilePath = gfile.Join(path, binaryFileName)
writable = gfile.IsWritable(path)
installed = isInstalled(binaryFilePath)
)
if !writable && !installed {
return folderPaths
}
return append(
folderPaths,
installFolderPath{
path: path,
writable: writable,
binaryFilePath: binaryFilePath,
installed: installed,
})
}
// Check if this gf binary path exists.
func isInstalled(path string) bool {
return gfile.Exists(path)
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/kmyss/gf-ex.git
git@gitee.com:kmyss/gf-ex.git
kmyss
gf-ex
gf-ex
v0.8.0

搜索帮助