FastIgnoreRule.java
- /*
- * Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package org.eclipse.jgit.ignore;
- import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH;
- import static org.eclipse.jgit.ignore.internal.Strings.isDirectoryPattern;
- import static org.eclipse.jgit.ignore.internal.Strings.stripTrailing;
- import static org.eclipse.jgit.ignore.internal.Strings.stripTrailingWhitespace;
- import org.eclipse.jgit.errors.InvalidPatternException;
- import org.eclipse.jgit.ignore.internal.IMatcher;
- import org.eclipse.jgit.ignore.internal.PathMatcher;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * "Fast" (compared with IgnoreRule) git ignore rule implementation supporting
- * also double star {@code **} pattern.
- * <p>
- * This class is immutable and thread safe.
- *
- * @since 3.6
- */
- public class FastIgnoreRule {
- private final static Logger LOG = LoggerFactory
- .getLogger(FastIgnoreRule.class);
- /**
- * Character used as default path separator for ignore entries
- */
- public static final char PATH_SEPARATOR = '/';
- private final IMatcher matcher;
- private final boolean inverse;
- private final boolean dirOnly;
- /**
- * Constructor for FastIgnoreRule
- *
- * @param pattern
- * ignore pattern as described in <a href=
- * "https://www.kernel.org/pub/software/scm/git/docs/gitignore.html"
- * >git manual</a>. If pattern is invalid or is not a pattern
- * (comment), this rule doesn't match anything.
- */
- public FastIgnoreRule(String pattern) {
- if (pattern == null)
- throw new IllegalArgumentException("Pattern must not be null!"); //$NON-NLS-1$
- if (pattern.length() == 0) {
- dirOnly = false;
- inverse = false;
- this.matcher = NO_MATCH;
- return;
- }
- inverse = pattern.charAt(0) == '!';
- if (inverse) {
- pattern = pattern.substring(1);
- if (pattern.length() == 0) {
- dirOnly = false;
- this.matcher = NO_MATCH;
- return;
- }
- }
- if (pattern.charAt(0) == '#') {
- this.matcher = NO_MATCH;
- dirOnly = false;
- return;
- }
- if (pattern.charAt(0) == '\\' && pattern.length() > 1) {
- char next = pattern.charAt(1);
- if (next == '!' || next == '#') {
- // remove backslash escaping first special characters
- pattern = pattern.substring(1);
- }
- }
- dirOnly = isDirectoryPattern(pattern);
- if (dirOnly) {
- pattern = stripTrailingWhitespace(pattern);
- pattern = stripTrailing(pattern, PATH_SEPARATOR);
- if (pattern.length() == 0) {
- this.matcher = NO_MATCH;
- return;
- }
- }
- IMatcher m;
- try {
- m = PathMatcher.createPathMatcher(pattern,
- Character.valueOf(PATH_SEPARATOR), dirOnly);
- } catch (InvalidPatternException e) {
- m = NO_MATCH;
- LOG.error(e.getMessage(), e);
- }
- this.matcher = m;
- }
- /**
- * 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
- * @return True if a match was made. This does not necessarily mean that the
- * target is ignored. Call {@link #getResult() getResult()} for the
- * result.
- */
- public boolean isMatch(String path, boolean directory) {
- return isMatch(path, directory, false);
- }
- /**
- * 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;
- }
- /**
- * Whether the pattern is just a file name and not a path
- *
- * @return {@code true} if the pattern is just a file name and not a path
- */
- public boolean getNameOnly() {
- return !(matcher instanceof PathMatcher);
- }
- /**
- * Whether the pattern should match directories only
- *
- * @return {@code true} if the pattern should match directories only
- */
- public boolean dirOnly() {
- return dirOnly;
- }
- /**
- * Indicates whether the rule is non-negation or negation.
- *
- * @return True if the pattern had a "!" in front of it
- */
- public boolean getNegation() {
- return inverse;
- }
- /**
- * Indicates whether the rule is non-negation or negation.
- *
- * @return True if the target is to be ignored, false otherwise.
- */
- public boolean getResult() {
- return !inverse;
- }
- /**
- * Whether the rule never matches
- *
- * @return {@code true} if the rule never matches (comment line or broken
- * pattern)
- * @since 4.1
- */
- public boolean isEmpty() {
- return matcher == NO_MATCH;
- }
- /** {@inheritDoc} */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- if (inverse)
- sb.append('!');
- sb.append(matcher);
- if (dirOnly)
- sb.append(PATH_SEPARATOR);
- return sb.toString();
- }
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (inverse ? 1231 : 1237);
- result = prime * result + (dirOnly ? 1231 : 1237);
- result = prime * result + ((matcher == null) ? 0 : matcher.hashCode());
- return result;
- }
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!(obj instanceof FastIgnoreRule))
- return false;
- FastIgnoreRule other = (FastIgnoreRule) obj;
- if (inverse != other.inverse)
- return false;
- if (dirOnly != other.dirOnly)
- return false;
- return matcher.equals(other.matcher);
- }
- }