github.com/golang/dep@v0.5.4/gps/pkgtree/ignored_ruleset.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package pkgtree
     6  
     7  import (
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/armon/go-radix"
    12  )
    13  
    14  // IgnoredRuleset comprises a set of rules for ignoring import paths. It can
    15  // manage both literal and prefix-wildcard matches.
    16  type IgnoredRuleset struct {
    17  	t *radix.Tree
    18  }
    19  
    20  // NewIgnoredRuleset processes a set of strings into an IgnoredRuleset. Strings
    21  // that end in "*" are treated as wildcards, where any import path with a
    22  // matching prefix will be ignored. IgnoredRulesets are immutable once created.
    23  //
    24  // Duplicate and redundant (i.e. a literal path that has a prefix of a wildcard
    25  // path) declarations are discarded. Consequently, it is possible that the
    26  // returned IgnoredRuleset may have a smaller Len() than the input slice.
    27  func NewIgnoredRuleset(ig []string) *IgnoredRuleset {
    28  	if len(ig) == 0 {
    29  		return &IgnoredRuleset{}
    30  	}
    31  
    32  	ir := &IgnoredRuleset{
    33  		t: radix.New(),
    34  	}
    35  
    36  	// Sort the list of all the ignores in order to ensure that wildcard
    37  	// precedence is recorded correctly in the trie.
    38  	sort.Strings(ig)
    39  	for _, i := range ig {
    40  		// Skip global ignore and empty string.
    41  		if i == "*" || i == "" {
    42  			continue
    43  		}
    44  
    45  		_, wildi, has := ir.t.LongestPrefix(i)
    46  		// We may not always have a value here, but if we do, then it's a bool.
    47  		wild, _ := wildi.(bool)
    48  		// Check if it's a wildcard ignore.
    49  		if strings.HasSuffix(i, "*") {
    50  			// Check if it is ineffectual.
    51  			if has && wild {
    52  				// Skip ineffectual wildcard ignore.
    53  				continue
    54  			}
    55  			// Create the ignore prefix and insert in the radix tree.
    56  			ir.t.Insert(i[:len(i)-1], true)
    57  		} else if !has || !wild {
    58  			ir.t.Insert(i, false)
    59  		}
    60  	}
    61  
    62  	if ir.t.Len() == 0 {
    63  		ir.t = nil
    64  	}
    65  
    66  	return ir
    67  }
    68  
    69  // IsIgnored indicates whether the provided path should be ignored, according to
    70  // the ruleset.
    71  func (ir *IgnoredRuleset) IsIgnored(path string) bool {
    72  	if path == "" || ir == nil || ir.t == nil {
    73  		return false
    74  	}
    75  
    76  	prefix, wildi, has := ir.t.LongestPrefix(path)
    77  	return has && (wildi.(bool) || path == prefix)
    78  }
    79  
    80  // Len indicates the number of rules in the ruleset.
    81  func (ir *IgnoredRuleset) Len() int {
    82  	if ir == nil || ir.t == nil {
    83  		return 0
    84  	}
    85  
    86  	return ir.t.Len()
    87  }
    88  
    89  // ToSlice converts the contents of the IgnoredRuleset to a string slice.
    90  //
    91  // This operation is symmetrically dual to NewIgnoredRuleset.
    92  func (ir *IgnoredRuleset) ToSlice() []string {
    93  	irlen := ir.Len()
    94  	if irlen == 0 {
    95  		return nil
    96  	}
    97  
    98  	items := make([]string, 0, irlen)
    99  	ir.t.Walk(func(s string, v interface{}) bool {
   100  		if s != "" {
   101  			if v.(bool) {
   102  				items = append(items, s+"*")
   103  			} else {
   104  				items = append(items, s)
   105  			}
   106  		}
   107  		return false
   108  	})
   109  
   110  	return items
   111  }