/*
 * Copyright (C) 2010, 2017 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
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.attributes;

import static org.eclipse.jgit.ignore.IMatcher.NO_MATCH;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.jgit.attributes.Attribute.State;
import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.ignore.FastIgnoreRule;
import org.eclipse.jgit.ignore.IMatcher;
import org.eclipse.jgit.ignore.internal.PathMatcher;

A single attributes rule corresponding to one line in a .gitattributes file. Inspiration from: FastIgnoreRule
Since:3.7
/** * A single attributes rule corresponding to one line in a .gitattributes file. * * Inspiration from: {@link org.eclipse.jgit.ignore.FastIgnoreRule} * * @since 3.7 */
public class AttributesRule {
regular expression for splitting attributes - space, tab and \r (the C implementation oddly enough allows \r between attributes)
/** * regular expression for splitting attributes - space, tab and \r (the C * implementation oddly enough allows \r between attributes) * */
private static final String ATTRIBUTES_SPLIT_REGEX = "[ \t\r]"; //$NON-NLS-1$ private static List<Attribute> parseAttributes(String attributesLine) { // the C implementation oddly enough allows \r between attributes too. ArrayList<Attribute> result = new ArrayList<>(); for (String attribute : attributesLine.split(ATTRIBUTES_SPLIT_REGEX)) { attribute = attribute.trim(); if (attribute.length() == 0) continue; if (attribute.startsWith("-")) {//$NON-NLS-1$ if (attribute.length() > 1) result.add(new Attribute(attribute.substring(1), State.UNSET)); continue; } if (attribute.startsWith("!")) {//$NON-NLS-1$ if (attribute.length() > 1) result.add(new Attribute(attribute.substring(1), State.UNSPECIFIED)); continue; } final int equalsIndex = attribute.indexOf('='); if (equalsIndex == -1) result.add(new Attribute(attribute, State.SET)); else { String attributeKey = attribute.substring(0, equalsIndex); if (attributeKey.length() > 0) { String attributeValue = attribute .substring(equalsIndex + 1); result.add(new Attribute(attributeKey, attributeValue)); } } } return result; } private final String pattern; private final List<Attribute> attributes; private final boolean nameOnly; private final boolean dirOnly; private final IMatcher matcher;
Create a new attribute rule with the given pattern. Assumes that the pattern is already trimmed.
Params:
  • pattern – Base pattern for the attributes rule. This pattern will be parsed to generate rule parameters. It can not be null.
  • attributes – the rule attributes. This string will be parsed to read the attributes.
/** * Create a new attribute rule with the given pattern. Assumes that the * pattern is already trimmed. * * @param pattern * Base pattern for the attributes rule. This pattern will be * parsed to generate rule parameters. It can not be * <code>null</code>. * @param attributes * the rule attributes. This string will be parsed to read the * attributes. */
public AttributesRule(String pattern, String attributes) { this.attributes = parseAttributes(attributes); if (pattern.endsWith("/")) { //$NON-NLS-1$ pattern = pattern.substring(0, pattern.length() - 1); dirOnly = true; } else { dirOnly = false; } int slashIndex = pattern.indexOf('/'); if (slashIndex < 0) { nameOnly = true; } else if (slashIndex == 0) { nameOnly = false; } else { nameOnly = false; // Contains "/" but does not start with one // Adding / to the start should not interfere with matching pattern = "/" + pattern; //$NON-NLS-1$ } IMatcher candidateMatcher = NO_MATCH; try { candidateMatcher = PathMatcher.createPathMatcher(pattern, Character.valueOf(FastIgnoreRule.PATH_SEPARATOR), dirOnly); } catch (InvalidPatternException e) { // ignore: invalid patterns are silently ignored } this.matcher = candidateMatcher; this.pattern = pattern; }
Whether to match directories only
Returns:true if the pattern should match directories only
Since:4.3
/** * Whether to match directories only * * @return {@code true} if the pattern should match directories only * @since 4.3 */
public boolean isDirOnly() { return dirOnly; }
Return the attributes.
Returns:an unmodifiable list of attributes (never returns null)
/** * Return the attributes. * * @return an unmodifiable list of attributes (never returns * <code>null</code>) */
public List<Attribute> getAttributes() { return Collections.unmodifiableList(attributes); }
Whether the pattern is only a file name and not a path
Returns:true if the pattern is just a file name and not a path
/** * Whether the pattern is only a file name and not a path * * @return <code>true</code> if the pattern is just a file name and not a * path */
public boolean isNameOnly() { return nameOnly; }
Get the pattern
Returns:The blob pattern to be used as a matcher (never returns null)
/** * Get the pattern * * @return The blob pattern to be used as a matcher (never returns * <code>null</code>) */
public String getPattern() { return pattern; }
Returns true if a match was made.
Params:
  • relativeTarget – Name pattern of the file, relative to the base directory of this rule
  • isDirectory – Whether the target file is a directory or not
Returns:True if a match was made.
/** * Returns <code>true</code> if a match was made. * * @param relativeTarget * Name pattern of the file, relative to the base directory of * this rule * @param isDirectory * Whether the target file is a directory or not * @return True if a match was made. */
public boolean isMatch(String relativeTarget, boolean isDirectory) { if (relativeTarget == null) return false; if (relativeTarget.length() == 0) return false; boolean match = matcher.matches(relativeTarget, isDirectory, true); return match; }
{@inheritDoc}
/** {@inheritDoc} */
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(pattern); for (Attribute a : attributes) { sb.append(" "); //$NON-NLS-1$ sb.append(a); } return sb.toString(); } }