prow/config/tide.go
func (tq *TideQuery) Validate() error {
	duplicates := func(field string, list []string) error {
		dups := sets.NewString()
		seen := sets.NewString()
		for _, elem := range list {
			if seen.Has(elem) {
				dups.Insert(elem)
			} else {
				seen.Insert(elem)
			}
		}
		dupCount := len(list) - seen.Len()
		if dupCount == 0 {
			return nil
		}
		return fmt.Errorf("%q contains %d duplicate entries: %s", field, dupCount, strings.Join(dups.List(), ", "))
	}

	orgs := sets.NewString()
	for o := range tq.Orgs {
		if strings.Contains(tq.Orgs[o], "/") {
			return fmt.Errorf("orgs[%d]: %q contains a '/' which is not valid", o, tq.Orgs[o])
		}
		if len(tq.Orgs[o]) == 0 {
			return fmt.Errorf("orgs[%d]: is an empty string", o)
		}
		orgs.Insert(tq.Orgs[o])
	}
	if err := duplicates("orgs", tq.Orgs); err != nil {
		return err
	}

	for r := range tq.Repos {
		parts := strings.Split(tq.Repos[r], "/")
		if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
			return fmt.Errorf("repos[%d]: %q is not of the form \"org/repo\"", r, tq.Repos[r])
		}
		if orgs.Has(parts[0]) {
			return fmt.Errorf("repos[%d]: %q is already included via org: %q", r, tq.Repos[r], parts[0])
		}
	}
	if err := duplicates("repos", tq.Repos); err != nil {
		return err
	}

	if len(tq.Orgs) == 0 && len(tq.Repos) == 0 {
		return errors.New("'orgs' and 'repos' cannot both be empty")
	}

	for er := range tq.ExcludedRepos {
		parts := strings.Split(tq.ExcludedRepos[er], "/")
		if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
			return fmt.Errorf("excludedRepos[%d]: %q is not of the form \"org/repo\"", er, tq.ExcludedRepos[er])
		}
		if !orgs.Has(parts[0]) {
			return fmt.Errorf("excludedRepos[%d]: %q has no effect because org %q is not included", er, tq.ExcludedRepos[er], parts[0])
		}
		// Note: At this point we also know that this excludedRepo is not found in 'repos'.
	}
	if err := duplicates("excludedRepos", tq.ExcludedRepos); err != nil {
		return err
	}

	if invalids := sets.NewString(tq.Labels...).Intersection(sets.NewString(tq.MissingLabels...)); len(invalids) > 0 {
		return fmt.Errorf("the labels: %q are both required and forbidden", invalids.List())
	}
	if err := duplicates("labels", tq.Labels); err != nil {
		return err
	}
	if err := duplicates("missingLabels", tq.MissingLabels); err != nil {
		return err
	}

	if len(tq.ExcludedBranches) > 0 && len(tq.IncludedBranches) > 0 {
		return errors.New("both 'includedBranches' and 'excludedBranches' are specified ('excludedBranches' have no effect)")
	}
	if err := duplicates("includedBranches", tq.IncludedBranches); err != nil {
		return err
	}
	if err := duplicates("excludedBranches", tq.ExcludedBranches); err != nil {
		return err
	}

	return nil
}
func (tq *TideQuery) Validate() error {
	duplicates := func(field string, list []string) error {
		dups := sets.NewString()
		seen := sets.NewString()
		for _, elem := range list {
			if seen.Has(elem) {
				dups.Insert(elem)
			} else {
				seen.Insert(elem)
			}
		}
		dupCount := len(list) - seen.Len()
		if dupCount == 0 {
			return nil
		}
		return fmt.Errorf("%q contains %d duplicate entries: %s", field, dupCount, strings.Join(dups.List(), ", "))
	}

	orgs := sets.NewString()
	for o := range tq.Orgs {
		if strings.Contains(tq.Orgs[o], "/") {
			return fmt.Errorf("orgs[%d]: %q contains a '/' which is not valid", o, tq.Orgs[o])
		}
		if len(tq.Orgs[o]) == 0 {
			return fmt.Errorf("orgs[%d]: is an empty string", o)
		}
		orgs.Insert(tq.Orgs[o])
	}
	if err := duplicates("orgs", tq.Orgs); err != nil {
		return err
	}

	for r := range tq.Repos {
		parts := strings.Split(tq.Repos[r], "/")
		if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
			return fmt.Errorf("repos[%d]: %q is not of the form \"org/repo\"", r, tq.Repos[r])
		}
		if orgs.Has(parts[0]) {
			return fmt.Errorf("repos[%d]: %q is already included via org: %q", r, tq.Repos[r], parts[0])
		}
	}
	if err := duplicates("repos", tq.Repos); err != nil {
		return err
	}

	if len(tq.Orgs) == 0 && len(tq.Repos) == 0 {
		return errors.New("'orgs' and 'repos' cannot both be empty")
	}

	for er := range tq.ExcludedRepos {
		parts := strings.Split(tq.ExcludedRepos[er], "/")
		if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
			return fmt.Errorf("excludedRepos[%d]: %q is not of the form \"org/repo\"", er, tq.ExcludedRepos[er])
		}
		if !orgs.Has(parts[0]) {
			return fmt.Errorf("excludedRepos[%d]: %q has no effect because org %q is not included", er, tq.ExcludedRepos[er], parts[0])
		}
		// Note: At this point we also know that this excludedRepo is not found in 'repos'.
	}
	if err := duplicates("excludedRepos", tq.ExcludedRepos); err != nil {
		return err
	}

	if invalids := sets.NewString(tq.Labels...).Intersection(sets.NewString(tq.MissingLabels...)); len(invalids) > 0 {
		return fmt.Errorf("the labels: %q are both required and forbidden", invalids.List())
	}
	if err := duplicates("labels", tq.Labels); err != nil {
		return err
	}
	if err := duplicates("missingLabels", tq.MissingLabels); err != nil {
		return err
	}

	if len(tq.ExcludedBranches) > 0 && len(tq.IncludedBranches) > 0 {
		return errors.New("both 'includedBranches' and 'excludedBranches' are specified ('excludedBranches' have no effect)")
	}
	if err := duplicates("includedBranches", tq.IncludedBranches); err != nil {
		return err
	}
	if err := duplicates("excludedBranches", tq.ExcludedBranches); err != nil {
		return err
	}

	return nil
}
func ( tq * TideQuery ) Validate ( ) error { duplicates := func ( field string , list [ ] string ) error { dups := sets . NewString ( ) seen := sets . NewString ( ) for _ , elem := range list { if seen . Has ( elem ) { dups . Insert ( elem ) } else { seen . Insert ( elem ) } } dupCount := len ( list ) - seen . Len ( ) if dupCount == 0 { return nil } return fmt . Errorf ( " " , field , dupCount , strings . Join ( dups . List ( ) , " " ) ) } orgs := sets . NewString ( ) for o := range tq . Orgs { if strings . Contains ( tq . Orgs [ o ] , " " ) { return fmt . Errorf ( " " , o , tq . Orgs [ o ] ) } if len ( tq . Orgs [ o ] ) == 0 { return fmt . Errorf ( " " , o ) } orgs . Insert ( tq . Orgs [ o ] ) } if err := duplicates ( " " , tq . Orgs ) ; err != nil { return err } for r := range tq . Repos { parts := strings . Split ( tq . Repos [ r ] , " " ) if len ( parts ) != 2 || len ( parts [ 0 ] ) == 0 || len ( parts [ 1 ] ) == 0 { return fmt . Errorf ( " \" \" " , r , tq . Repos [ r ] ) } if orgs . Has ( parts [ 0 ] ) { return fmt . Errorf ( " " , r , tq . Repos [ r ] , parts [ 0 ] ) } } if err := duplicates ( " " , tq . Repos ) ; err != nil { return err } if len ( tq . Orgs ) == 0 && len ( tq . Repos ) == 0 { return errors . New ( " " ) } for er := range tq . ExcludedRepos { parts := strings . Split ( tq . ExcludedRepos [ er ] , " " ) if len ( parts ) != 2 || len ( parts [ 0 ] ) == 0 || len ( parts [ 1 ] ) == 0 { return fmt . Errorf ( " \" \" " , er , tq . ExcludedRepos [ er ] ) } if ! orgs . Has ( parts [ 0 ] ) { return fmt . Errorf ( " " , er , tq . ExcludedRepos [ er ] , parts [ 0 ] ) } // Note: At this point we also know that this excludedRepo is not found in 'repos'. } if err := duplicates ( " " , tq . ExcludedRepos ) ; err != nil { return err } if invalids := sets . NewString ( tq . Labels ... ) . Intersection ( sets . NewString ( tq . MissingLabels ... ) ) ; len ( invalids ) > 0 { return fmt . Errorf ( " " , invalids . List ( ) ) } if err := duplicates ( " " , tq . Labels ) ; err != nil { return err } if err := duplicates ( " " , tq . MissingLabels ) ; err != nil { return err } if len ( tq . ExcludedBranches ) > 0 && len ( tq . IncludedBranches ) > 0 { return errors . New ( " " ) } if err := duplicates ( " " , tq . IncludedBranches ) ; err != nil { return err } if err := duplicates ( " " , tq . ExcludedBranches ) ; err != nil { return err } return nil }
// Validate returns an error if the query has any errors.
//
// Examples include:
// * an org name that is empty or includes a /
// * repos that are not org/repo
// * a label that is in both the labels and missing_labels section
// * a branch that is in both included and excluded branch set.
Validate returns an error if the query has any errors . Examples include : * an org name that is empty or includes a / * repos that are not org / repo * a label that is in both the labels and missing_labels section * a branch that is in both included and excluded branch set .