1
0
mirror of https://github.com/go-task/task.git synced 2024-12-29 02:57:27 +02:00
task/vendor/mvdan.cc/sh/interp/test.go

179 lines
4.1 KiB
Go
Raw Normal View History

2017-04-24 14:47:10 +02:00
// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information
package interp
import (
2018-01-03 19:12:40 +02:00
"fmt"
2017-04-24 14:47:10 +02:00
"os"
"os/exec"
"regexp"
2017-11-19 22:26:37 +02:00
"golang.org/x/crypto/ssh/terminal"
"mvdan.cc/sh/syntax"
2017-04-24 14:47:10 +02:00
)
// non-empty string is true, empty string is false
func (r *Runner) bashTest(expr syntax.TestExpr) string {
switch x := expr.(type) {
case *syntax.Word:
return r.loneWord(x)
case *syntax.ParenTest:
return r.bashTest(x.X)
case *syntax.BinaryTest:
switch x.Op {
case syntax.TsMatch, syntax.TsNoMatch:
str := r.loneWord(x.X.(*syntax.Word))
yw := x.Y.(*syntax.Word)
2018-01-03 19:12:40 +02:00
pat := r.lonePattern(yw)
if match(pat, str) == (x.Op == syntax.TsMatch) {
return "1"
}
return ""
}
2017-04-24 14:47:10 +02:00
if r.binTest(x.Op, r.bashTest(x.X), r.bashTest(x.Y)) {
return "1"
}
return ""
case *syntax.UnaryTest:
if r.unTest(x.Op, r.bashTest(x.X)) {
return "1"
}
return ""
}
return ""
}
func (r *Runner) binTest(op syntax.BinTestOperator, x, y string) bool {
switch op {
case syntax.TsReMatch:
re, err := regexp.Compile(y)
if err != nil {
r.exit = 2
return false
}
return re.MatchString(x)
case syntax.TsNewer:
2018-01-03 19:12:40 +02:00
info1, err1 := r.stat(x)
info2, err2 := r.stat(y)
if err1 != nil || err2 != nil {
2017-04-24 14:47:10 +02:00
return false
}
2018-01-03 19:12:40 +02:00
return info1.ModTime().After(info2.ModTime())
2017-04-24 14:47:10 +02:00
case syntax.TsOlder:
2018-01-03 19:12:40 +02:00
info1, err1 := r.stat(x)
info2, err2 := r.stat(y)
if err1 != nil || err2 != nil {
2017-04-24 14:47:10 +02:00
return false
}
2018-01-03 19:12:40 +02:00
return info1.ModTime().Before(info2.ModTime())
2017-04-24 14:47:10 +02:00
case syntax.TsDevIno:
2018-01-03 19:12:40 +02:00
info1, err1 := r.stat(x)
info2, err2 := r.stat(y)
if err1 != nil || err2 != nil {
return false
}
return os.SameFile(info1, info2)
2017-04-24 14:47:10 +02:00
case syntax.TsEql:
return atoi(x) == atoi(y)
case syntax.TsNeq:
return atoi(x) != atoi(y)
case syntax.TsLeq:
return atoi(x) <= atoi(y)
case syntax.TsGeq:
return atoi(x) >= atoi(y)
case syntax.TsLss:
return atoi(x) < atoi(y)
case syntax.TsGtr:
return atoi(x) > atoi(y)
case syntax.AndTest:
return x != "" && y != ""
case syntax.OrTest:
return x != "" || y != ""
case syntax.TsBefore:
return x < y
default: // syntax.TsAfter
return x > y
}
}
2017-07-06 01:46:05 +02:00
func (r *Runner) statMode(name string, mode os.FileMode) bool {
2018-01-03 19:12:40 +02:00
info, err := r.stat(name)
return err == nil && info.Mode()&mode != 0
2017-04-24 14:47:10 +02:00
}
func (r *Runner) unTest(op syntax.UnTestOperator, x string) bool {
switch op {
case syntax.TsExists:
2018-01-03 19:12:40 +02:00
_, err := r.stat(x)
return err == nil
2017-04-24 14:47:10 +02:00
case syntax.TsRegFile:
2018-01-03 19:12:40 +02:00
info, err := r.stat(x)
return err == nil && info.Mode().IsRegular()
2017-04-24 14:47:10 +02:00
case syntax.TsDirect:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeDir)
2017-11-19 22:26:37 +02:00
case syntax.TsCharSp:
return r.statMode(x, os.ModeCharDevice)
case syntax.TsBlckSp:
2018-01-03 19:12:40 +02:00
info, err := r.stat(x)
return err == nil && info.Mode()&os.ModeDevice != 0 &&
2017-11-19 22:26:37 +02:00
info.Mode()&os.ModeCharDevice == 0
2017-04-24 14:47:10 +02:00
case syntax.TsNmPipe:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeNamedPipe)
2017-04-24 14:47:10 +02:00
case syntax.TsSocket:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeSocket)
2017-04-24 14:47:10 +02:00
case syntax.TsSmbLink:
2018-01-03 19:12:40 +02:00
info, err := os.Lstat(r.relPath(x))
return err == nil && info.Mode()&os.ModeSymlink != 0
2017-04-24 14:47:10 +02:00
case syntax.TsSticky:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeSticky)
2017-04-24 14:47:10 +02:00
case syntax.TsUIDSet:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeSetuid)
2017-04-24 14:47:10 +02:00
case syntax.TsGIDSet:
2017-07-06 01:46:05 +02:00
return r.statMode(x, os.ModeSetgid)
2017-04-24 14:47:10 +02:00
//case syntax.TsGrpOwn:
//case syntax.TsUsrOwn:
//case syntax.TsModif:
case syntax.TsRead:
f, err := r.open(r.relPath(x), os.O_RDONLY, 0, false)
2017-04-24 14:47:10 +02:00
if err == nil {
f.Close()
}
return err == nil
case syntax.TsWrite:
f, err := r.open(r.relPath(x), os.O_WRONLY, 0, false)
2017-04-24 14:47:10 +02:00
if err == nil {
f.Close()
}
return err == nil
case syntax.TsExec:
2017-07-06 01:46:05 +02:00
_, err := exec.LookPath(r.relPath(x))
2017-04-24 14:47:10 +02:00
return err == nil
case syntax.TsNoEmpty:
2018-01-03 19:12:40 +02:00
info, err := r.stat(x)
return err == nil && info.Size() > 0
2017-11-19 22:26:37 +02:00
case syntax.TsFdTerm:
return terminal.IsTerminal(atoi(x))
2017-04-24 14:47:10 +02:00
case syntax.TsEmpStr:
return x == ""
case syntax.TsNempStr:
return x != ""
2017-11-19 22:26:37 +02:00
case syntax.TsOptSet:
2018-04-28 20:35:15 +02:00
if opt := r.optByName(x, false); opt != nil {
2018-01-03 19:12:40 +02:00
return *opt
2017-11-19 22:26:37 +02:00
}
2018-01-03 19:12:40 +02:00
return false
2017-05-27 16:17:49 +02:00
case syntax.TsVarSet:
_, e := r.lookupVar(x)
return e
2017-11-19 22:26:37 +02:00
case syntax.TsRefVar:
v, _ := r.lookupVar(x)
2018-01-03 19:12:40 +02:00
return v.NameRef
2017-04-24 14:47:10 +02:00
case syntax.TsNot:
return x == ""
default:
2018-01-03 19:12:40 +02:00
panic(fmt.Sprintf("unhandled unary test op: %v", op))
2017-04-24 14:47:10 +02:00
}
}