diff options
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes')
5 files changed, 1249 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java new file mode 100644 index 0000000000..ea250369a0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2014, Obeo. + * and other copyright owners as documented in the project's IP log. + * + * 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 static org.eclipse.jgit.attributes.Attribute.State.SET; +import static org.eclipse.jgit.attributes.Attribute.State.UNSET; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +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.Test; + +/** + * Test {@link AttributesNode} + */ +public class AttributeNodeTest { + + private static final Attribute A_SET_ATTR = new Attribute("A", SET); + + private static final Attribute A_UNSET_ATTR = new Attribute("A", UNSET); + + private static final Attribute B_SET_ATTR = new Attribute("B", SET); + + private static final Attribute B_UNSET_ATTR = new Attribute("B", UNSET); + + private static final Attribute C_VALUE_ATTR = new Attribute("C", "value"); + + private static final Attribute C_VALUE2_ATTR = new Attribute("C", "value2"); + + private InputStream is; + + @After + public void after() throws IOException { + if (is != null) + is.close(); + } + + @Test + public void testBasic() throws IOException { + String attributeFileContent = "*.type1 A -B C=value\n" + + "*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + } + + @Test + public void testNegativePattern() throws IOException { + String attributeFileContent = "!*.type1 A -B C=value\n" + + "!*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, Collections.<Attribute> emptySet()); + } + + @Test + public void testEmptyNegativeAttributeKey() throws IOException { + String attributeFileContent = "*.type1 - \n" // + + "*.type2 - -A"; + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, asSet(A_UNSET_ATTR)); + } + + @Test + public void testEmptyValueKey() throws IOException { + String attributeFileContent = "*.type1 = \n" // + + "*.type2 =value\n"// + + "*.type3 attr=\n"; + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type3", node, asSet(new Attribute("attr", ""))); + } + + @Test + public void testEmptyLine() throws IOException { + String attributeFileContent = "*.type1 A -B C=value\n" // + + "\n" // + + " \n" // + + "*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + } + + @Test + public void testTabSeparator() throws IOException { + String attributeFileContent = "*.type1 \tA -B\tC=value\n" + + "*.type2\t -A\tB C=value2\n" // + + "*.type3 \t\t B\n" // + + "*.type3\t-A";// + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + assertAttribute("file.type3", node, asSet(A_UNSET_ATTR, B_SET_ATTR)); + } + + private void assertAttribute(String path, AttributesNode node, + Set<Attribute> attrs) { + HashMap<String, Attribute> attributes = new HashMap<String, Attribute>(); + node.getAttributes(path, false, attributes); + assertEquals(attrs, new HashSet<Attribute>(attributes.values())); + } + + static Set<Attribute> asSet(Attribute... attrs) { + Set<Attribute> result = new HashSet<Attribute>(); + for (Attribute attr : attrs) + result.add(attr); + return result; + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java new file mode 100644 index 0000000000..93b954fa9a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010, Marc Strapetz <marc.strapetz@syntevo.com> + * Copyright (C) 2013, Gunnar Wagenknecht + * and other copyright owners as documented in the project's IP log. + * + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.eclipse.jgit.attributes.Attribute.State; +import org.junit.Test; + +/** + * Tests {@link Attribute} + */ +public class AttributeTest { + + @Test + public void testBasic() { + Attribute a = new Attribute("delta", State.SET); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.SET); + assertNull(a.getValue()); + assertEquals(a.toString(), "delta"); + + a = new Attribute("delta", State.UNSET); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.UNSET); + assertNull(a.getValue()); + assertEquals(a.toString(), "-delta"); + + a = new Attribute("delta", "value"); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.CUSTOM); + assertEquals(a.getValue(), "value"); + assertEquals(a.toString(), "delta=value"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java new file mode 100644 index 0000000000..6865406927 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2010, Red Hat Inc. + * and other copyright owners as documented in the project's IP log. + * + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Tests git attributes pattern matches + * <p> + * Inspired by {@link org.eclipse.jgit.ignore.IgnoreMatcherTest} + * </p> + */ +public class AttributesMatcherTest { + + @Test + public void testBasic() { + String pattern = "/test.stp"; + assertMatched(pattern, "/test.stp"); + + pattern = "#/test.stp"; + assertNotMatched(pattern, "/test.stp"); + } + + @Test + public void testFileNameWildcards() { + //Test basic * and ? for any pattern + any character + String pattern = "*.st?"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/anothertest.stg"); + assertMatched(pattern, "/anothertest.st0"); + assertNotMatched(pattern, "/anothertest.sta1"); + //Check that asterisk does not expand to "/" + assertNotMatched(pattern, "/another/test.sta1"); + + //Same as above, with a leading slash to ensure that doesn't cause problems + pattern = "/*.st?"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/anothertest.stg"); + assertMatched(pattern, "/anothertest.st0"); + assertNotMatched(pattern, "/anothertest.sta1"); + //Check that asterisk does not expand to "/" + assertNotMatched(pattern, "/another/test.sta1"); + + //Test for numbers + pattern = "*.sta[0-5]"; + assertMatched(pattern, "/test.sta5"); + assertMatched(pattern, "/test.sta4"); + assertMatched(pattern, "/test.sta3"); + assertMatched(pattern, "/test.sta2"); + assertMatched(pattern, "/test.sta1"); + assertMatched(pattern, "/test.sta0"); + assertMatched(pattern, "/anothertest.sta2"); + assertNotMatched(pattern, "test.stag"); + assertNotMatched(pattern, "test.sta6"); + + //Test for letters + pattern = "/[tv]est.sta[a-d]"; + assertMatched(pattern, "/test.staa"); + assertMatched(pattern, "/test.stab"); + assertMatched(pattern, "/test.stac"); + assertMatched(pattern, "/test.stad"); + assertMatched(pattern, "/vest.stac"); + assertNotMatched(pattern, "test.stae"); + assertNotMatched(pattern, "test.sta9"); + + //Test child directory/file is matched + pattern = "/src/ne?"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new.c"); + + //Test name-only fnmatcher matches + pattern = "ne?"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertMatched(pattern, "/neb"); + assertNotMatched(pattern, "/src/new.c"); + } + + @Test + public void testTargetWithoutLeadingSlash() { + //Test basic * and ? for any pattern + any character + String pattern = "/*.st?"; + assertMatched(pattern, "test.stp"); + assertMatched(pattern, "anothertest.stg"); + assertMatched(pattern, "anothertest.st0"); + assertNotMatched(pattern, "anothertest.sta1"); + //Check that asterisk does not expand to "" + assertNotMatched(pattern, "another/test.sta1"); + + //Same as above, with a leading slash to ensure that doesn't cause problems + pattern = "/*.st?"; + assertMatched(pattern, "test.stp"); + assertMatched(pattern, "anothertest.stg"); + assertMatched(pattern, "anothertest.st0"); + assertNotMatched(pattern, "anothertest.sta1"); + //Check that asterisk does not expand to "" + assertNotMatched(pattern, "another/test.sta1"); + + //Test for numbers + pattern = "/*.sta[0-5]"; + assertMatched(pattern, "test.sta5"); + assertMatched(pattern, "test.sta4"); + assertMatched(pattern, "test.sta3"); + assertMatched(pattern, "test.sta2"); + assertMatched(pattern, "test.sta1"); + assertMatched(pattern, "test.sta0"); + assertMatched(pattern, "anothertest.sta2"); + assertNotMatched(pattern, "test.stag"); + assertNotMatched(pattern, "test.sta6"); + + //Test for letters + pattern = "/[tv]est.sta[a-d]"; + assertMatched(pattern, "test.staa"); + assertMatched(pattern, "test.stab"); + assertMatched(pattern, "test.stac"); + assertMatched(pattern, "test.stad"); + assertMatched(pattern, "vest.stac"); + assertNotMatched(pattern, "test.stae"); + assertNotMatched(pattern, "test.sta9"); + + //Test child directory/file is matched + pattern = "/src/ne?"; + assertMatched(pattern, "src/new/"); + assertMatched(pattern, "src/new"); + assertMatched(pattern, "src/new/a.c"); + assertMatched(pattern, "src/new/a/a.c"); + assertNotMatched(pattern, "src/new.c"); + + //Test name-only fnmatcher matches + pattern = "ne?"; + assertMatched(pattern, "src/new/"); + assertMatched(pattern, "src/new"); + assertMatched(pattern, "src/new/a.c"); + assertMatched(pattern, "src/new/a/a.c"); + assertMatched(pattern, "neb"); + assertNotMatched(pattern, "src/new.c"); + } + + @Test + public void testParentDirectoryGitAttributes() { + //Contains git attribute patterns such as might be seen in a parent directory + + //Test for wildcards + String pattern = "/*/*.c"; + assertMatched(pattern, "/file/a.c"); + assertMatched(pattern, "/src/a.c"); + assertNotMatched(pattern, "/src/new/a.c"); + + //Test child directory/file is matched + pattern = "/src/new"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new.c"); + + //Test child directory is matched, slash after name + pattern = "/src/new/"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new"); + assertNotMatched(pattern, "/src/new.c"); + + //Test directory is matched by name only + pattern = "b1"; + assertMatched(pattern, "/src/new/a/b1/a.c"); + assertNotMatched(pattern, "/src/new/a/b2/file.c"); + assertNotMatched(pattern, "/src/new/a/bb1/file.c"); + assertNotMatched(pattern, "/src/new/a/file.c"); + } + + @Test + public void testTrailingSlash() { + String pattern = "/src/"; + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/a.c"); + assertNotMatched(pattern, "/src"); + assertNotMatched(pattern, "/srcA/"); + } + + @Test + public void testNameOnlyMatches() { + /* + * Name-only matches do not contain any path separators + */ + //Test matches for file extension + String pattern = "*.stp"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/src/test.stp"); + assertNotMatched(pattern, "/test.stp1"); + assertNotMatched(pattern, "/test.astp"); + + //Test matches for name-only, applies to file name or folder name + pattern = "src"; + assertMatched(pattern, "/src"); + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + + //Test matches for name-only, applies only to folder names + pattern = "src/"; + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertNotMatched(pattern, "/src"); + assertNotMatched(pattern, "/file/src"); + + //Test matches for name-only, applies to file name or folder name + //With a small wildcard + pattern = "?rc"; + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + assertMatched(pattern, "/src/"); + + //Test matches for name-only, applies to file name or folder name + //With a small wildcard + pattern = "?r[a-c]"; + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/srb/a.c"); + assertMatched(pattern, "/grb/new/a.c"); + assertMatched(pattern, "/new/crb/a.c"); + assertMatched(pattern, "/file/3rb"); + assertMatched(pattern, "/xrb/"); + assertMatched(pattern, "/3ra/a.c"); + assertMatched(pattern, "/5ra/new/a.c"); + assertMatched(pattern, "/new/1ra/a.c"); + assertMatched(pattern, "/file/dra"); + assertMatched(pattern, "/era/"); + assertNotMatched(pattern, "/crg"); + assertNotMatched(pattern, "/cr3"); + } + + @Test + public void testGetters() { + AttributesRule r = new AttributesRule("/pattern/", ""); + assertFalse(r.isNameOnly()); + assertTrue(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "/pattern"); + + r = new AttributesRule("/patter?/", ""); + assertFalse(r.isNameOnly()); + assertTrue(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "/patter?"); + + r = new AttributesRule("patt*", ""); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "patt*"); + + r = new AttributesRule("pattern", "attribute1"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertFalse(r.getAttributes().isEmpty()); + assertEquals(r.getAttributes().size(), 1); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1 -attribute2"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1 \t-attribute2 \t"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1\t-attribute2\t"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1\t -attribute2\t "); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", + "attribute1 -attribute2 attribute3=value "); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 3); + assertEquals(r.getPattern(), "pattern"); + assertEquals(r.getAttributes().get(0).toString(), "attribute1"); + assertEquals(r.getAttributes().get(1).toString(), "-attribute2"); + assertEquals(r.getAttributes().get(2).toString(), "attribute3=value"); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + */ + public void assertMatched(String pattern, String target) { + boolean value = match(pattern, target); + assertTrue("Expected a match for: " + pattern + " with: " + target, + value); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + */ + public void assertNotMatched(String pattern, String target) { + boolean value = match(pattern, target); + assertFalse("Expected no match for: " + pattern + " with: " + target, + value); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + * @return Result of {@link AttributesRule#isMatch(String, boolean)} + */ + private static boolean match(String pattern, String target) { + AttributesRule r = new AttributesRule(pattern, ""); + //If speed of this test is ever an issue, we can use a presetRule field + //to avoid recompiling a pattern each time. + return r.isMatch(target, target.endsWith("/")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java new file mode 100644 index 0000000000..49279e6e5a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2010, Red Hat Inc. + * and other copyright owners as documented in the project's IP log. + * + * 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 static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.attributes.Attribute.State; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests attributes node behavior on the the index. + */ +public class AttributesNodeDirCacheIteratorTest extends RepositoryTestCase { + + private static final FileMode D = FileMode.TREE; + + private static final FileMode F = FileMode.REGULAR_FILE; + + private static Attribute EOL_LF = new Attribute("eol", "lf"); + + private static Attribute DELTA_UNSET = new Attribute("delta", State.UNSET); + + private Git git; + + private TreeWalk walk; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + + } + + @Test + public void testRules() throws Exception { + writeAttributesFile(".git/info/attributes", "windows* eol=crlf"); + + writeAttributesFile(".gitattributes", "*.txt eol=lf"); + writeTrashFile("windows.file", ""); + writeTrashFile("windows.txt", ""); + writeTrashFile("readme.txt", ""); + + writeAttributesFile("src/config/.gitattributes", "*.txt -delta"); + writeTrashFile("src/config/readme.txt", ""); + writeTrashFile("src/config/windows.file", ""); + writeTrashFile("src/config/windows.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "readme.txt", asList(EOL_LF)); + + assertIteration(D, "src"); + + assertIteration(D, "src/config"); + assertIteration(F, "src/config/.gitattributes"); + assertIteration(F, "src/config/readme.txt", asList(DELTA_UNSET)); + assertIteration(F, "src/config/windows.file", null); + assertIteration(F, "src/config/windows.txt", asList(DELTA_UNSET)); + + assertIteration(F, "windows.file", null); + assertIteration(F, "windows.txt", asList(EOL_LF)); + + endWalk(); + } + + /** + * Checks that if there is no .gitattributes file in the repository + * everything still work fine. + * + * @throws Exception + */ + @Test + public void testNoAttributes() throws Exception { + writeTrashFile("l0.txt", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + /** + * Checks that empty .gitattribute files do not return incorrect value. + * + * @throws Exception + */ + @Test + public void testEmptyGitAttributeFile() throws Exception { + writeAttributesFile(".git/info/attributes", ""); + writeTrashFile("l0.txt", ""); + writeAttributesFile(".gitattributes", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + @Test + public void testNoMatchingAttributes() throws Exception { + writeAttributesFile(".git/info/attributes", "*.java delta"); + writeAttributesFile(".gitattributes", "*.java -delta"); + writeAttributesFile("levelA/.gitattributes", "*.java eol=lf"); + writeAttributesFile("levelB/.gitattributes", "*.txt eol=lf"); + + writeTrashFile("levelA/lA.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + assertIteration(D, "levelB"); + assertIteration(F, "levelB/.gitattributes"); + + endWalk(); + } + + @Test + public void testIncorrectAttributeFileName() throws Exception { + writeAttributesFile("levelA/file.gitattributes", "*.txt -delta"); + writeAttributesFile("gitattributes", "*.txt eol=lf"); + + writeTrashFile("l0.txt", ""); + writeTrashFile("levelA/lA.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, "gitattributes"); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/file.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + endWalk(); + } + + private void assertIteration(FileMode type, String pathName) + throws IOException { + assertIteration(type, pathName, Collections.<Attribute> emptyList()); + } + + private void assertIteration(FileMode type, String pathName, + List<Attribute> nodeAttrs) throws IOException { + assertTrue("walk has entry", walk.next()); + assertEquals(pathName, walk.getPathString()); + assertEquals(type, walk.getFileMode(0)); + DirCacheIterator itr = walk.getTree(0, DirCacheIterator.class); + assertNotNull("has tree", itr); + + AttributesNode attributeNode = itr.getEntryAttributesNode(db + .newObjectReader()); + assertAttributeNode(pathName, attributeNode, nodeAttrs); + + if (D.equals(type)) + walk.enterSubtree(); + + } + + private void assertAttributeNode(String pathName, + AttributesNode attributeNode, List<Attribute> nodeAttrs) { + if (attributeNode == null) + assertTrue(nodeAttrs == null || nodeAttrs.isEmpty()); + else { + + Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>(); + attributeNode.getAttributes(pathName, false, entryAttributes); + + if (nodeAttrs != null && !nodeAttrs.isEmpty()) { + for (Attribute attribute : nodeAttrs) { + assertThat(entryAttributes.values(), hasItem(attribute)); + } + } else { + assertTrue( + "The entry " + + pathName + + " should not have any attributes. Instead, the following attributes are applied to this file " + + entryAttributes.toString(), + entryAttributes.isEmpty()); + } + } + } + + private void writeAttributesFile(String name, String... rules) + throws IOException { + StringBuilder data = new StringBuilder(); + for (String line : rules) + data.append(line + "\n"); + writeTrashFile(name, data.toString()); + } + + private TreeWalk beginWalk() throws Exception { + TreeWalk newWalk = new TreeWalk(db); + newWalk.addTree(new DirCacheIterator(db.readDirCache())); + return newWalk; + } + + private void endWalk() throws IOException { + assertFalse("Not all files tested", walk.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java new file mode 100644 index 0000000000..64b0535d6a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2014, Obeo. + * and other copyright owners as documented in the project's IP log. + * + * 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 static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.attributes.Attribute.State; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.FileTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.WorkingTreeIterator; +import org.junit.Test; + +/** + * Tests attributes node behavior on the local filesystem. + */ +public class AttributesNodeWorkingTreeIteratorTest extends RepositoryTestCase { + + private static final FileMode D = FileMode.TREE; + + private static final FileMode F = FileMode.REGULAR_FILE; + + private static Attribute EOL_CRLF = new Attribute("eol", "crlf"); + + private static Attribute EOL_LF = new Attribute("eol", "lf"); + + private static Attribute DELTA_UNSET = new Attribute("delta", State.UNSET); + + private static Attribute CUSTOM_VALUE = new Attribute("custom", "value"); + + private TreeWalk walk; + + @Test + public void testRules() throws Exception { + + File customAttributeFile = File.createTempFile("tmp_", + "customAttributeFile", null); + customAttributeFile.deleteOnExit(); + + JGitTestUtil.write(customAttributeFile, "*.txt custom=value"); + db.getConfig().setString("core", null, "attributesfile", + customAttributeFile.getAbsolutePath()); + writeAttributesFile(".git/info/attributes", "windows* eol=crlf"); + + writeAttributesFile(".gitattributes", "*.txt eol=lf"); + writeTrashFile("windows.file", ""); + writeTrashFile("windows.txt", ""); + writeTrashFile("global.txt", ""); + writeTrashFile("readme.txt", ""); + + writeAttributesFile("src/config/.gitattributes", "*.txt -delta"); + writeTrashFile("src/config/readme.txt", ""); + writeTrashFile("src/config/windows.file", ""); + writeTrashFile("src/config/windows.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "global.txt", asList(EOL_LF), null, + asList(CUSTOM_VALUE)); + assertIteration(F, "readme.txt", asList(EOL_LF), null, + asList(CUSTOM_VALUE)); + + assertIteration(D, "src"); + + assertIteration(D, "src/config"); + assertIteration(F, "src/config/.gitattributes"); + assertIteration(F, "src/config/readme.txt", asList(DELTA_UNSET), null, + asList(CUSTOM_VALUE)); + assertIteration(F, "src/config/windows.file", null, asList(EOL_CRLF), + null); + assertIteration(F, "src/config/windows.txt", asList(DELTA_UNSET), + asList(EOL_CRLF), asList(CUSTOM_VALUE)); + + assertIteration(F, "windows.file", null, asList(EOL_CRLF), null); + assertIteration(F, "windows.txt", asList(EOL_LF), asList(EOL_CRLF), + asList(CUSTOM_VALUE)); + + endWalk(); + } + + /** + * Checks that if there is no .gitattributes file in the repository + * everything still work fine. + * + * @throws Exception + */ + @Test + public void testNoAttributes() throws Exception { + writeTrashFile("l0.txt", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + walk = beginWalk(); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + /** + * Checks that empty .gitattribute files do not return incorrect value. + * + * @throws Exception + */ + @Test + public void testEmptyGitAttributeFile() throws Exception { + writeAttributesFile(".git/info/attributes", ""); + writeTrashFile("l0.txt", ""); + writeAttributesFile(".gitattributes", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + @Test + public void testNoMatchingAttributes() throws Exception { + writeAttributesFile(".git/info/attributes", "*.java delta"); + writeAttributesFile(".gitattributes", "*.java -delta"); + writeAttributesFile("levelA/.gitattributes", "*.java eol=lf"); + writeAttributesFile("levelB/.gitattributes", "*.txt eol=lf"); + + writeTrashFile("levelA/lA.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + assertIteration(D, "levelB"); + assertIteration(F, "levelB/.gitattributes"); + + endWalk(); + } + + private void assertIteration(FileMode type, String pathName) + throws IOException { + assertIteration(type, pathName, Collections.<Attribute> emptyList(), + Collections.<Attribute> emptyList(), + Collections.<Attribute> emptyList()); + } + + private void assertIteration(FileMode type, String pathName, + List<Attribute> nodeAttrs, List<Attribute> infoAttrs, + List<Attribute> globalAttrs) + throws IOException { + assertTrue("walk has entry", walk.next()); + assertEquals(pathName, walk.getPathString()); + assertEquals(type, walk.getFileMode(0)); + WorkingTreeIterator itr = walk.getTree(0, WorkingTreeIterator.class); + assertNotNull("has tree", itr); + + AttributesNode attributeNode = itr.getEntryAttributesNode(); + assertAttributeNode(pathName, attributeNode, nodeAttrs); + AttributesNode infoAttributeNode = itr.getInfoAttributesNode(); + assertAttributeNode(pathName, infoAttributeNode, infoAttrs); + AttributesNode globalAttributeNode = itr.getGlobalAttributesNode(); + assertAttributeNode(pathName, globalAttributeNode, globalAttrs); + if (D.equals(type)) + walk.enterSubtree(); + + } + + private void assertAttributeNode(String pathName, + AttributesNode attributeNode, List<Attribute> nodeAttrs) { + if (attributeNode == null) + assertTrue(nodeAttrs == null || nodeAttrs.isEmpty()); + else { + + Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>(); + attributeNode.getAttributes(pathName, false, entryAttributes); + + if (nodeAttrs != null && !nodeAttrs.isEmpty()) { + for (Attribute attribute : nodeAttrs) { + assertThat(entryAttributes.values(), hasItem(attribute)); + } + } else { + assertTrue( + "The entry " + + pathName + + " should not have any attributes. Instead, the following attributes are applied to this file " + + entryAttributes.toString(), + entryAttributes.isEmpty()); + } + } + } + + private void writeAttributesFile(String name, String... rules) + throws IOException { + StringBuilder data = new StringBuilder(); + for (String line : rules) + data.append(line + "\n"); + writeTrashFile(name, data.toString()); + } + + private TreeWalk beginWalk() throws CorruptObjectException { + TreeWalk newWalk = new TreeWalk(db); + newWalk.addTree(new FileTreeIterator(db)); + return newWalk; + } + + private void endWalk() throws IOException { + assertFalse("Not all files tested", walk.next()); + } +} |