Browse Source

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>
tags/v5.11.0.202102240950-m3
Thomas Wolf 3 years ago
parent
commit
29697d86c5

+ 1
- 0
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties View File

badEscape=Bad escape: {0} badEscape=Bad escape: {0}
badGroupHeader=Bad group header badGroupHeader=Bad group header
badIgnorePattern=Cannot parse .gitignore pattern ''{0}'' badIgnorePattern=Cannot parse .gitignore pattern ''{0}''
badIgnorePatternFull=File {0} line {1}: cannot parse pattern ''{2}'': {3}
badObjectType=Bad object type: {0} badObjectType=Bad object type: {0}
badRef=Bad ref: {0}: {1} badRef=Bad ref: {0}: {1}
badSectionEntry=Bad section entry: {0} badSectionEntry=Bad section entry: {0}

+ 22
- 16
org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java View File

/* /*
* 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 * This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at * terms of the Eclipse Distribution License v. 1.0 which is available at
*/ */
public static final char PATH_SEPARATOR = '/'; 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 * Constructor for FastIgnoreRule
* (comment), this rule doesn't match anything. * (comment), this rule doesn't match anything.
*/ */
public FastIgnoreRule(String pattern) { 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$ throw new IllegalArgumentException("Pattern must not be null!"); //$NON-NLS-1$
}
if (pattern.length() == 0) { if (pattern.length() == 0) {
dirOnly = false; dirOnly = false;
inverse = false; inverse = false;
return; 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);
} }


/** /**

+ 43
- 3
org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreNode.java View File

/* /*
* 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 * This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at * terms of the Eclipse Distribution License v. 1.0 which is available at
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;


import org.eclipse.jgit.annotations.Nullable; 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. * Represents a bundle of ignore rules inherited from a base directory.
* This class is not thread safe, it maintains state about the last match. * This class is not thread safe, it maintains state about the last match.
*/ */
public class IgnoreNode { public class IgnoreNode {

private static final Logger LOG = LoggerFactory.getLogger(IgnoreNode.class);

/** Result from {@link IgnoreNode#isIgnored(String, boolean)}. */ /** Result from {@link IgnoreNode#isIgnored(String, boolean)}. */
public enum MatchResult { public enum MatchResult {
/** The file is not ignored, due to a rule saying its not ignored. */ /** The file is not ignored, due to a rule saying its not ignored. */
* Create an empty ignore node with no rules. * Create an empty ignore node with no rules.
*/ */
public IgnoreNode() { public IgnoreNode() {
rules = new ArrayList<>();
this(new ArrayList<>());
} }


/** /**
* Error thrown when reading an ignore file. * Error thrown when reading an ignore file.
*/ */
public void parse(InputStream in) throws IOException { 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); BufferedReader br = asReader(in);
String txt; String txt;
int lineNumber = 1;
while ((txt = br.readLine()) != null) { while ((txt = br.readLine()) != null) {
if (txt.length() > 0 && !txt.startsWith("#") && !txt.equals("/")) { //$NON-NLS-1$ //$NON-NLS-2$ 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()) { if (!rule.isEmpty()) {
rules.add(rule); rules.add(rule);
} }
} }
lineNumber++;
} }
} }



+ 1
- 0
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java View File

/***/ public String badEscape; /***/ public String badEscape;
/***/ public String badGroupHeader; /***/ public String badGroupHeader;
/***/ public String badIgnorePattern; /***/ public String badIgnorePattern;
/***/ public String badIgnorePatternFull;
/***/ public String badObjectType; /***/ public String badObjectType;
/***/ public String badRef; /***/ public String badRef;
/***/ public String badSectionEntry; /***/ public String badSectionEntry;

+ 13
- 7
org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java View File

* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
* Copyright (C) 2010, Matthias Sohn <matthias.sohn@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 * This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at * terms of the Eclipse Distribution License v. 1.0 which is available at
if (Constants.DOT_GIT.equals(name)) if (Constants.DOT_GIT.equals(name))
continue; continue;
if (Constants.DOT_GIT_IGNORE.equals(name)) 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)) if (Constants.DOT_GIT_ATTRIBUTES.equals(name))
attributesNode = new PerDirectoryAttributesNode(e); attributesNode = new PerDirectoryAttributesNode(e);
if (i != o) if (i != o)


/** Magic type indicating we know rules exist, but they aren't loaded. */ /** Magic type indicating we know rules exist, but they aren't loaded. */
private static class PerDirectoryIgnoreNode extends IgnoreNode { private static class PerDirectoryIgnoreNode extends IgnoreNode {
final Entry entry;
protected final Entry entry;

private final String name;


PerDirectoryIgnoreNode(Entry entry) {
PerDirectoryIgnoreNode(String name, Entry entry) {
super(Collections.<FastIgnoreRule> emptyList()); super(Collections.<FastIgnoreRule> emptyList());
this.name = name;
this.entry = entry; this.entry = entry;
} }


IgnoreNode load() throws IOException { IgnoreNode load() throws IOException {
IgnoreNode r = new IgnoreNode(); IgnoreNode r = new IgnoreNode();
try (InputStream in = entry.openInputStream()) { try (InputStream in = entry.openInputStream()) {
r.parse(in);
r.parse(name, in);
} }
return r.getRules().isEmpty() ? null : r; return r.getRules().isEmpty() ? null : r;
} }
final Repository repository; final Repository repository;


RootIgnoreNode(Entry entry, Repository repository) { RootIgnoreNode(Entry entry, Repository repository) {
super(entry);
super(entry != null ? entry.getName() : null, entry);
this.repository = repository; this.repository = repository;
} }


throws FileNotFoundException, IOException { throws FileNotFoundException, IOException {
if (FS.DETECTED.exists(exclude)) { if (FS.DETECTED.exists(exclude)) {
try (FileInputStream in = new FileInputStream(exclude)) { try (FileInputStream in = new FileInputStream(exclude)) {
r.parse(in);
r.parse(exclude.getAbsolutePath(), in);
} }
} }
} }

Loading…
Cancel
Save