1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.attributes;
44
45 import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH;
46
47 import java.util.ArrayList;
48 import java.util.Collections;
49 import java.util.List;
50
51 import org.eclipse.jgit.attributes.Attribute.State;
52 import org.eclipse.jgit.errors.InvalidPatternException;
53 import org.eclipse.jgit.ignore.FastIgnoreRule;
54 import org.eclipse.jgit.ignore.internal.IMatcher;
55 import org.eclipse.jgit.ignore.internal.PathMatcher;
56
57
58
59
60
61
62
63
64 public class AttributesRule {
65
66
67
68
69
70 private static final String ATTRIBUTES_SPLIT_REGEX = "[ \t\r]";
71
72 private static List<Attribute> parseAttributes(String attributesLine) {
73
74 ArrayList<Attribute> result = new ArrayList<>();
75 for (String attribute : attributesLine.split(ATTRIBUTES_SPLIT_REGEX)) {
76 attribute = attribute.trim();
77 if (attribute.length() == 0)
78 continue;
79
80 if (attribute.startsWith("-")) {
81 if (attribute.length() > 1)
82 result.add(new Attribute(attribute.substring(1),
83 State.UNSET));
84 continue;
85 }
86
87 if (attribute.startsWith("!")) {
88 if (attribute.length() > 1)
89 result.add(new Attribute(attribute.substring(1),
90 State.UNSPECIFIED));
91 continue;
92 }
93
94 final int equalsIndex = attribute.indexOf("=");
95 if (equalsIndex == -1)
96 result.add(new Attribute(attribute, State.SET));
97 else {
98 String attributeKey = attribute.substring(0, equalsIndex);
99 if (attributeKey.length() > 0) {
100 String attributeValue = attribute
101 .substring(equalsIndex + 1);
102 result.add(new Attribute(attributeKey, attributeValue));
103 }
104 }
105 }
106 return result;
107 }
108
109 private final String pattern;
110 private final List<Attribute> attributes;
111
112 private final boolean nameOnly;
113
114 private final boolean dirOnly;
115
116 private final IMatcher matcher;
117
118
119
120
121
122
123
124
125
126
127
128
129
130 public AttributesRule(String pattern, String attributes) {
131 this.attributes = parseAttributes(attributes);
132
133 if (pattern.endsWith("/")) {
134 pattern = pattern.substring(0, pattern.length() - 1);
135 dirOnly = true;
136 } else {
137 dirOnly = false;
138 }
139
140 int slashIndex = pattern.indexOf('/');
141
142 if (slashIndex < 0) {
143 nameOnly = true;
144 } else if (slashIndex == 0) {
145 nameOnly = false;
146 } else {
147 nameOnly = false;
148
149
150 pattern = "/" + pattern;
151 }
152
153 IMatcher candidateMatcher = NO_MATCH;
154 try {
155 candidateMatcher = PathMatcher.createPathMatcher(pattern,
156 Character.valueOf(FastIgnoreRule.PATH_SEPARATOR), dirOnly);
157 } catch (InvalidPatternException e) {
158
159 }
160 this.matcher = candidateMatcher;
161 this.pattern = pattern;
162 }
163
164
165
166
167
168
169
170 public boolean isDirOnly() {
171 return dirOnly;
172 }
173
174
175
176
177
178
179
180 public List<Attribute> getAttributes() {
181 return Collections.unmodifiableList(attributes);
182 }
183
184
185
186
187
188
189
190 public boolean isNameOnly() {
191 return nameOnly;
192 }
193
194
195
196
197
198
199
200 public String getPattern() {
201 return pattern;
202 }
203
204
205
206
207
208
209
210
211
212
213
214 public boolean isMatch(String relativeTarget, boolean isDirectory) {
215 if (relativeTarget == null)
216 return false;
217 if (relativeTarget.length() == 0)
218 return false;
219 boolean match = matcher.matches(relativeTarget, isDirectory, true);
220 return match;
221 }
222
223
224 @Override
225 public String toString() {
226 StringBuilder sb = new StringBuilder();
227 sb.append(pattern);
228 for (Attribute a : attributes) {
229 sb.append(" ");
230 sb.append(a);
231 }
232 return sb.toString();
233
234 }
235 }