1 /* 2 * Copyright (C) 2010, Red Hat Inc. 3 * and other copyright owners as documented in the project's IP log. 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 package org.eclipse.jgit.ignore; 44 45 import static java.nio.charset.StandardCharsets.UTF_8; 46 47 import java.io.BufferedReader; 48 import java.io.IOException; 49 import java.io.InputStream; 50 import java.io.InputStreamReader; 51 import java.util.ArrayList; 52 import java.util.Collections; 53 import java.util.List; 54 55 /** 56 * Represents a bundle of ignore rules inherited from a base directory. 57 * 58 * This class is not thread safe, it maintains state about the last match. 59 */ 60 public class IgnoreNode { 61 /** Result from {@link IgnoreNode#isIgnored(String, boolean)}. */ 62 public static enum MatchResult { 63 /** The file is not ignored, due to a rule saying its not ignored. */ 64 NOT_IGNORED, 65 66 /** The file is ignored due to a rule in this node. */ 67 IGNORED, 68 69 /** The ignore status is unknown, check inherited rules. */ 70 CHECK_PARENT, 71 72 /** 73 * The first previous (parent) ignore rule match (if any) should be 74 * negated, and then inherited rules applied. 75 * 76 * @since 3.6 77 */ 78 CHECK_PARENT_NEGATE_FIRST_MATCH; 79 } 80 81 /** The rules that have been parsed into this node. */ 82 private final List<FastIgnoreRule> rules; 83 84 /** 85 * Create an empty ignore node with no rules. 86 */ 87 public IgnoreNode() { 88 rules = new ArrayList<>(); 89 } 90 91 /** 92 * Create an ignore node with given rules. 93 * 94 * @param rules 95 * list of rules. 96 */ 97 public IgnoreNode(List<FastIgnoreRule> rules) { 98 this.rules = rules; 99 } 100 101 /** 102 * Parse files according to gitignore standards. 103 * 104 * @param in 105 * input stream holding the standard ignore format. The caller is 106 * responsible for closing the stream. 107 * @throws java.io.IOException 108 * Error thrown when reading an ignore file. 109 */ 110 public void parse(InputStream in) throws IOException { 111 BufferedReader br = asReader(in); 112 String txt; 113 while ((txt = br.readLine()) != null) { 114 if (txt.length() > 0 && !txt.startsWith("#") && !txt.equals("/")) { //$NON-NLS-1$ //$NON-NLS-2$ 115 FastIgnoreRule rule = new FastIgnoreRule(txt); 116 if (!rule.isEmpty()) { 117 rules.add(rule); 118 } 119 } 120 } 121 } 122 123 private static BufferedReader asReader(InputStream in) { 124 return new BufferedReader(new InputStreamReader(in, UTF_8)); 125 } 126 127 /** 128 * Get list of all ignore rules held by this node 129 * 130 * @return list of all ignore rules held by this node 131 */ 132 public List<FastIgnoreRule> getRules() { 133 return Collections.unmodifiableList(rules); 134 } 135 136 /** 137 * Determine if an entry path matches an ignore rule. 138 * 139 * @param entryPath 140 * the path to test. The path must be relative to this ignore 141 * node's own repository path, and in repository path format 142 * (uses '/' and not '\'). 143 * @param isDirectory 144 * true if the target item is a directory. 145 * @return status of the path. 146 */ 147 public MatchResult isIgnored(String entryPath, boolean isDirectory) { 148 final Boolean result = checkIgnored(entryPath, isDirectory); 149 if (result == null) { 150 return MatchResult.CHECK_PARENT; 151 } 152 153 return result.booleanValue() ? MatchResult.IGNORED 154 : MatchResult.NOT_IGNORED; 155 } 156 157 /** 158 * Determine if an entry path matches an ignore rule. 159 * 160 * @param entryPath 161 * the path to test. The path must be relative to this ignore 162 * node's own repository path, and in repository path format 163 * (uses '/' and not '\'). 164 * @param isDirectory 165 * true if the target item is a directory. 166 * @return Boolean.TRUE, if the entry is ignored; Boolean.FALSE, if the 167 * entry is forced to be not ignored (negated match); or null, if 168 * undetermined 169 * @since 4.11 170 */ 171 public Boolean checkIgnored(String entryPath, boolean isDirectory) { 172 // Parse rules in the reverse order that they were read because later 173 // rules have higher priority 174 for (int i = rules.size() - 1; i > -1; i--) { 175 FastIgnoreRule rule = rules.get(i); 176 if (rule.isMatch(entryPath, isDirectory, true)) { 177 return Boolean.valueOf(rule.getResult()); 178 } 179 } 180 return null; 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public String toString() { 186 return rules.toString(); 187 } 188 }