| | |
| | |
| | |
| |
|
| | package script |
| |
|
| | import ( |
| | "fmt" |
| | "internal/syslist" |
| | "os" |
| | "runtime" |
| | "sync" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | func DefaultConds() map[string]Cond { |
| | conds := make(map[string]Cond) |
| |
|
| | conds["GOOS"] = PrefixCondition( |
| | "runtime.GOOS == <suffix>", |
| | func(_ *State, suffix string) (bool, error) { |
| | if suffix == runtime.GOOS { |
| | return true, nil |
| | } |
| | if _, ok := syslist.KnownOS[suffix]; !ok { |
| | return false, fmt.Errorf("unrecognized GOOS %q", suffix) |
| | } |
| | return false, nil |
| | }) |
| |
|
| | conds["GOARCH"] = PrefixCondition( |
| | "runtime.GOARCH == <suffix>", |
| | func(_ *State, suffix string) (bool, error) { |
| | if suffix == runtime.GOARCH { |
| | return true, nil |
| | } |
| | if _, ok := syslist.KnownArch[suffix]; !ok { |
| | return false, fmt.Errorf("unrecognized GOOS %q", suffix) |
| | } |
| | return false, nil |
| | }) |
| |
|
| | conds["compiler"] = PrefixCondition( |
| | "runtime.Compiler == <suffix>", |
| | func(_ *State, suffix string) (bool, error) { |
| | if suffix == runtime.Compiler { |
| | return true, nil |
| | } |
| | switch suffix { |
| | case "gc", "gccgo": |
| | return false, nil |
| | default: |
| | return false, fmt.Errorf("unrecognized compiler %q", suffix) |
| | } |
| | }) |
| |
|
| | conds["root"] = BoolCondition("os.Geteuid() == 0", os.Geteuid() == 0) |
| |
|
| | return conds |
| | } |
| |
|
| | |
| | func Condition(summary string, eval func(*State) (bool, error)) Cond { |
| | return &funcCond{eval: eval, usage: CondUsage{Summary: summary}} |
| | } |
| |
|
| | type funcCond struct { |
| | eval func(*State) (bool, error) |
| | usage CondUsage |
| | } |
| |
|
| | func (c *funcCond) Usage() *CondUsage { return &c.usage } |
| |
|
| | func (c *funcCond) Eval(s *State, suffix string) (bool, error) { |
| | if suffix != "" { |
| | return false, ErrUsage |
| | } |
| | return c.eval(s) |
| | } |
| |
|
| | |
| | func PrefixCondition(summary string, eval func(*State, string) (bool, error)) Cond { |
| | return &prefixCond{eval: eval, usage: CondUsage{Summary: summary, Prefix: true}} |
| | } |
| |
|
| | type prefixCond struct { |
| | eval func(*State, string) (bool, error) |
| | usage CondUsage |
| | } |
| |
|
| | func (c *prefixCond) Usage() *CondUsage { return &c.usage } |
| |
|
| | func (c *prefixCond) Eval(s *State, suffix string) (bool, error) { |
| | return c.eval(s, suffix) |
| | } |
| |
|
| | |
| | |
| | func BoolCondition(summary string, v bool) Cond { |
| | return &boolCond{v: v, usage: CondUsage{Summary: summary}} |
| | } |
| |
|
| | type boolCond struct { |
| | v bool |
| | usage CondUsage |
| | } |
| |
|
| | func (b *boolCond) Usage() *CondUsage { return &b.usage } |
| |
|
| | func (b *boolCond) Eval(s *State, suffix string) (bool, error) { |
| | if suffix != "" { |
| | return false, ErrUsage |
| | } |
| | return b.v, nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | func OnceCondition(summary string, eval func() (bool, error)) Cond { |
| | return &onceCond{ |
| | eval: sync.OnceValues(eval), |
| | usage: CondUsage{Summary: summary}, |
| | } |
| | } |
| |
|
| | type onceCond struct { |
| | eval func() (bool, error) |
| | usage CondUsage |
| | } |
| |
|
| | func (l *onceCond) Usage() *CondUsage { return &l.usage } |
| |
|
| | func (l *onceCond) Eval(s *State, suffix string) (bool, error) { |
| | if suffix != "" { |
| | return false, ErrUsage |
| | } |
| | return l.eval() |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | func CachedCondition(summary string, eval func(string) (bool, error)) Cond { |
| | return &cachedCond{eval: eval, usage: CondUsage{Summary: summary, Prefix: true}} |
| | } |
| |
|
| | type cachedCond struct { |
| | m sync.Map |
| | eval func(string) (bool, error) |
| | usage CondUsage |
| | } |
| |
|
| | func (c *cachedCond) Usage() *CondUsage { return &c.usage } |
| |
|
| | func (c *cachedCond) Eval(_ *State, suffix string) (bool, error) { |
| | for { |
| | var ready chan struct{} |
| |
|
| | v, loaded := c.m.Load(suffix) |
| | if !loaded { |
| | ready = make(chan struct{}) |
| | v, loaded = c.m.LoadOrStore(suffix, (<-chan struct{})(ready)) |
| |
|
| | if !loaded { |
| | inPanic := true |
| | defer func() { |
| | if inPanic { |
| | c.m.Delete(suffix) |
| | } |
| | close(ready) |
| | }() |
| |
|
| | b, err := c.eval(suffix) |
| | inPanic = false |
| |
|
| | if err == nil { |
| | c.m.Store(suffix, b) |
| | return b, nil |
| | } else { |
| | c.m.Store(suffix, err) |
| | return false, err |
| | } |
| | } |
| | } |
| |
|
| | switch v := v.(type) { |
| | case bool: |
| | return v, nil |
| | case error: |
| | return false, v |
| | case <-chan struct{}: |
| | <-v |
| | } |
| | } |
| | } |
| |
|