package yaml import ( "path/filepath" "github.com/drone/drone/yaml/types" ) // Constraints define constraints for container execution. type Constraints struct { Repo Constraint Ref Constraint Refspec Constraint Platform Constraint Environment Constraint Event Constraint Branch Constraint Status Constraint Matrix ConstraintMap } // Match returns true if all constraints match the given input. If a single constraint // fails a false value is returned. func (c *Constraints) Match(arch, target, event, branch, status string, matrix map[string]string) bool { return c.Platform.Match(arch) && c.Environment.Match(target) && c.Event.Match(event) && c.Branch.Match(branch) && c.Status.Match(status) && c.Matrix.Match(matrix) } // Constraint defines an individual constraint. type Constraint struct { Include []string Exclude []string } // Match returns true if the string matches the include patterns and does not // match any of the exclude patterns. func (c *Constraint) Match(v string) bool { if c.Excludes(v) { return false } if c.Includes(v) { return true } if len(c.Include) == 0 { return true } return false } // Includes returns true if the string matches matches the include patterns. func (c *Constraint) Includes(v string) bool { for _, pattern := range c.Include { if ok, _ := filepath.Match(pattern, v); ok { return true } } return false } // Excludes returns true if the string matches matches the exclude patterns. func (c *Constraint) Excludes(v string) bool { for _, pattern := range c.Exclude { if ok, _ := filepath.Match(pattern, v); ok { return true } } return false } // UnmarshalYAML implements custom Yaml unmarshaling. func (c *Constraint) UnmarshalYAML(unmarshal func(interface{}) error) error { var out1 = struct { Include types.StringOrSlice Exclude types.StringOrSlice }{} var out2 types.StringOrSlice unmarshal(&out1) unmarshal(&out2) c.Exclude = out1.Exclude.Slice() c.Include = append( out1.Include.Slice(), out2.Slice()..., ) return nil } // ConstraintMap defines an individual constraint for key value structures. type ConstraintMap struct { Include map[string]string Exclude map[string]string } // Match returns true if the params matches the include key values and does not // match any of the exclude key values. func (c *ConstraintMap) Match(params map[string]string) bool { // when no includes or excludes automatically match if len(c.Include) == 0 && len(c.Exclude) == 0 { return true } // exclusions are processed first. So we can include everything and then // selectively include others. if len(c.Exclude) != 0 { var matches int for key, val := range c.Exclude { if params[key] == val { matches++ } } if matches == len(c.Exclude) { return false } } for key, val := range c.Include { if params[key] != val { return false } } return true } // UnmarshalYAML implements custom Yaml unmarshaling. func (c *ConstraintMap) UnmarshalYAML(unmarshal func(interface{}) error) error { out1 := struct { Include map[string]string Exclude map[string]string }{ Include: map[string]string{}, Exclude: map[string]string{}, } out2 := map[string]string{} unmarshal(&out1) unmarshal(&out2) c.Include = out1.Include c.Exclude = out1.Exclude for k, v := range out2 { c.Include[k] = v } return nil }