AJ ONeal
5 年前
共有 5 个文件被更改,包括 318 次插入 和 15 次删除
@ -0,0 +1,205 @@ |
|||
package manager |
|||
|
|||
import ( |
|||
"fmt" |
|||
"io/ioutil" |
|||
"os/exec" |
|||
"path/filepath" |
|||
"strings" |
|||
) |
|||
|
|||
// Runnable defines a command to run, along with its arguments,
|
|||
// and whether or not failing to exit successfully matters.
|
|||
// It also defines whether certains words must exist (or not exist)
|
|||
// in its output, apart from existing successfully, to determine
|
|||
// whether or not it was actually successful.
|
|||
type Runnable struct { |
|||
Exec string |
|||
Args []string |
|||
Must bool |
|||
Keywords []string |
|||
Badwords []string |
|||
} |
|||
|
|||
func (x Runnable) Run() error { |
|||
cmd := exec.Command(x.Exec, x.Args...) |
|||
out, err := cmd.CombinedOutput() |
|||
if !x.Must { |
|||
return nil |
|||
} |
|||
|
|||
good := true |
|||
str := string(out) |
|||
for j := range x.Keywords { |
|||
if !strings.Contains(str, x.Keywords[j]) { |
|||
good = false |
|||
break |
|||
} |
|||
} |
|||
if good && 0 != len(x.Badwords) { |
|||
for j := range x.Badwords { |
|||
if "" != x.Badwords[j] && !strings.Contains(str, x.Badwords[j]) { |
|||
good = false |
|||
break |
|||
} |
|||
} |
|||
} |
|||
if nil != err { |
|||
return fmt.Errorf("Failed to run %s %s\n%s\n", x.Exec, strings.Join(x.Args, " "), str) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (x Runnable) String() string { |
|||
var comment string |
|||
var must = "true" |
|||
|
|||
if x.Must { |
|||
must = "exit" |
|||
if len(x.Keywords) > 0 { |
|||
comment += "# output must match all of:\n" |
|||
comment += "\t" + strings.Join(x.Keywords, "#\t \n") + "\n" |
|||
} |
|||
if len(x.Badwords) > 0 { |
|||
comment += "# output must not match any of:\n" |
|||
comment += "\t" + strings.Join(x.Keywords, "#\t \n") + "\n" |
|||
} |
|||
} |
|||
|
|||
return strings.TrimSpace(fmt.Sprintf( |
|||
"%s %s || %s\n%s", |
|||
x.Exec, |
|||
strings.Join(x.Args, " "), |
|||
must, |
|||
comment, |
|||
)) |
|||
} |
|||
|
|||
func getSrvs(dir string) ([]string, error) { |
|||
plists := []string{} |
|||
|
|||
infos, err := ioutil.ReadDir(dir) |
|||
if nil != err { |
|||
return nil, err |
|||
} |
|||
|
|||
for i := range infos { |
|||
x := infos[i] |
|||
fname := strings.ToLower(x.Name()) |
|||
if strings.HasSuffix(fname, srvExt) { |
|||
plists = append(plists, x.Name()) |
|||
} |
|||
} |
|||
|
|||
return plists, nil |
|||
} |
|||
|
|||
func getSystemSrvs() ([]string, error) { |
|||
return getSrvs(srvSysPath) |
|||
} |
|||
|
|||
func getUserSrvs(home string) ([]string, error) { |
|||
dir := filepath.Join(home, srvUserPath) |
|||
return getSrvs(dir) |
|||
} |
|||
|
|||
func filterMatchingSrvs(plists []string, name string) []string { |
|||
filtered := []string{} |
|||
|
|||
for i := range plists { |
|||
pname := plists[i] |
|||
lname := strings.ToLower(pname) |
|||
n := len(lname) |
|||
if strings.HasSuffix(lname[:n-srvLen], strings.ToLower(name)) { |
|||
filtered = append(filtered, pname) |
|||
} |
|||
} |
|||
|
|||
return filtered |
|||
} |
|||
|
|||
func getMatchingSrvs(home string, name string) ([]string, []string, error) { |
|||
sysPlists, err := getSystemSrvs() |
|||
if nil != err { |
|||
return nil, nil, err |
|||
} |
|||
|
|||
var userPlists []string |
|||
if "" != home { |
|||
userPlists, err = getUserSrvs(home) |
|||
if nil != err { |
|||
return nil, nil, err |
|||
} |
|||
} |
|||
|
|||
return filterMatchingSrvs(sysPlists, name), filterMatchingSrvs(userPlists, name), nil |
|||
} |
|||
|
|||
func getExactSrvMatch(srvs []string, name string) string { |
|||
for i := range srvs { |
|||
srv := srvs[i] |
|||
n := len(srv) |
|||
if srv[:n-srvLen] == strings.ToLower(name) { |
|||
return srv |
|||
} |
|||
} |
|||
|
|||
return "" |
|||
} |
|||
|
|||
func getOneSysSrv(sys []string, user []string, name string) (string, error) { |
|||
service := getExactSrvMatch(user, name) |
|||
if "" != service { |
|||
return service, nil |
|||
} |
|||
|
|||
var errstr string |
|||
// system service was wanted
|
|||
n := len(sys) |
|||
switch { |
|||
case 0 == n: |
|||
errstr += fmt.Sprintf("Didn't find user service matching %q\n", name) |
|||
if 0 != len(user) { |
|||
errstr += fmt.Sprintf("Did you intend to run a user service instead?\n\t%s\n", strings.Join(user, "\n\t")) |
|||
} |
|||
case n > 1: |
|||
errstr += fmt.Sprintf("Found more than one matching service:\n\t%s\n", strings.Join(sys, "\n\t")) |
|||
default: |
|||
service = filepath.Join(srvSysPath, sys[0]) |
|||
} |
|||
|
|||
if "" != errstr { |
|||
return "", fmt.Errorf(errstr) |
|||
} |
|||
|
|||
return service, nil |
|||
} |
|||
|
|||
func getOneUserSrv(home string, sys []string, user []string, name string) (string, error) { |
|||
service := getExactSrvMatch(user, name) |
|||
if "" != service { |
|||
return service, nil |
|||
} |
|||
|
|||
var errstr string |
|||
// user service was wanted
|
|||
n := len(user) |
|||
switch { |
|||
case 0 == n: |
|||
errstr += fmt.Sprintf("Didn't find user service matching %q\n", name) |
|||
if 0 != len(sys) { |
|||
errstr += fmt.Sprintf("Did you intend to run a system service instead?\n\t%s\n", strings.Join(sys, "\n\t")) |
|||
} |
|||
case n > 1: |
|||
errstr += fmt.Sprintf("Found more than one matching service:\n\t%s\n", strings.Join(user, "\n\t")) |
|||
default: |
|||
service = filepath.Join(home, srvUserPath, user[0]+srvExt) |
|||
} |
|||
|
|||
if "" != errstr { |
|||
return "", fmt.Errorf(errstr) |
|||
} |
|||
|
|||
return service, nil |
|||
} |
正在加载...
在新工单中引用