Add the new class Attributes holding multiple Attribute(s)
Attributes represents a semantic collector of Attribute(s) and replaces the anonymous Map<String,Attribute>. This class will be returned by TreeWalk.getAttributes(). It offers convenient access to the attributes wrapped in the Attributes object. Adds preparations for a future Attribute Macro Expansion Change-Id: I8348c8c457a2a7f1f0c48050e10399b0fa1cdbe1 Signed-off-by: Ivan Motsch <ivan.motsch@bsiag.com>
This commit is contained in:
parent
adbe900683
commit
75697adc5a
|
@ -52,9 +52,7 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
import org.eclipse.jgit.attributes.Attribute.State;
|
import org.eclipse.jgit.attributes.Attribute.State;
|
||||||
|
@ -258,12 +256,14 @@ private void assertAttributesNode(String pathName,
|
||||||
assertTrue(nodeAttrs == null || nodeAttrs.isEmpty());
|
assertTrue(nodeAttrs == null || nodeAttrs.isEmpty());
|
||||||
else {
|
else {
|
||||||
|
|
||||||
Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>();
|
Attributes entryAttributes = new Attributes();
|
||||||
attributesNode.getAttributes(pathName, false, entryAttributes);
|
attributesNode.getAttributes(pathName,
|
||||||
|
false, entryAttributes);
|
||||||
|
|
||||||
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
|
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
|
||||||
for (Attribute attribute : nodeAttrs) {
|
for (Attribute attribute : nodeAttrs) {
|
||||||
assertThat(entryAttributes.values(), hasItem(attribute));
|
assertThat(entryAttributes.getAll(),
|
||||||
|
hasItem(attribute));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
|
|
|
@ -49,10 +49,6 @@
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -104,8 +100,8 @@ public void testNegativePattern() throws IOException {
|
||||||
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
||||||
AttributesNode node = new AttributesNode();
|
AttributesNode node = new AttributesNode();
|
||||||
node.parse(is);
|
node.parse(is);
|
||||||
assertAttribute("file.type1", node, Collections.<Attribute> emptySet());
|
assertAttribute("file.type1", node, new Attributes());
|
||||||
assertAttribute("file.type2", node, Collections.<Attribute> emptySet());
|
assertAttribute("file.type2", node, new Attributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -115,7 +111,7 @@ public void testEmptyNegativeAttributeKey() throws IOException {
|
||||||
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
||||||
AttributesNode node = new AttributesNode();
|
AttributesNode node = new AttributesNode();
|
||||||
node.parse(is);
|
node.parse(is);
|
||||||
assertAttribute("file.type1", node, Collections.<Attribute> emptySet());
|
assertAttribute("file.type1", node, new Attributes());
|
||||||
assertAttribute("file.type2", node, asSet(A_UNSET_ATTR));
|
assertAttribute("file.type2", node, asSet(A_UNSET_ATTR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +123,8 @@ public void testEmptyValueKey() throws IOException {
|
||||||
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
is = new ByteArrayInputStream(attributeFileContent.getBytes());
|
||||||
AttributesNode node = new AttributesNode();
|
AttributesNode node = new AttributesNode();
|
||||||
node.parse(is);
|
node.parse(is);
|
||||||
assertAttribute("file.type1", node, Collections.<Attribute> emptySet());
|
assertAttribute("file.type1", node, new Attributes());
|
||||||
assertAttribute("file.type2", node, Collections.<Attribute> emptySet());
|
assertAttribute("file.type2", node, new Attributes());
|
||||||
assertAttribute("file.type3", node, asSet(new Attribute("attr", "")));
|
assertAttribute("file.type3", node, asSet(new Attribute("attr", "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,17 +162,14 @@ public void testTabSeparator() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertAttribute(String path, AttributesNode node,
|
private void assertAttribute(String path, AttributesNode node,
|
||||||
Set<Attribute> attrs) {
|
Attributes attrs) {
|
||||||
HashMap<String, Attribute> attributes = new HashMap<String, Attribute>();
|
Attributes attributes = new Attributes();
|
||||||
node.getAttributes(path, false, attributes);
|
node.getAttributes(path, false, attributes);
|
||||||
assertEquals(attrs, new HashSet<Attribute>(attributes.values()));
|
assertEquals(attrs, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Set<Attribute> asSet(Attribute... attrs) {
|
static Attributes asSet(Attribute... attrs) {
|
||||||
Set<Attribute> result = new HashSet<Attribute>();
|
return new Attributes(attrs);
|
||||||
for (Attribute attr : attrs)
|
|
||||||
result.add(attr);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,7 @@
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.attributes.Attribute.State;
|
import org.eclipse.jgit.attributes.Attribute.State;
|
||||||
import org.eclipse.jgit.errors.CorruptObjectException;
|
import org.eclipse.jgit.errors.CorruptObjectException;
|
||||||
|
@ -227,12 +225,14 @@ private void assertAttributesNode(String pathName,
|
||||||
assertTrue(nodeAttrs == null || nodeAttrs.isEmpty());
|
assertTrue(nodeAttrs == null || nodeAttrs.isEmpty());
|
||||||
else {
|
else {
|
||||||
|
|
||||||
Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>();
|
Attributes entryAttributes = new Attributes();
|
||||||
attributesNode.getAttributes(pathName, false, entryAttributes);
|
attributesNode.getAttributes(pathName,
|
||||||
|
false, entryAttributes);
|
||||||
|
|
||||||
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
|
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
|
||||||
for (Attribute attribute : nodeAttrs) {
|
for (Attribute attribute : nodeAttrs) {
|
||||||
assertThat(entryAttributes.values(), hasItem(attribute));
|
assertThat(entryAttributes.getAll(),
|
||||||
|
hasItem(attribute));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
|
|
|
@ -802,8 +802,9 @@ private void assertEntry(FileMode type, String pathName,
|
||||||
assertEquals(type, walk.getFileMode(0));
|
assertEquals(type, walk.getFileMode(0));
|
||||||
|
|
||||||
assertEquals(checkinAttributes,
|
assertEquals(checkinAttributes,
|
||||||
asSet(ci_walk.getAttributes().values()));
|
asSet(ci_walk.getAttributes().getAll()));
|
||||||
assertEquals(checkoutAttributes, asSet(walk.getAttributes().values()));
|
assertEquals(checkoutAttributes,
|
||||||
|
asSet(walk.getAttributes().getAll()));
|
||||||
|
|
||||||
if (D.equals(type)) {
|
if (D.equals(type)) {
|
||||||
walk.enterSubtree();
|
walk.enterSubtree();
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<component id="org.eclipse.jgit" version="2">
|
<component id="org.eclipse.jgit" version="2">
|
||||||
|
<resource path="src/org/eclipse/jgit/attributes/AttributesNode.java" type="org.eclipse.jgit.attributes.AttributesNode">
|
||||||
|
<filter comment="attributes weren't really usable in earlier versions" id="338792546">
|
||||||
|
<message_arguments>
|
||||||
|
<message_argument value="org.eclipse.jgit.attributes.AttributesNode"/>
|
||||||
|
<message_argument value="getAttributes(String, boolean, Map<String,Attribute>)"/>
|
||||||
|
</message_arguments>
|
||||||
|
</filter>
|
||||||
|
</resource>
|
||||||
<resource path="src/org/eclipse/jgit/lib/BitmapIndex.java" type="org.eclipse.jgit.lib.BitmapIndex$BitmapBuilder">
|
<resource path="src/org/eclipse/jgit/lib/BitmapIndex.java" type="org.eclipse.jgit.lib.BitmapIndex$BitmapBuilder">
|
||||||
<filter comment="interface is implemented by extenders but not clients of the API" id="403804204">
|
<filter comment="interface is implemented by extenders but not clients of the API" id="403804204">
|
||||||
<message_arguments>
|
<message_arguments>
|
||||||
|
|
|
@ -50,8 +50,10 @@
|
||||||
* <li>Set - represented by {@link State#SET}</li>
|
* <li>Set - represented by {@link State#SET}</li>
|
||||||
* <li>Unset - represented by {@link State#UNSET}</li>
|
* <li>Unset - represented by {@link State#UNSET}</li>
|
||||||
* <li>Set to a value - represented by {@link State#CUSTOM}</li>
|
* <li>Set to a value - represented by {@link State#CUSTOM}</li>
|
||||||
* <li>Unspecified - <code>null</code> is used instead of an instance of this
|
* <li>Unspecified - used to revert an attribute . This is crucial in order to
|
||||||
* class</li>
|
* mark an attribute as unspecified in the attributes map and thus preventing
|
||||||
|
* following (with lower priority) nodes from setting the attribute to a value
|
||||||
|
* at all</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
|
@ -61,6 +63,7 @@ public final class Attribute {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attribute value state
|
* The attribute value state
|
||||||
|
* see also https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
|
||||||
*/
|
*/
|
||||||
public static enum State {
|
public static enum State {
|
||||||
/** the attribute is set */
|
/** the attribute is set */
|
||||||
|
@ -69,6 +72,13 @@ public static enum State {
|
||||||
/** the attribute is unset */
|
/** the attribute is unset */
|
||||||
UNSET,
|
UNSET,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the attribute appears as if it would not be defined at all
|
||||||
|
*
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
UNSPECIFIED,
|
||||||
|
|
||||||
/** the attribute is set to a custom value */
|
/** the attribute is set to a custom value */
|
||||||
CUSTOM
|
CUSTOM
|
||||||
}
|
}
|
||||||
|
@ -176,6 +186,8 @@ public String toString() {
|
||||||
return key;
|
return key;
|
||||||
case UNSET:
|
case UNSET:
|
||||||
return "-" + key; //$NON-NLS-1$
|
return "-" + key; //$NON-NLS-1$
|
||||||
|
case UNSPECIFIED:
|
||||||
|
return "!" + key; //$NON-NLS-1$
|
||||||
case CUSTOM:
|
case CUSTOM:
|
||||||
default:
|
default:
|
||||||
return key + "=" + value; //$NON-NLS-1$
|
return key + "=" + value; //$NON-NLS-1$
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015, Ivan Motsch <ivan.motsch@bsiag.com>
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available
|
||||||
|
* under the terms of the Eclipse Distribution License v1.0 which
|
||||||
|
* accompanies this distribution, is reproduced below, and is
|
||||||
|
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
*
|
||||||
|
* - Neither the name of the Eclipse Foundation, Inc. nor the
|
||||||
|
* names of its contributors may be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.eclipse.jgit.attributes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.attributes.Attribute.State;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a set of attributes for a path
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
public final class Attributes {
|
||||||
|
private final Map<String, Attribute> map = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*
|
||||||
|
* @param attributes
|
||||||
|
*/
|
||||||
|
public Attributes(Attribute... attributes) {
|
||||||
|
if (attributes != null) {
|
||||||
|
for (Attribute a : attributes) {
|
||||||
|
put(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the set does not contain any attributes
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return the attribute or null
|
||||||
|
*/
|
||||||
|
public Attribute get(String key) {
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all attributes
|
||||||
|
*/
|
||||||
|
public Collection<Attribute> getAll() {
|
||||||
|
return new ArrayList<>(map.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a
|
||||||
|
*/
|
||||||
|
public void put(Attribute a) {
|
||||||
|
map.put(a.getKey(), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public void remove(String key) {
|
||||||
|
map.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return true if the {@link Attributes} contains this key
|
||||||
|
*/
|
||||||
|
public boolean containsKey(String key) {
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*
|
||||||
|
* @return the state (never returns <code>null</code>)
|
||||||
|
*/
|
||||||
|
public Attribute.State getState(String key) {
|
||||||
|
Attribute a = map.get(key);
|
||||||
|
return a != null ? a.getState() : Attribute.State.UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return true if the key is {@link State#SET}, false in all other cases
|
||||||
|
*/
|
||||||
|
public boolean isSet(String key) {
|
||||||
|
return (getState(key) == State.SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return true if the key is {@link State#UNSET}, false in all other cases
|
||||||
|
*/
|
||||||
|
public boolean isUnset(String key) {
|
||||||
|
return (getState(key) == State.UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return true if the key is {@link State#UNSPECIFIED}, false in all other
|
||||||
|
* cases
|
||||||
|
*/
|
||||||
|
public boolean isUnspecified(String key) {
|
||||||
|
return (getState(key) == State.UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return true if the key is {@link State#CUSTOM}, false in all other cases
|
||||||
|
* see {@link #getValue(String)} for the value of the key
|
||||||
|
*/
|
||||||
|
public boolean isCustom(String key) {
|
||||||
|
return (getState(key) == State.CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @return the attribute value (may be <code>null</code>)
|
||||||
|
*/
|
||||||
|
public String getValue(String key) {
|
||||||
|
Attribute a = map.get(key);
|
||||||
|
return a != null ? a.getValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append(getClass().getSimpleName());
|
||||||
|
buf.append("["); //$NON-NLS-1$
|
||||||
|
buf.append(" "); //$NON-NLS-1$
|
||||||
|
for (Attribute a : map.values()) {
|
||||||
|
buf.append(a.toString());
|
||||||
|
buf.append(" "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
buf.append("]"); //$NON-NLS-1$
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return map.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!(obj instanceof Attributes))
|
||||||
|
return false;
|
||||||
|
Attributes other = (Attributes) obj;
|
||||||
|
return this.map.equals(other.map);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -50,7 +50,6 @@
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
|
||||||
|
@ -134,11 +133,12 @@ public List<AttributesRule> getRules() {
|
||||||
* true if the target item is a directory.
|
* true if the target item is a directory.
|
||||||
* @param attributes
|
* @param attributes
|
||||||
* Map that will hold the attributes matching this entry path. If
|
* Map that will hold the attributes matching this entry path. If
|
||||||
* it is not empty, this method will NOT override any
|
* it is not empty, this method will NOT override any existing
|
||||||
* existing entry.
|
* entry.
|
||||||
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public void getAttributes(String entryPath, boolean isDirectory,
|
public void getAttributes(String entryPath,
|
||||||
Map<String, Attribute> attributes) {
|
boolean isDirectory, Attributes attributes) {
|
||||||
// Parse rules in the reverse order that they were read since the last
|
// Parse rules in the reverse order that they were read since the last
|
||||||
// entry should be used
|
// entry should be used
|
||||||
ListIterator<AttributesRule> ruleIterator = rules.listIterator(rules
|
ListIterator<AttributesRule> ruleIterator = rules.listIterator(rules
|
||||||
|
@ -153,7 +153,7 @@ public void getAttributes(String entryPath, boolean isDirectory,
|
||||||
while (attributeIte.hasPrevious()) {
|
while (attributeIte.hasPrevious()) {
|
||||||
Attribute attr = attributeIte.previous();
|
Attribute attr = attributeIte.previous();
|
||||||
if (!attributes.containsKey(attr.getKey()))
|
if (!attributes.containsKey(attr.getKey()))
|
||||||
attributes.put(attr.getKey(), attr);
|
attributes.put(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,6 @@
|
||||||
*/
|
*/
|
||||||
package org.eclipse.jgit.attributes;
|
package org.eclipse.jgit.attributes;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for classes which provide git attributes
|
* Interface for classes which provide git attributes
|
||||||
*
|
*
|
||||||
|
@ -51,7 +49,7 @@
|
||||||
*/
|
*/
|
||||||
public interface AttributesProvider {
|
public interface AttributesProvider {
|
||||||
/**
|
/**
|
||||||
* @return the currently active attributes by attribute key
|
* @return the currently active attributes
|
||||||
*/
|
*/
|
||||||
public Map<String, Attribute> getAttributes();
|
public Attributes getAttributes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,13 @@ private static List<Attribute> parseAttributes(String attributesLine) {
|
||||||
continue;
|
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("="); //$NON-NLS-1$
|
final int equalsIndex = attribute.indexOf("="); //$NON-NLS-1$
|
||||||
if (equalsIndex == -1)
|
if (equalsIndex == -1)
|
||||||
result.add(new Attribute(attribute, State.SET));
|
result.add(new Attribute(attribute, State.SET));
|
||||||
|
@ -200,4 +207,16 @@ public boolean isMatch(String relativeTarget, boolean isDirectory) {
|
||||||
boolean match = matcher.matches(relativeTarget, isDirectory);
|
boolean match = matcher.matches(relativeTarget, isDirectory);
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -47,6 +47,7 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.eclipse.jgit.attributes.AttributesNode;
|
import org.eclipse.jgit.attributes.AttributesNode;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.util.FS;
|
import org.eclipse.jgit.util.FS;
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ public AttributesNode load() throws IOException {
|
||||||
FS fs = repository.getFS();
|
FS fs = repository.getFS();
|
||||||
|
|
||||||
File attributes = fs.resolve(repository.getDirectory(),
|
File attributes = fs.resolve(repository.getDirectory(),
|
||||||
"info/attributes"); //$NON-NLS-1$
|
Constants.INFO_ATTRIBUTES);
|
||||||
FileRepository.AttributesNodeProviderImpl.loadRulesFromFile(r, attributes);
|
FileRepository.AttributesNodeProviderImpl.loadRulesFromFile(r, attributes);
|
||||||
|
|
||||||
return r.getRules().isEmpty() ? null : r;
|
return r.getRules().isEmpty() ? null : r;
|
||||||
|
|
|
@ -272,6 +272,13 @@ public final class Constants {
|
||||||
*/
|
*/
|
||||||
public static final String INFO_EXCLUDE = "info/exclude";
|
public static final String INFO_EXCLUDE = "info/exclude";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes-override-file
|
||||||
|
*
|
||||||
|
* @since 4.2
|
||||||
|
*/
|
||||||
|
public static final String INFO_ATTRIBUTES = "info/attributes";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The system property that contains the system user name
|
* The system property that contains the system user name
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,17 +45,16 @@
|
||||||
package org.eclipse.jgit.treewalk;
|
package org.eclipse.jgit.treewalk;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jgit.annotations.Nullable;
|
import org.eclipse.jgit.annotations.Nullable;
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||||
import org.eclipse.jgit.attributes.Attribute;
|
import org.eclipse.jgit.attributes.Attribute;
|
||||||
|
import org.eclipse.jgit.attributes.Attributes;
|
||||||
import org.eclipse.jgit.attributes.AttributesNode;
|
import org.eclipse.jgit.attributes.AttributesNode;
|
||||||
import org.eclipse.jgit.attributes.AttributesNodeProvider;
|
import org.eclipse.jgit.attributes.AttributesNodeProvider;
|
||||||
import org.eclipse.jgit.attributes.AttributesProvider;
|
import org.eclipse.jgit.attributes.AttributesProvider;
|
||||||
|
import org.eclipse.jgit.attributes.Attribute.State;
|
||||||
import org.eclipse.jgit.dircache.DirCacheIterator;
|
import org.eclipse.jgit.dircache.DirCacheIterator;
|
||||||
import org.eclipse.jgit.errors.CorruptObjectException;
|
import org.eclipse.jgit.errors.CorruptObjectException;
|
||||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
@ -258,7 +257,7 @@ public static TreeWalk forPath(final Repository db, final String path,
|
||||||
AbstractTreeIterator currentHead;
|
AbstractTreeIterator currentHead;
|
||||||
|
|
||||||
/** Cached attribute for the current entry */
|
/** Cached attribute for the current entry */
|
||||||
private Map<String, Attribute> attrs = null;
|
private Attributes attrs = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new tree walker for a given repository.
|
* Create a new tree walker for a given repository.
|
||||||
|
@ -1119,7 +1118,7 @@ static String pathOf(final byte[] buf, int pos, int end) {
|
||||||
* @return a {@link Set} of {@link Attribute}s that match the current entry.
|
* @return a {@link Set} of {@link Attribute}s that match the current entry.
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public Map<String, Attribute> getAttributes() {
|
public Attributes getAttributes() {
|
||||||
if (attrs != null)
|
if (attrs != null)
|
||||||
return attrs;
|
return attrs;
|
||||||
|
|
||||||
|
@ -1138,35 +1137,42 @@ public Map<String, Attribute> getAttributes() {
|
||||||
&& other == null) {
|
&& other == null) {
|
||||||
// Can not retrieve the attributes without at least one of the above
|
// Can not retrieve the attributes without at least one of the above
|
||||||
// iterators.
|
// iterators.
|
||||||
return Collections.<String, Attribute> emptyMap();
|
return new Attributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = currentHead.getEntryPathString();
|
String path = currentHead.getEntryPathString();
|
||||||
final boolean isDir = FileMode.TREE.equals(currentHead.mode);
|
final boolean isDir = FileMode.TREE.equals(currentHead.mode);
|
||||||
Map<String, Attribute> attributes = new LinkedHashMap<String, Attribute>();
|
Attributes attributes = new Attributes();
|
||||||
try {
|
try {
|
||||||
// Gets the info attributes
|
// Gets the global attributes node
|
||||||
|
AttributesNode globalNodeAttr = attributesNodeProvider
|
||||||
|
.getGlobalAttributesNode();
|
||||||
|
// Gets the info attributes node
|
||||||
AttributesNode infoNodeAttr = attributesNodeProvider
|
AttributesNode infoNodeAttr = attributesNodeProvider
|
||||||
.getInfoAttributesNode();
|
.getInfoAttributesNode();
|
||||||
|
|
||||||
|
// Gets the info attributes
|
||||||
if (infoNodeAttr != null) {
|
if (infoNodeAttr != null) {
|
||||||
infoNodeAttr.getAttributes(path, isDir, attributes);
|
infoNodeAttr.getAttributes(path, isDir, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Gets the attributes located on the current entry path
|
// Gets the attributes located on the current entry path
|
||||||
getPerDirectoryEntryAttributes(path, isDir, operationType,
|
getPerDirectoryEntryAttributes(path, isDir, operationType,
|
||||||
workingTreeIterator, dirCacheIterator, other,
|
workingTreeIterator, dirCacheIterator, other, attributes);
|
||||||
attributes);
|
|
||||||
|
|
||||||
// Gets the attributes located in the global attribute file
|
// Gets the attributes located in the global attribute file
|
||||||
AttributesNode globalNodeAttr = attributesNodeProvider
|
|
||||||
.getGlobalAttributesNode();
|
|
||||||
if (globalNodeAttr != null) {
|
if (globalNodeAttr != null) {
|
||||||
globalNodeAttr.getAttributes(path, isDir, attributes);
|
globalNodeAttr.getAttributes(path, isDir, attributes);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JGitInternalException("Error while parsing attributes", e); //$NON-NLS-1$
|
throw new JGitInternalException("Error while parsing attributes", e); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
// now after all attributes are collected - in the correct hierarchy
|
||||||
|
// order - remove all unspecified entries (the ! marker)
|
||||||
|
for (Attribute a : attributes.getAll()) {
|
||||||
|
if (a.getState() == State.UNSPECIFIED)
|
||||||
|
attributes.remove(a.getKey());
|
||||||
|
}
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1195,7 +1201,7 @@ public Map<String, Attribute> getAttributes() {
|
||||||
private void getPerDirectoryEntryAttributes(String path, boolean isDir,
|
private void getPerDirectoryEntryAttributes(String path, boolean isDir,
|
||||||
OperationType opType, WorkingTreeIterator workingTreeIterator,
|
OperationType opType, WorkingTreeIterator workingTreeIterator,
|
||||||
DirCacheIterator dirCacheIterator, CanonicalTreeParser other,
|
DirCacheIterator dirCacheIterator, CanonicalTreeParser other,
|
||||||
Map<String, Attribute> attributes)
|
Attributes attributes)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// Prevents infinite recurrence
|
// Prevents infinite recurrence
|
||||||
if (workingTreeIterator != null || dirCacheIterator != null
|
if (workingTreeIterator != null || dirCacheIterator != null
|
||||||
|
@ -1208,12 +1214,11 @@ private void getPerDirectoryEntryAttributes(String path, boolean isDir,
|
||||||
getPerDirectoryEntryAttributes(path, isDir, opType,
|
getPerDirectoryEntryAttributes(path, isDir, opType,
|
||||||
getParent(workingTreeIterator, WorkingTreeIterator.class),
|
getParent(workingTreeIterator, WorkingTreeIterator.class),
|
||||||
getParent(dirCacheIterator, DirCacheIterator.class),
|
getParent(dirCacheIterator, DirCacheIterator.class),
|
||||||
getParent(other, CanonicalTreeParser.class),
|
getParent(other, CanonicalTreeParser.class), attributes);
|
||||||
attributes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends AbstractTreeIterator> T getParent(T current,
|
private static <T extends AbstractTreeIterator> T getParent(T current,
|
||||||
Class<T> type) {
|
Class<T> type) {
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
AbstractTreeIterator parent = current.parent;
|
AbstractTreeIterator parent = current.parent;
|
||||||
|
@ -1224,7 +1229,7 @@ private <T extends AbstractTreeIterator> T getParent(T current,
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getTree(Class<T> type) {
|
private <T extends AbstractTreeIterator> T getTree(Class<T> type) {
|
||||||
for (int i = 0; i < trees.length; i++) {
|
for (int i = 0; i < trees.length; i++) {
|
||||||
AbstractTreeIterator tree = trees[i];
|
AbstractTreeIterator tree = trees[i];
|
||||||
if (type.isInstance(tree)) {
|
if (type.isInstance(tree)) {
|
||||||
|
|
Loading…
Reference in New Issue