Skip to content

Commit 1ae5bbb

Browse files
authored
Merge pull request #126 from xushiwei/q
x/cmd/tool
2 parents c197fb1 + 749b2b8 commit 1ae5bbb

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

cmd/tool/tool.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
Copyright 2025 Qiniu Limited (qiniu.com)
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tool
18+
19+
import (
20+
"os"
21+
"os/exec"
22+
"strings"
23+
)
24+
25+
var (
26+
// ErrNotFound is the error resulting if a path search failed to find
27+
// an executable file.
28+
ErrNotFound = exec.ErrNotFound
29+
)
30+
31+
// Tool represents a tool that can be executed.
32+
type Tool struct {
33+
cmd string
34+
installs [][]string
35+
}
36+
37+
// New creates a new Tool instance with the specified cmd and its install commands.
38+
func New(cmd string, installs []string) *Tool {
39+
inst := make([][]string, len(installs))
40+
for i, install := range installs {
41+
inst[i] = strings.Split(install, " ")
42+
}
43+
return &Tool{
44+
cmd: cmd,
45+
installs: inst,
46+
}
47+
}
48+
49+
// New creates a new command with the specified arguments.
50+
func (p *Tool) New(quietInstall bool, args ...string) (cmd *exec.Cmd, err error) {
51+
app, err := p.Get(quietInstall)
52+
if err != nil {
53+
return
54+
}
55+
return exec.Command(app, args...), nil
56+
}
57+
58+
// Get retrieves the path of the command.
59+
// If the command is not found, it attempts to install it using the specified
60+
// install commands.
61+
func (p *Tool) Get(quietInstall bool) (app string, err error) {
62+
app, err = exec.LookPath(p.cmd)
63+
if err == nil {
64+
return
65+
}
66+
amPath, install, err := p.getAppManager()
67+
if err != nil {
68+
return
69+
}
70+
c := exec.Command(amPath, install[1:]...)
71+
c.Stdout = os.Stdout
72+
c.Stderr = os.Stderr
73+
if err = c.Run(); err != nil {
74+
return
75+
}
76+
return exec.LookPath(p.cmd)
77+
}
78+
79+
func (p *Tool) getAppManager() (amPath string, install []string, err error) {
80+
for _, install = range p.installs {
81+
am := install[0]
82+
if amPath, err = exec.LookPath(am); err == nil {
83+
return
84+
}
85+
}
86+
err = ErrNotFound
87+
return
88+
}

0 commit comments

Comments
 (0)