14
14
15
15
package com .google .devtools .build .lib .cmdline ;
16
16
17
+ import static com .google .common .collect .ImmutableList .toImmutableList ;
17
18
import static com .google .common .collect .ImmutableSet .toImmutableSet ;
18
19
19
20
import com .google .common .base .MoreObjects ;
20
21
import com .google .common .base .Preconditions ;
22
+ import com .google .common .base .Splitter ;
23
+ import com .google .common .collect .ImmutableList ;
21
24
import com .google .common .collect .ImmutableSet ;
25
+ import com .google .common .collect .Iterables ;
26
+ import com .google .devtools .build .lib .skyframe .serialization .DeserializationContext ;
27
+ import com .google .devtools .build .lib .skyframe .serialization .ObjectCodec ;
28
+ import com .google .devtools .build .lib .skyframe .serialization .SerializationContext ;
29
+ import com .google .devtools .build .lib .skyframe .serialization .SerializationException ;
22
30
import com .google .devtools .build .lib .vfs .PathFragment ;
31
+ import com .google .devtools .build .lib .vfs .UnixGlob ;
32
+ import com .google .protobuf .CodedInputStream ;
33
+ import com .google .protobuf .CodedOutputStream ;
34
+ import java .io .IOException ;
23
35
import java .util .Objects ;
24
36
import javax .annotation .Nullable ;
25
37
26
38
/**
27
39
* A set of subdirectories to ignore during target pattern matching or globbing.
28
- *
29
- * <p>This is currently just a prefix, but will eventually support glob-style wildcards.
30
40
*/
31
41
public final class IgnoredSubdirectories {
32
- public static final IgnoredSubdirectories EMPTY = new IgnoredSubdirectories (ImmutableSet .of ());
42
+ public static final IgnoredSubdirectories EMPTY =
43
+ new IgnoredSubdirectories (ImmutableSet .of (), ImmutableList .of ());
44
+
45
+ private static final Splitter SLASH_SPLITTER = Splitter .on ("/" );
33
46
34
47
private final ImmutableSet <PathFragment > prefixes ;
35
48
36
- private IgnoredSubdirectories (ImmutableSet <PathFragment > prefixes ) {
37
- for (PathFragment prefix : prefixes ) {
38
- Preconditions .checkArgument (!prefix .isAbsolute ());
49
+ // String[] is mutable; we keep the split version because that's faster to match and the non-split
50
+ // one because that allows for simpler equality checking and then matchingEntry() doesn't need to
51
+ // allocate new objects.
52
+ private final ImmutableList <String > patterns ;
53
+ private final ImmutableList <String []> splitPatterns ;
54
+
55
+ private static class Codec implements ObjectCodec <IgnoredSubdirectories > {
56
+ private static final Codec INSTANCE = new Codec ();
57
+
58
+ @ Override
59
+ public Class <? extends IgnoredSubdirectories > getEncodedClass () {
60
+ return IgnoredSubdirectories .class ;
61
+ }
62
+
63
+ @ Override
64
+ public void serialize (
65
+ SerializationContext context , IgnoredSubdirectories obj , CodedOutputStream codedOut )
66
+ throws SerializationException , IOException {
67
+ context .serialize (obj .prefixes , codedOut );
68
+ context .serialize (obj .patterns , codedOut );
39
69
}
70
+
71
+ @ Override
72
+ public IgnoredSubdirectories deserialize (
73
+ DeserializationContext context , CodedInputStream codedIn )
74
+ throws SerializationException , IOException {
75
+ ImmutableSet <PathFragment > prefixes = context .deserialize (codedIn );
76
+ ImmutableList <String > patterns = context .deserialize (codedIn );
77
+
78
+ return new IgnoredSubdirectories (prefixes , patterns );
79
+ }
80
+ }
81
+
82
+ private IgnoredSubdirectories (
83
+ ImmutableSet <PathFragment > prefixes , ImmutableList <String > patterns ) {
40
84
this .prefixes = prefixes ;
85
+ this .patterns = patterns ;
86
+ this .splitPatterns =
87
+ patterns .stream ()
88
+ .map (p -> Iterables .toArray (SLASH_SPLITTER .split (p ), String .class ))
89
+ .collect (toImmutableList ());
41
90
}
42
91
43
92
public static IgnoredSubdirectories of (ImmutableSet <PathFragment > prefixes ) {
44
- if (prefixes .isEmpty ()) {
93
+ return of (prefixes , ImmutableList .of ());
94
+ }
95
+
96
+ public static IgnoredSubdirectories of (
97
+ ImmutableSet <PathFragment > prefixes , ImmutableList <String > patterns ) {
98
+ if (prefixes .isEmpty () && patterns .isEmpty ()) {
45
99
return EMPTY ;
46
- } else {
47
- return new IgnoredSubdirectories (prefixes );
48
100
}
101
+
102
+ for (PathFragment prefix : prefixes ) {
103
+ Preconditions .checkArgument (!prefix .isAbsolute ());
104
+ }
105
+
106
+ return new IgnoredSubdirectories (prefixes , patterns );
49
107
}
50
108
51
109
public IgnoredSubdirectories withPrefix (PathFragment prefix ) {
52
- ImmutableSet <PathFragment > prefixed =
110
+ Preconditions .checkArgument (!prefix .isAbsolute ());
111
+
112
+ ImmutableSet <PathFragment > prefixedPrefixes =
53
113
prefixes .stream ().map (prefix ::getRelative ).collect (toImmutableSet ());
54
- return new IgnoredSubdirectories (prefixed );
114
+
115
+ ImmutableList <String > prefixedPatterns =
116
+ patterns .stream ().map (p -> prefix + "/" + p ).collect (toImmutableList ());
117
+
118
+ return new IgnoredSubdirectories (prefixedPrefixes , prefixedPatterns );
55
119
}
56
120
57
121
public IgnoredSubdirectories union (IgnoredSubdirectories other ) {
58
122
return new IgnoredSubdirectories (
59
- ImmutableSet .<PathFragment >builder ().addAll (prefixes ).addAll (other .prefixes ).build ());
123
+ ImmutableSet .<PathFragment >builder ().addAll (prefixes ).addAll (other .prefixes ).build (),
124
+ ImmutableList .copyOf (
125
+ ImmutableSet .<String >builder ().addAll (patterns ).addAll (other .patterns ).build ()));
60
126
}
61
127
62
128
/** Filters out entries that cannot match anything under {@code directory}. */
63
129
public IgnoredSubdirectories filterForDirectory (PathFragment directory ) {
64
130
ImmutableSet <PathFragment > filteredPrefixes =
65
131
prefixes .stream ().filter (p -> p .startsWith (directory )).collect (toImmutableSet ());
66
132
67
- return new IgnoredSubdirectories (filteredPrefixes );
133
+ String [] splitDirectory =
134
+ Iterables .toArray (SLASH_SPLITTER .split (directory .getPathString ()), String .class );
135
+ ImmutableList .Builder <String > filteredPatterns = ImmutableList .builder ();
136
+ for (int i = 0 ; i < patterns .size (); i ++) {
137
+ if (UnixGlob .canMatchChild (splitPatterns .get (i ), splitDirectory )) {
138
+ filteredPatterns .add (patterns .get (i ));
139
+ }
140
+ }
141
+
142
+ return new IgnoredSubdirectories (filteredPrefixes , filteredPatterns .build ());
68
143
}
69
144
70
145
public ImmutableSet <PathFragment > prefixes () {
@@ -95,10 +170,17 @@ public boolean allPathsAreUnder(PathFragment directory) {
95
170
96
171
/** Returns the entry that matches a given directory or {@code null} if none. */
97
172
@ Nullable
98
- public PathFragment matchingEntry (PathFragment directory ) {
173
+ public String matchingEntry (PathFragment directory ) {
99
174
for (PathFragment prefix : prefixes ) {
100
175
if (directory .startsWith (prefix )) {
101
- return prefix ;
176
+ return prefix .getPathString ();
177
+ }
178
+ }
179
+
180
+ String [] segmentArray = Iterables .toArray (directory .segments (), String .class );
181
+ for (int i = 0 ; i < patterns .size (); i ++) {
182
+ if (UnixGlob .matchesPrefix (splitPatterns .get (i ), segmentArray )) {
183
+ return patterns .get (i );
102
184
}
103
185
}
104
186
@@ -111,17 +193,22 @@ public boolean equals(Object other) {
111
193
return false ;
112
194
}
113
195
196
+ // splitPatterns is a function of patterns so it's enough to check if patterns is equal
114
197
IgnoredSubdirectories that = (IgnoredSubdirectories ) other ;
115
- return Objects .equals (this .prefixes , that .prefixes );
198
+ return Objects .equals (this .prefixes , that .prefixes )
199
+ && Objects .equals (this .patterns , that .patterns );
116
200
}
117
201
118
202
@ Override
119
203
public int hashCode () {
120
- return prefixes . hashCode ( );
204
+ return Objects . hash ( prefixes , patterns );
121
205
}
122
206
123
207
@ Override
124
208
public String toString () {
125
- return MoreObjects .toStringHelper ("IgnoredSubdirectories" ).add ("prefixes" , prefixes ).toString ();
209
+ return MoreObjects .toStringHelper ("IgnoredSubdirectories" )
210
+ .add ("prefixes" , prefixes )
211
+ .add ("patterns" , patterns )
212
+ .toString ();
126
213
}
127
214
}
0 commit comments