IgnoreNode: include path to file for invalid .gitignore patterns

Include the full file path of the .gitignore file and the line number
of the invalid pattern. Also include the pattern itself.

.gitignore files inside the repository are reported with their
repository-relative path; files outside (from git config
core.excludesFile or .git/info/exclude) are reported with their
full absolute path.

Bug: 571143
Change-Id: Ibe5969679bc22cff923c62e3ab9801d90d6d06d1
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
Thomas Wolf 2021-02-23 18:10:08 +01:00 committed by Matthias Sohn
parent 4e745c57f7
commit 29697d86c5
5 changed files with 80 additions and 26 deletions

View File

@ -31,6 +31,7 @@ badEntryName=Bad entry name: {0}
badEscape=Bad escape: {0}
badGroupHeader=Bad group header
badIgnorePattern=Cannot parse .gitignore pattern ''{0}''
badIgnorePatternFull=File {0} line {1}: cannot parse pattern ''{2}'': {3}
badObjectType=Bad object type: {0}
badRef=Bad ref: {0}: {1}
badSectionEntry=Bad section entry: {0}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de> and others
* Copyright (C) 2014, 2021 Andrey Loskutov <loskutov@gmx.de> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -39,11 +39,11 @@ public class FastIgnoreRule {
*/
public static final char PATH_SEPARATOR = '/';
private final IMatcher matcher;
private IMatcher matcher;
private final boolean inverse;
private boolean inverse;
private final boolean dirOnly;
private boolean dirOnly;
/**
* Constructor for FastIgnoreRule
@ -55,8 +55,23 @@ public class FastIgnoreRule {
* (comment), this rule doesn't match anything.
*/
public FastIgnoreRule(String pattern) {
if (pattern == null)
this();
try {
parse(pattern);
} catch (InvalidPatternException e) {
LOG.error(MessageFormat.format(JGitText.get().badIgnorePattern,
e.getPattern()), e);
}
}
FastIgnoreRule() {
matcher = IMatcher.NO_MATCH;
}
void parse(String pattern) throws InvalidPatternException {
if (pattern == null) {
throw new IllegalArgumentException("Pattern must not be null!"); //$NON-NLS-1$
}
if (pattern.length() == 0) {
dirOnly = false;
inverse = false;
@ -93,17 +108,8 @@ public FastIgnoreRule(String pattern) {
return;
}
}
IMatcher m;
try {
m = PathMatcher.createPathMatcher(pattern,
Character.valueOf(PATH_SEPARATOR), dirOnly);
} catch (InvalidPatternException e) {
m = NO_MATCH;
LOG.error(MessageFormat.format(
JGitText.get().badIgnorePattern,
e.getPattern()), e);
}
this.matcher = m;
this.matcher = PathMatcher.createPathMatcher(pattern,
Character.valueOf(PATH_SEPARATOR), dirOnly);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010, Red Hat Inc. and others
* Copyright (C) 2010, 2021 Red Hat Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -15,11 +15,16 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.internal.JGitText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents a bundle of ignore rules inherited from a base directory.
@ -27,6 +32,9 @@
* This class is not thread safe, it maintains state about the last match.
*/
public class IgnoreNode {
private static final Logger LOG = LoggerFactory.getLogger(IgnoreNode.class);
/** Result from {@link IgnoreNode#isIgnored(String, boolean)}. */
public enum MatchResult {
/** The file is not ignored, due to a rule saying its not ignored. */
@ -54,7 +62,7 @@ public enum MatchResult {
* Create an empty ignore node with no rules.
*/
public IgnoreNode() {
rules = new ArrayList<>();
this(new ArrayList<>());
}
/**
@ -77,15 +85,47 @@ public IgnoreNode(List<FastIgnoreRule> rules) {
* Error thrown when reading an ignore file.
*/
public void parse(InputStream in) throws IOException {
parse(null, in);
}
/**
* Parse files according to gitignore standards.
*
* @param sourceName
* identifying the source of the stream
* @param in
* input stream holding the standard ignore format. The caller is
* responsible for closing the stream.
* @throws java.io.IOException
* Error thrown when reading an ignore file.
* @since 5.11
*/
public void parse(String sourceName, InputStream in) throws IOException {
BufferedReader br = asReader(in);
String txt;
int lineNumber = 1;
while ((txt = br.readLine()) != null) {
if (txt.length() > 0 && !txt.startsWith("#") && !txt.equals("/")) { //$NON-NLS-1$ //$NON-NLS-2$
FastIgnoreRule rule = new FastIgnoreRule(txt);
FastIgnoreRule rule = new FastIgnoreRule();
try {
rule.parse(txt);
} catch (InvalidPatternException e) {
if (sourceName != null) {
LOG.error(MessageFormat.format(
JGitText.get().badIgnorePatternFull, sourceName,
Integer.toString(lineNumber), e.getPattern(),
e.getLocalizedMessage()), e);
} else {
LOG.error(MessageFormat.format(
JGitText.get().badIgnorePattern,
e.getPattern()), e);
}
}
if (!rule.isEmpty()) {
rules.add(rule);
}
}
lineNumber++;
}
}

View File

@ -59,6 +59,7 @@ public static JGitText get() {
/***/ public String badEscape;
/***/ public String badGroupHeader;
/***/ public String badIgnorePattern;
/***/ public String badIgnorePatternFull;
/***/ public String badObjectType;
/***/ public String badRef;
/***/ public String badSectionEntry;

View File

@ -2,7 +2,7 @@
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* Copyright (C) 2010, Matthias Sohn <matthias.sohn@sap.com>
* Copyright (C) 2012-2020, Robin Rosenberg and others
* Copyright (C) 2012-2021, Robin Rosenberg and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -800,7 +800,10 @@ protected void init(Entry[] list) {
if (Constants.DOT_GIT.equals(name))
continue;
if (Constants.DOT_GIT_IGNORE.equals(name))
ignoreNode = new PerDirectoryIgnoreNode(e);
ignoreNode = new PerDirectoryIgnoreNode(
TreeWalk.pathOf(path, 0, pathOffset)
+ Constants.DOT_GIT_IGNORE,
e);
if (Constants.DOT_GIT_ATTRIBUTES.equals(name))
attributesNode = new PerDirectoryAttributesNode(e);
if (i != o)
@ -1274,17 +1277,20 @@ public String toString() {
/** Magic type indicating we know rules exist, but they aren't loaded. */
private static class PerDirectoryIgnoreNode extends IgnoreNode {
final Entry entry;
protected final Entry entry;
PerDirectoryIgnoreNode(Entry entry) {
private final String name;
PerDirectoryIgnoreNode(String name, Entry entry) {
super(Collections.<FastIgnoreRule> emptyList());
this.name = name;
this.entry = entry;
}
IgnoreNode load() throws IOException {
IgnoreNode r = new IgnoreNode();
try (InputStream in = entry.openInputStream()) {
r.parse(in);
r.parse(name, in);
}
return r.getRules().isEmpty() ? null : r;
}
@ -1295,7 +1301,7 @@ private static class RootIgnoreNode extends PerDirectoryIgnoreNode {
final Repository repository;
RootIgnoreNode(Entry entry, Repository repository) {
super(entry);
super(entry != null ? entry.getName() : null, entry);
this.repository = repository;
}
@ -1329,7 +1335,7 @@ private static void loadRulesFromFile(IgnoreNode r, File exclude)
throws FileNotFoundException, IOException {
if (FS.DETECTED.exists(exclude)) {
try (FileInputStream in = new FileInputStream(exclude)) {
r.parse(in);
r.parse(exclude.getAbsolutePath(), in);
}
}
}