You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IgnoreNode.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (C) 2010, 2021 Red Hat Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.ignore;
  11. import static java.nio.charset.StandardCharsets.UTF_8;
  12. import java.io.BufferedReader;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.io.InputStreamReader;
  16. import java.text.MessageFormat;
  17. import java.util.ArrayList;
  18. import java.util.Collections;
  19. import java.util.List;
  20. import org.eclipse.jgit.annotations.Nullable;
  21. import org.eclipse.jgit.errors.InvalidPatternException;
  22. import org.eclipse.jgit.internal.JGitText;
  23. import org.slf4j.Logger;
  24. import org.slf4j.LoggerFactory;
  25. /**
  26. * Represents a bundle of ignore rules inherited from a base directory.
  27. *
  28. * This class is not thread safe, it maintains state about the last match.
  29. */
  30. public class IgnoreNode {
  31. private static final Logger LOG = LoggerFactory.getLogger(IgnoreNode.class);
  32. /** Result from {@link IgnoreNode#isIgnored(String, boolean)}. */
  33. public enum MatchResult {
  34. /** The file is not ignored, due to a rule saying its not ignored. */
  35. NOT_IGNORED,
  36. /** The file is ignored due to a rule in this node. */
  37. IGNORED,
  38. /** The ignore status is unknown, check inherited rules. */
  39. CHECK_PARENT,
  40. /**
  41. * The first previous (parent) ignore rule match (if any) should be
  42. * negated, and then inherited rules applied.
  43. *
  44. * @since 3.6
  45. */
  46. CHECK_PARENT_NEGATE_FIRST_MATCH;
  47. }
  48. /** The rules that have been parsed into this node. */
  49. private final List<FastIgnoreRule> rules;
  50. /**
  51. * Create an empty ignore node with no rules.
  52. */
  53. public IgnoreNode() {
  54. this(new ArrayList<>());
  55. }
  56. /**
  57. * Create an ignore node with given rules.
  58. *
  59. * @param rules
  60. * list of rules.
  61. */
  62. public IgnoreNode(List<FastIgnoreRule> rules) {
  63. this.rules = rules;
  64. }
  65. /**
  66. * Parse files according to gitignore standards.
  67. *
  68. * @param in
  69. * input stream holding the standard ignore format. The caller is
  70. * responsible for closing the stream.
  71. * @throws java.io.IOException
  72. * Error thrown when reading an ignore file.
  73. */
  74. public void parse(InputStream in) throws IOException {
  75. parse(null, in);
  76. }
  77. /**
  78. * Parse files according to gitignore standards.
  79. *
  80. * @param sourceName
  81. * identifying the source of the stream
  82. * @param in
  83. * input stream holding the standard ignore format. The caller is
  84. * responsible for closing the stream.
  85. * @throws java.io.IOException
  86. * Error thrown when reading an ignore file.
  87. * @since 5.11
  88. */
  89. public void parse(String sourceName, InputStream in) throws IOException {
  90. BufferedReader br = asReader(in);
  91. String txt;
  92. int lineNumber = 1;
  93. while ((txt = br.readLine()) != null) {
  94. if (txt.length() > 0 && !txt.startsWith("#") && !txt.equals("/")) { //$NON-NLS-1$ //$NON-NLS-2$
  95. FastIgnoreRule rule = new FastIgnoreRule();
  96. try {
  97. rule.parse(txt);
  98. } catch (InvalidPatternException e) {
  99. if (sourceName != null) {
  100. LOG.error(MessageFormat.format(
  101. JGitText.get().badIgnorePatternFull, sourceName,
  102. Integer.toString(lineNumber), e.getPattern(),
  103. e.getLocalizedMessage()), e);
  104. } else {
  105. LOG.error(MessageFormat.format(
  106. JGitText.get().badIgnorePattern,
  107. e.getPattern()), e);
  108. }
  109. }
  110. if (!rule.isEmpty()) {
  111. rules.add(rule);
  112. }
  113. }
  114. lineNumber++;
  115. }
  116. }
  117. private static BufferedReader asReader(InputStream in) {
  118. return new BufferedReader(new InputStreamReader(in, UTF_8));
  119. }
  120. /**
  121. * Get list of all ignore rules held by this node
  122. *
  123. * @return list of all ignore rules held by this node
  124. */
  125. public List<FastIgnoreRule> getRules() {
  126. return Collections.unmodifiableList(rules);
  127. }
  128. /**
  129. * Determine if an entry path matches an ignore rule.
  130. *
  131. * @param entryPath
  132. * the path to test. The path must be relative to this ignore
  133. * node's own repository path, and in repository path format
  134. * (uses '/' and not '\').
  135. * @param isDirectory
  136. * true if the target item is a directory.
  137. * @return status of the path.
  138. */
  139. public MatchResult isIgnored(String entryPath, boolean isDirectory) {
  140. final Boolean result = checkIgnored(entryPath, isDirectory);
  141. if (result == null) {
  142. return MatchResult.CHECK_PARENT;
  143. }
  144. return result.booleanValue() ? MatchResult.IGNORED
  145. : MatchResult.NOT_IGNORED;
  146. }
  147. /**
  148. * Determine if an entry path matches an ignore rule.
  149. *
  150. * @param entryPath
  151. * the path to test. The path must be relative to this ignore
  152. * node's own repository path, and in repository path format
  153. * (uses '/' and not '\').
  154. * @param isDirectory
  155. * true if the target item is a directory.
  156. * @return Boolean.TRUE, if the entry is ignored; Boolean.FALSE, if the
  157. * entry is forced to be not ignored (negated match); or null, if
  158. * undetermined
  159. * @since 4.11
  160. */
  161. public @Nullable Boolean checkIgnored(String entryPath,
  162. boolean isDirectory) {
  163. // Parse rules in the reverse order that they were read because later
  164. // rules have higher priority
  165. for (int i = rules.size() - 1; i > -1; i--) {
  166. FastIgnoreRule rule = rules.get(i);
  167. if (rule.isMatch(entryPath, isDirectory, true)) {
  168. return Boolean.valueOf(rule.getResult());
  169. }
  170. }
  171. return null;
  172. }
  173. /** {@inheritDoc} */
  174. @Override
  175. public String toString() {
  176. return rules.toString();
  177. }
  178. }