WildCardMatcher(String pattern, Character pathSeparator, boolean dirOnly) throws InvalidPatternException { super(pattern, pathSeparator, dirOnly, false); p = convertGlob(subPattern); }
/** {@inheritDoc} */ @Override public final boolean matches(String path, boolean assumeDirectory, boolean pathMatch) { return !dirOnly || assumeDirectory || !pathMatch && isSubdirectory(path); }
private PathMatcher(String pattern, Character pathSeparator, boolean dirOnly) throws InvalidPatternException { super(pattern, dirOnly); slash = getPathSeparator(pathSeparator); beginning = pattern.indexOf(slash) == 0; if (isSimplePathWithSegments(pattern)) matchers = null; else matchers = createMatchers(split(pattern, slash), pathSeparator, dirOnly); }
private static IMatcher createNameMatcher0(String segment, Character pathSeparator, boolean dirOnly, boolean lastSegment) throws InvalidPatternException { // check if we see /** or ** segments => double star pattern if (WildMatcher.WILDMATCH.equals(segment) || WildMatcher.WILDMATCH2.equals(segment)) return dirOnly && lastSegment ? WILD_ONLY_DIRECTORY : WILD_NO_DIRECTORY; PatternState state = checkWildCards(segment); switch (state) { case LEADING_ASTERISK_ONLY: return new LeadingAsteriskMatcher(segment, pathSeparator, dirOnly); case TRAILING_ASTERISK_ONLY: return new TrailingAsteriskMatcher(segment, pathSeparator, dirOnly); case COMPLEX: return new WildCardMatcher(segment, pathSeparator, dirOnly); default: return new NameMatcher(segment, pathSeparator, dirOnly, true); } }
/** * Create path matcher * * @param pattern * a pattern * @param pathSeparator * if this parameter isn't null then this character will not * match at wildcards(* and ? are wildcards). * @param dirOnly * a boolean. * @return never null * @throws org.eclipse.jgit.errors.InvalidPatternException */ public static IMatcher createPathMatcher(String pattern, Character pathSeparator, boolean dirOnly) throws InvalidPatternException { pattern = trim(pattern); char slash = Strings.getPathSeparator(pathSeparator); // ignore possible leading and trailing slash int slashIdx = pattern.indexOf(slash, 1); if (slashIdx > 0 && slashIdx < pattern.length() - 1) return new PathMatcher(pattern, pathSeparator, dirOnly); return createNameMatcher0(pattern, pathSeparator, dirOnly, true); }
dirOnly = isDirectoryPattern(pattern); if (dirOnly) { pattern = stripTrailingWhitespace(pattern); pattern = stripTrailing(pattern, PATH_SEPARATOR); if (pattern.length() == 0) { this.matcher = NO_MATCH; m = PathMatcher.createPathMatcher(pattern, Character.valueOf(PATH_SEPARATOR), dirOnly); } catch (InvalidPatternException e) {
/** * Returns <code>true</code> if a match was made. * * @param relativeTarget * Name pattern of the file, relative to the base directory of * this rule * @param isDirectory * Whether the target file is a directory or not * @return True if a match was made. */ public boolean isMatch(String relativeTarget, boolean isDirectory) { if (relativeTarget == null) return false; if (relativeTarget.length() == 0) return false; boolean match = matcher.matches(relativeTarget, isDirectory, true); return match; }
/** {@inheritDoc} */ @Override public boolean matches(String path, boolean assumeDirectory, boolean pathMatch) { if (matchers == null) { return simpleMatch(path, assumeDirectory, pathMatch); } return iterate(path, 0, path.length(), assumeDirectory, pathMatch); }
private boolean isSimplePathWithSegments(String path) { return !isWildCard(path) && path.indexOf('\\') < 0 && count(path, slash, true) > 0; }
NameMatcher(String pattern, Character pathSeparator, boolean dirOnly, boolean deleteBackslash) { super(pattern, dirOnly); slash = getPathSeparator(pathSeparator); if (deleteBackslash) { pattern = Strings.deleteBackslash(pattern); } beginning = pattern.length() == 0 ? false : pattern.charAt(0) == slash; if (!beginning) { this.subPattern = pattern; } else { this.subPattern = pattern.substring(1); } }
private static List<IMatcher> createMatchers(List<String> segments, Character pathSeparator, boolean dirOnly) throws InvalidPatternException { List<IMatcher> matchers = new ArrayList<>(segments.size()); for (int i = 0; i < segments.size(); i++) { String segment = segments.get(i); IMatcher matcher = createNameMatcher0(segment, pathSeparator, dirOnly, i == segments.size() - 1); if (i > 0) { final IMatcher last = matchers.get(matchers.size() - 1); if (isWild(matcher) && isWild(last)) // collapse wildmatchers **/** is same as **, but preserve // dirOnly flag (i.e. always use the last wildmatcher) matchers.remove(matchers.size() - 1); } matchers.add(matcher); } return matchers; }
/** * Sets one or more {@code glob(7)} patterns that tags must match to be * considered. If multiple patterns are provided, tags only need match one * of them. * * @param patterns * the {@code glob(7)} pattern or patterns * @return {@code this} * @throws org.eclipse.jgit.errors.InvalidPatternException * if the pattern passed in was invalid. * @see <a href= * "https://www.kernel.org/pub/software/scm/git/docs/git-describe.html" * >Git documentation about describe</a> * @since 4.9 */ public DescribeCommand setMatch(String... patterns) throws InvalidPatternException { for (String p : patterns) { matchers.add(PathMatcher.createPathMatcher(p, null, false)); } return this; }
static boolean isWildCard(String pattern) { return pattern.indexOf('*') != -1 || isComplexWildcard(pattern); }
private static boolean isComplexWildcard(String pattern) { int idx1 = pattern.indexOf('['); if (idx1 != -1) { return true; } if (pattern.indexOf('?') != -1) { return true; } else { // check if the backslash escapes one of the glob special characters // if not, backslash is not part of a regex and treated literally int backSlash = pattern.indexOf('\\'); if (backSlash >= 0) { int nextIdx = backSlash + 1; if (pattern.length() == nextIdx) { return false; } char nextChar = pattern.charAt(nextIdx); if (escapedByBackslash(nextChar)) { return true; } else { return false; } } } return false; }
private boolean matches(int matcherIdx, String path, int startIncl, int endExcl, boolean assumeDirectory, boolean pathMatch) { IMatcher matcher = matchers.get(matcherIdx); final boolean matches = matcher.matches(path, startIncl, endExcl); if (!matches || !pathMatch || matcherIdx < matchers.size() - 1 || !(matcher instanceof AbstractMatcher)) { return matches; } return assumeDirectory || !((AbstractMatcher) matcher).dirOnly; }
static PatternState checkWildCards(String pattern) { if (isComplexWildcard(pattern)) return PatternState.COMPLEX; int startIdx = pattern.indexOf('*'); if (startIdx < 0) return PatternState.NONE; if (startIdx == pattern.length() - 1) return PatternState.TRAILING_ASTERISK_ONLY; if (pattern.lastIndexOf('*') == 0) return PatternState.LEADING_ASTERISK_ONLY; return PatternState.COMPLEX; }
static String deleteBackslash(String s) { if (s.indexOf('\\') < 0) { return s; } StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch == '\\') { if (i + 1 == s.length()) { continue; } char next = s.charAt(i + 1); if (next == '\\') { sb.append(ch); i++; continue; } if (!escapedByBackslash(next)) { continue; } } sb.append(ch); } return sb.toString(); }
/** * Returns true if a match was made. <br> * This function does NOT return the actual ignore status of the target! * Please consult {@link #getResult()} for the negation status. The actual * ignore status may be true or false depending on whether this rule is an * ignore rule or a negation rule. * * @param path * Name pattern of the file, relative to the base directory of * this rule * @param directory * Whether the target file is a directory or not * @param pathMatch * {@code true} if the match is for the full path: see * {@link IMatcher#matches(String, int, int)} * @return True if a match was made. This does not necessarily mean that the * target is ignored. Call {@link #getResult() getResult()} for the * result. * @since 4.11 */ public boolean isMatch(String path, boolean directory, boolean pathMatch) { if (path == null) return false; if (path.length() == 0) return false; boolean match = matcher.matches(path, directory, pathMatch); return match; }
private Optional<Ref> getBestMatch(List<Ref> tags) { if (tags == null || tags.size() == 0) { return Optional.empty(); } else if (matchers.size() == 0) { Collections.sort(tags, TAG_TIE_BREAKER); return Optional.of(tags.get(0)); } else { // Find the first tag that matches in the stream of all tags // filtered by matchers ordered by tie break order Stream<Ref> matchingTags = Stream.empty(); for (IMatcher matcher : matchers) { Stream<Ref> m = tags.stream().filter( tag -> matcher.matches(tag.getName(), false, false)); matchingTags = Stream.of(matchingTags, m).flatMap(i -> i); } return matchingTags.sorted(TAG_TIE_BREAKER).findFirst(); } }