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