go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/vpython/spec/match.go (about)

     1  // Copyright 2017 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package spec
    16  
    17  import (
    18  	"go.chromium.org/luci/vpython/api/vpython"
    19  )
    20  
    21  // PackageMatches returns true if the package's match constraints are compatible
    22  // with tags. A package matches if:
    23  //
    24  //   - None of the tags matches any of the "not_match_tag" entries, and
    25  //   - Every "match_tag" entry matches at least one tag.
    26  //
    27  // As a special case, if the package doesn't specify any match tags, it will
    28  // always match regardless of the supplied PEP425 tags. This handles the default
    29  // case where the user specifies no constraints.
    30  //
    31  // See PEP425Matches for information about how tags are matched.
    32  func PackageMatches(pkg *vpython.Spec_Package, tags []*vpython.PEP425Tag) bool {
    33  	// If any "not_match_tag" matches, then this package does not match.
    34  	for _, matchTag := range pkg.NotMatchTag {
    35  		if PEP425Matches(matchTag, tags) {
    36  			return false
    37  		}
    38  	}
    39  
    40  	// If we have no match tags, or if a match tag matches a host tag, then the
    41  	// package matches.
    42  	if len(pkg.MatchTag) == 0 {
    43  		return true
    44  	}
    45  	for _, matchTag := range pkg.MatchTag {
    46  		if PEP425Matches(matchTag, tags) {
    47  			return true
    48  		}
    49  	}
    50  	return false
    51  }
    52  
    53  // PEP425Matches returns true if match matches at least one of the tags in tags.
    54  //
    55  // A match is determined if the non-zero fields in match equal the equivalent
    56  // fields in a tag.
    57  func PEP425Matches(match *vpython.PEP425Tag, tags []*vpython.PEP425Tag) bool {
    58  	// Special case: empty match matches nothing.
    59  	if match.IsZero() {
    60  		return false
    61  	}
    62  
    63  	for _, tag := range tags {
    64  		if v := match.Python; v != "" && tag.Python != v {
    65  			continue
    66  		}
    67  		if v := match.Abi; v != "" && tag.Abi != v {
    68  			continue
    69  		}
    70  		if v := match.Platform; v != "" && tag.Platform != v {
    71  			continue
    72  		}
    73  		return true
    74  	}
    75  
    76  	return false
    77  }