diff options
Diffstat (limited to 'org.eclipse.jgit.test/tst')
22 files changed, 1437 insertions, 334 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java index 1e3a39aad8..2a553ce1a2 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/EolStreamTypeUtilTest.java @@ -1,43 +1,11 @@ /* - * Copyright (C) 2015, Ivan Motsch <ivan.motsch@bsiag.com> + * Copyright (C) 2015, 2020 Ivan Motsch <ivan.motsch@bsiag.com> and others * - * 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 + * 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. * - * 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. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.api; @@ -90,16 +58,20 @@ public class EolStreamTypeUtilTest { testCheckout(TEXT_LF, AUTO_LF, "\r", "\r"); testCheckout(TEXT_LF, AUTO_LF, "\n", "\n"); - testCheckout(TEXT_LF, AUTO_LF, "\r\n", "\n"); + testCheckout(TEXT_LF, null, "\r\n", "\n"); + testCheckout(null, AUTO_LF, "\r\n", "\r\n"); testCheckout(TEXT_LF, AUTO_LF, "\n\r", "\n\r"); - testCheckout(TEXT_LF, AUTO_LF, "\n\r\n", "\n\n"); - testCheckout(TEXT_LF, AUTO_LF, "\r\n\r", "\n\r"); + testCheckout(TEXT_LF, null, "\n\r\n", "\n\n"); + testCheckout(null, AUTO_LF, "\n\r\n", "\n\r\n"); + testCheckout(TEXT_LF, null, "\r\n\r", "\n\r"); + testCheckout(null, AUTO_LF, "\r\n\r", "\r\n\r"); testCheckout(TEXT_LF, AUTO_LF, "a\nb\n", "a\nb\n"); testCheckout(TEXT_LF, AUTO_LF, "a\rb\r", "a\rb\r"); testCheckout(TEXT_LF, AUTO_LF, "a\n\rb\n\r", "a\n\rb\n\r"); - testCheckout(TEXT_LF, AUTO_LF, "a\r\nb\r\n", "a\nb\n"); + testCheckout(TEXT_LF, null, "a\r\nb\r\n", "a\nb\n"); + testCheckout(null, AUTO_LF, "a\r\nb\r\n", "a\r\nb\r\n"); } @Test @@ -153,45 +125,49 @@ public class EolStreamTypeUtilTest { byte[] outputBytes = output.getBytes(UTF_8); byte[] expectedConversionBytes = expectedConversion.getBytes(UTF_8); - // test using output text and assuming it was declared TEXT - b = new ByteArrayOutputStream(); - try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, - streamTypeText)) { - out.write(outputBytes); + if (streamTypeText != null) { + // test using output text and assuming it was declared TEXT + b = new ByteArrayOutputStream(); + try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, + streamTypeText)) { + out.write(outputBytes); + } + assertArrayEquals(expectedConversionBytes, b.toByteArray()); } - assertArrayEquals(expectedConversionBytes, b.toByteArray()); - - // test using ouput text and assuming it was declared AUTO, using binary - // detection - b = new ByteArrayOutputStream(); - try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, - streamTypeWithBinaryCheck)) { - out.write(outputBytes); + if (streamTypeWithBinaryCheck != null) { + // test using output text and assuming it was declared AUTO, using + // binary detection + b = new ByteArrayOutputStream(); + try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, + streamTypeWithBinaryCheck)) { + out.write(outputBytes); + } + assertArrayEquals(expectedConversionBytes, b.toByteArray()); } - assertArrayEquals(expectedConversionBytes, b.toByteArray()); - // now pollute output text with some binary bytes outputBytes = extendWithBinaryData(outputBytes); expectedConversionBytes = extendWithBinaryData(expectedConversionBytes); - // again, test using output text and assuming it was declared TEXT - b = new ByteArrayOutputStream(); - try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, - streamTypeText)) { - out.write(outputBytes); + if (streamTypeText != null) { + // again, test using output text and assuming it was declared TEXT + b = new ByteArrayOutputStream(); + try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, + streamTypeText)) { + out.write(outputBytes); + } + assertArrayEquals(expectedConversionBytes, b.toByteArray()); } - assertArrayEquals(expectedConversionBytes, b.toByteArray()); - - // again, test using ouput text and assuming it was declared AUTO, using - // binary - // detection - b = new ByteArrayOutputStream(); - try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, - streamTypeWithBinaryCheck)) { - out.write(outputBytes); + if (streamTypeWithBinaryCheck != null) { + // again, test using output text and assuming it was declared AUTO, + // using binary detection + b = new ByteArrayOutputStream(); + try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, + streamTypeWithBinaryCheck)) { + out.write(outputBytes); + } + // expect no conversion + assertArrayEquals(outputBytes, b.toByteArray()); } - // expect no conversion - assertArrayEquals(outputBytes, b.toByteArray()); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java index 3d46a47ced..62824d3aec 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2013 Google Inc. and others + * Copyright (C) 2010, 2020 Google 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 @@ -11,12 +11,16 @@ package org.eclipse.jgit.diff; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.Status; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.junit.RepositoryTestCase; @@ -74,6 +78,17 @@ public class DiffFormatterTest extends RepositoryTestCase { } @Test + public void testDefaultRenameDetectorSettings() throws Exception { + RenameDetector rd = df.getRenameDetector(); + assertNull(rd); + df.setDetectRenames(true); + rd = df.getRenameDetector(); + assertNotNull(rd); + assertEquals(400, rd.getRenameLimit()); + assertEquals(60, rd.getRenameScore()); + } + + @Test public void testCreateFileHeader_Add() throws Exception { ObjectId adId = blob("a\nd\n"); DiffEntry ent = DiffEntry.add("FOO", adId); @@ -455,6 +470,58 @@ public class DiffFormatterTest extends RepositoryTestCase { } @Test + public void testTrackedFileInIgnoredFolderUnchanged() + throws Exception { + commitFile("empty/empty/foo", "", "master"); + commitFile(".gitignore", "empty/*", "master"); + try (Git git = new Git(db)) { + Status status = git.status().call(); + assertTrue(status.isClean()); + } + try (ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(os)) { + dfmt.setRepository(db); + dfmt.format(new DirCacheIterator(db.readDirCache()), + new FileTreeIterator(db)); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + + assertEquals("", actual); + } + } + + @Test + public void testTrackedFileInIgnoredFolderChanged() + throws Exception { + String expectedDiff = "diff --git a/empty/empty/foo b/empty/empty/foo\n" + + "index e69de29..5ea2ed4 100644\n" // + + "--- a/empty/empty/foo\n" // + + "+++ b/empty/empty/foo\n" // + + "@@ -0,0 +1 @@\n" // + + "+changed\n"; + + commitFile("empty/empty/foo", "", "master"); + commitFile(".gitignore", "empty/*", "master"); + try (Git git = new Git(db)) { + Status status = git.status().call(); + assertTrue(status.isClean()); + } + try (ByteArrayOutputStream os = new ByteArrayOutputStream(); + DiffFormatter dfmt = new DiffFormatter(os)) { + writeTrashFile("empty/empty/foo", "changed\n"); + dfmt.setRepository(db); + dfmt.format(new DirCacheIterator(db.readDirCache()), + new FileTreeIterator(db)); + dfmt.flush(); + + String actual = os.toString("UTF-8"); + + assertEquals(expectedDiff, actual); + } + } + + @Test public void testDiffAutoCrlfSmallFile() throws Exception { String content = "01234\r\n01234\r\n01234\r\n"; String expectedDiff = "diff --git a/test.txt b/test.txt\n" diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheAfterCloneTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheAfterCloneTest.java new file mode 100644 index 0000000000..f210760bf5 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheAfterCloneTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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.dircache; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.EnumSet; +import java.util.Set; + +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.util.FileUtils; +import org.eclipse.jgit.util.SystemReader; +import org.junit.Test; + +/** + * Tests for initial DirCache version after a clone or after a mixed or hard + * reset. + */ +public class DirCacheAfterCloneTest extends RepositoryTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + try (Git git = new Git(db)) { + writeTrashFile("Test.txt", "Hello world"); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Initial commit").call(); + } + } + + private DirCacheVersion cloneAndCheck(Set<DirCacheVersion> expected) + throws Exception { + File directory = createTempDirectory("testCloneRepository"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI("file://" + db.getWorkTree().getAbsolutePath()); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + assertNotNull(git2); + DirCache dc = DirCache.read(git2.getRepository()); + DirCacheVersion version = dc.getVersion(); + assertTrue(expected.contains(version)); + return version; + } + + @Test + public void testCloneV3OrV2() throws Exception { + cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, + DirCacheVersion.DIRC_VERSION_EXTENDED)); + } + + @Test + public void testCloneV4() throws Exception { + StoredConfig cfg = SystemReader.getInstance().getUserConfig(); + cfg.load(); + cfg.setInt("index", null, "version", 4); + cfg.save(); + cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS)); + } + + @Test + public void testCloneV4manyFiles() throws Exception { + StoredConfig cfg = SystemReader.getInstance().getUserConfig(); + cfg.load(); + cfg.setBoolean("feature", null, "manyFiles", true); + cfg.save(); + cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS)); + } + + @Test + public void testCloneV3CommitNoVersionChange() throws Exception { + DirCacheVersion initial = cloneAndCheck( + EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, + DirCacheVersion.DIRC_VERSION_EXTENDED)); + StoredConfig cfg = db.getConfig(); + cfg.setInt("index", null, "version", 4); + cfg.save(); + try (Git git = new Git(db)) { + writeTrashFile("Test.txt2", "Hello again"); + git.add().addFilepattern("Test.txt2").call(); + git.commit().setMessage("Second commit").call(); + } + assertEquals("DirCache version should be unchanged", initial, + DirCache.read(db).getVersion()); + } + + @Test + public void testCloneV3ResetHardVersionChange() throws Exception { + cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, + DirCacheVersion.DIRC_VERSION_EXTENDED)); + StoredConfig cfg = db.getConfig(); + cfg.setInt("index", null, "version", 4); + cfg.save(); + FileUtils.delete(new File(db.getDirectory(), "index")); + try (Git git = new Git(db)) { + git.reset().setMode(ResetType.HARD).call(); + } + assertEquals("DirCache version should have changed", + DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, + DirCache.read(db).getVersion()); + } + + @Test + public void testCloneV3ResetMixedVersionChange() throws Exception { + cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, + DirCacheVersion.DIRC_VERSION_EXTENDED)); + StoredConfig cfg = db.getConfig(); + cfg.setInt("index", null, "version", 4); + cfg.save(); + FileUtils.delete(new File(db.getDirectory(), "index")); + try (Git git = new Git(db)) { + git.reset().setMode(ResetType.MIXED).call(); + } + assertEquals("DirCache version should have changed", + DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, + DirCache.read(db).getVersion()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java index c57cb263d1..6d4d0b4ab3 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2010, Google Inc. and others + * Copyright (C) 2008, 2020, Google 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 @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; @@ -188,6 +189,28 @@ public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase { assertArrayEquals(expectedBytes, indexBytes); } + @Test + public void testReadWriteV4() throws Exception { + final File file = pathOf("gitgit.index.v4"); + final DirCache dc = new DirCache(file, FS.DETECTED); + dc.read(); + assertEquals(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, + dc.getVersion()); + assertEquals(5, dc.getEntryCount()); + assertV4TreeEntry(0, "src/org/eclipse/jgit/atest/foo.txt", false, dc); + assertV4TreeEntry(1, "src/org/eclipse/jgit/atest/foobar.txt", false, + dc); + assertV4TreeEntry(2, "src/org/eclipse/jgit/other/bar.txt", true, dc); + assertV4TreeEntry(3, "test.txt", false, dc); + assertV4TreeEntry(4, "test.txt2", false, dc); + + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + dc.writeTo(null, bos); + final byte[] indexBytes = bos.toByteArray(); + final byte[] expectedBytes = IO.readFully(file); + assertArrayEquals(expectedBytes, indexBytes); + } + private static void assertV3TreeEntry(int indexPosition, String path, boolean skipWorkTree, boolean intentToAdd, DirCache dc) { final DirCacheEntry entry = dc.getEntry(indexPosition); @@ -196,6 +219,13 @@ public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase { assertEquals(intentToAdd, entry.isIntentToAdd()); } + private static void assertV4TreeEntry(int indexPosition, String path, + boolean skipWorkTree, DirCache dc) { + final DirCacheEntry entry = dc.getEntry(indexPosition); + assertEquals(path, entry.getPathString()); + assertEquals(skipWorkTree, entry.isSkipWorkTree()); + } + private static File pathOf(String name) { return JGitTestUtil.getTestResourceFile(name); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java index f21c7f854f..5477f565f4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Google Inc. and others + * Copyright (C) 2009, 2020 Google 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 @@ -11,14 +11,25 @@ package org.eclipse.jgit.dircache; import static java.time.Instant.EPOCH; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.MessageDigest; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.util.MutableInteger; import org.junit.Test; public class DirCacheEntryTest { @@ -47,6 +58,95 @@ public class DirCacheEntryTest { } } + private static void checkPath(DirCacheVersion indexVersion, + DirCacheEntry previous, String name) throws IOException { + DirCacheEntry dce = new DirCacheEntry(name); + long now = System.currentTimeMillis(); + long anHourAgo = now - TimeUnit.HOURS.toMillis(1); + dce.setLastModified(Instant.ofEpochMilli(anHourAgo)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + dce.write(out, indexVersion, previous); + byte[] raw = out.toByteArray(); + MessageDigest md0 = Constants.newMessageDigest(); + md0.update(raw); + ByteArrayInputStream in = new ByteArrayInputStream(raw); + MutableInteger infoAt = new MutableInteger(); + byte[] sharedInfo = new byte[raw.length]; + MessageDigest md = Constants.newMessageDigest(); + DirCacheEntry read = new DirCacheEntry(sharedInfo, infoAt, in, md, + Instant.ofEpochMilli(now), indexVersion, previous); + assertEquals("Paths of length " + name.length() + " should match", name, + read.getPathString()); + assertEquals("Should have been fully read", -1, in.read()); + assertArrayEquals("Digests should match", md0.digest(), + md.digest()); + } + + @Test + public void testLongPath() throws Exception { + StringBuilder name = new StringBuilder(4094 + 16); + for (int i = 0; i < 4094; i++) { + name.append('a'); + } + for (int j = 0; j < 16; j++) { + checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null, + name.toString()); + name.append('b'); + } + } + + @Test + public void testLongPathV4() throws Exception { + StringBuilder name = new StringBuilder(4094 + 16); + for (int i = 0; i < 4094; i++) { + name.append('a'); + } + DirCacheEntry previous = new DirCacheEntry(name.toString()); + for (int j = 0; j < 16; j++) { + checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, + name.toString()); + name.append('b'); + } + } + + @Test + public void testShortPath() throws Exception { + StringBuilder name = new StringBuilder(1 + 16); + name.append('a'); + for (int j = 0; j < 16; j++) { + checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null, + name.toString()); + name.append('b'); + } + } + + @Test + public void testShortPathV4() throws Exception { + StringBuilder name = new StringBuilder(1 + 16); + name.append('a'); + DirCacheEntry previous = new DirCacheEntry(name.toString()); + for (int j = 0; j < 16; j++) { + checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, + name.toString()); + name.append('b'); + } + } + + @Test + public void testPathV4() throws Exception { + StringBuilder name = new StringBuilder(); + for (int i = 0; i < 20; i++) { + name.append('a'); + } + DirCacheEntry previous = new DirCacheEntry(name.toString()); + for (int j = 0; j < 20; j++) { + name.setLength(name.length() - 1); + String newName = name.toString() + "bbb"; + checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, + newName); + } + } + @SuppressWarnings("unused") @Test public void testCreate_ByStringPath() { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBundleWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBundleWriterTest.java new file mode 100644 index 0000000000..4238ee6bf0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBundleWriterTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, Google LLC 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 + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.dfs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.FetchResult; +import org.eclipse.jgit.transport.RefSpec; +import org.eclipse.jgit.transport.TransportBundleStream; +import org.eclipse.jgit.transport.URIish; +import org.junit.Before; +import org.junit.Test; + +public class DfsBundleWriterTest { + private TestRepository<InMemoryRepository> git; + + private InMemoryRepository repo; + + @Before + public void setUp() throws IOException { + DfsRepositoryDescription desc = new DfsRepositoryDescription("test"); + git = new TestRepository<>(new InMemoryRepository(desc)); + repo = git.getRepository(); + } + + @Test + public void testRepo() throws Exception { + RevCommit commit0 = git.commit().message("0").create(); + RevCommit commit1 = git.commit().message("1").parent(commit0).create(); + git.update("master", commit1); + + RevCommit commit2 = git.commit().message("0").create(); + + byte[] bundle = makeBundle(); + try (Repository newRepo = new InMemoryRepository( + new DfsRepositoryDescription("copy"))) { + fetchFromBundle(newRepo, bundle); + Ref ref = newRepo.exactRef("refs/heads/master"); + assertNotNull(ref); + assertEquals(commit1.toObjectId(), ref.getObjectId()); + + // Unreferenced objects are included as well. + assertTrue(newRepo.getObjectDatabase().has(commit2)); + } + } + + private byte[] makeBundle() throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DfsBundleWriter.writeEntireRepositoryAsBundle( + NullProgressMonitor.INSTANCE, out, repo); + return out.toByteArray(); + } + + private static FetchResult fetchFromBundle(Repository newRepo, + byte[] bundle) throws Exception { + URIish uri = new URIish("in-memory://"); + ByteArrayInputStream in = new ByteArrayInputStream(bundle); + RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*"); + Set<RefSpec> refs = Collections.singleton(rs); + try (TransportBundleStream transport = new TransportBundleStream( + newRepo, uri, in)) { + return transport.fetch(NullProgressMonitor.INSTANCE, refs); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java index d269457eb1..a0bc63a698 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java @@ -44,8 +44,12 @@ package org.eclipse.jgit.internal.storage.file; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import java.io.File; import java.io.IOException; @@ -69,6 +73,7 @@ import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.junit.Assume; import org.junit.Test; +import org.mockito.Mockito; public class ObjectDirectoryTest extends RepositoryTestCase { @@ -195,6 +200,42 @@ public class ObjectDirectoryTest extends RepositoryTestCase { } @Test + public void testOpenLooseObjectSuppressStaleFileHandleException() + throws Exception { + ObjectId id = ObjectId + .fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"); + WindowCursor curs = new WindowCursor(db.getObjectDatabase()); + + ObjectDirectory mock = mock(ObjectDirectory.class); + UnpackedObjectCache unpackedObjectCacheMock = mock( + UnpackedObjectCache.class); + + Mockito.when(mock.getObjectLoader(any(), any(), any())) + .thenThrow(new IOException("Stale File Handle")); + Mockito.when(mock.openLooseObject(curs, id)).thenCallRealMethod(); + Mockito.when(mock.unpackedObjectCache()) + .thenReturn(unpackedObjectCacheMock); + + assertNull(mock.openLooseObject(curs, id)); + verify(unpackedObjectCacheMock).remove(id); + } + + @Test + public void testOpenLooseObjectPropagatesIOExceptions() throws Exception { + ObjectId id = ObjectId + .fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"); + WindowCursor curs = new WindowCursor(db.getObjectDatabase()); + + ObjectDirectory mock = mock(ObjectDirectory.class); + + Mockito.when(mock.getObjectLoader(any(), any(), any())) + .thenThrow(new IOException("some IO failure")); + Mockito.when(mock.openLooseObject(curs, id)).thenCallRealMethod(); + + assertThrows(IOException.class, () -> mock.openLooseObject(curs, id)); + } + + @Test public void testShallowFileCorrupt() throws Exception { FileRepository repository = createBareRepository(); ObjectDirectory dir = repository.getObjectDatabase(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java index fe05fbae39..910b928864 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java @@ -12,13 +12,17 @@ package org.eclipse.jgit.internal.storage.file; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry; import org.eclipse.jgit.junit.RepositoryTestCase; import org.junit.Test; @@ -51,6 +55,13 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { public abstract File getFileForPackdf2982f28(); /** + * Return file with appropriate index version for bad fanout table test. + * + * @return file with index + */ + public abstract File getFileForBadFanoutTable(); + + /** * Verify CRC32 support. * * @throws MissingObjectException @@ -158,4 +169,15 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { .name()); } + @Test + public void testBadFanoutTable() { + IOException ex = assertThrows(IOException.class, () -> { + try (FileInputStream fis = new FileInputStream( + getFileForBadFanoutTable())) { + PackIndex.read(fis); + } + }); + assertEquals(JGitText.get().indexFileIsTooLargeForJgit, + ex.getMessage()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV1Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV1Test.java index e41ded7d71..c4f637276c 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV1Test.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV1Test.java @@ -35,6 +35,11 @@ public class PackIndexV1Test extends PackIndexTestCase { "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx"); } + @Override + public File getFileForBadFanoutTable() { + return JGitTestUtil.getTestResourceFile("pack-bad-fanout-table.idx"); + } + /** * Verify CRC32 - V1 should not index anything. * diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV2Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV2Test.java index c1da54721f..1d179abd86 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV2Test.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexV2Test.java @@ -35,6 +35,11 @@ public class PackIndexV2Test extends PackIndexTestCase { "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2"); } + @Override + public File getFileForBadFanoutTable() { + return JGitTestUtil.getTestResourceFile("pack-bad-fanout-table.idxV2"); + } + /** * Verify CRC32 indexing. * diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java index a246ac9e9c..0a03fc3523 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java @@ -329,21 +329,21 @@ public class MergedReftableTest { public void overlappedUpdateIndices() throws IOException { ByteArrayOutputStream buf = new ByteArrayOutputStream(); ReftableWriter writer = new ReftableWriter(buf) - .setMinUpdateIndex(1) - .setMaxUpdateIndex(3) + .setMinUpdateIndex(2) + .setMaxUpdateIndex(4) .begin(); - writer.writeRef(ref("refs/heads/a", 1), 1); - writer.writeRef(ref("refs/heads/b", 2), 3); + writer.writeRef(ref("refs/heads/a", 10), 2); + writer.writeRef(ref("refs/heads/b", 20), 4); writer.finish(); byte[] base = buf.toByteArray(); buf = new ByteArrayOutputStream(); writer = new ReftableWriter(buf) - .setMinUpdateIndex(2) - .setMaxUpdateIndex(4) + .setMinUpdateIndex(1) + .setMaxUpdateIndex(3) .begin(); - writer.writeRef(ref("refs/heads/a", 10), 2); - writer.writeRef(ref("refs/heads/b", 20), 4); + writer.writeRef(ref("refs/heads/a", 1), 1); + writer.writeRef(ref("refs/heads/b", 2), 3); writer.finish(); byte[] delta = buf.toByteArray(); @@ -368,21 +368,21 @@ public class MergedReftableTest { public void enclosedUpdateIndices() throws IOException { ByteArrayOutputStream buf = new ByteArrayOutputStream(); ReftableWriter writer = new ReftableWriter(buf) - .setMinUpdateIndex(1) - .setMaxUpdateIndex(4) + .setMinUpdateIndex(2) + .setMaxUpdateIndex(3) .begin(); - writer.writeRef(ref("refs/heads/a", 1), 1); - writer.writeRef(ref("refs/heads/b", 20), 4); + writer.writeRef(ref("refs/heads/a", 10), 2); + writer.writeRef(ref("refs/heads/b", 2), 3); writer.finish(); byte[] base = buf.toByteArray(); buf = new ByteArrayOutputStream(); writer = new ReftableWriter(buf) - .setMinUpdateIndex(2) - .setMaxUpdateIndex(3) + .setMinUpdateIndex(1) + .setMaxUpdateIndex(4) .begin(); - writer.writeRef(ref("refs/heads/a", 10), 2); - writer.writeRef(ref("refs/heads/b", 2), 3); + writer.writeRef(ref("refs/heads/a", 1), 1); + writer.writeRef(ref("refs/heads/b", 20), 4); writer.finish(); byte[] delta = buf.toByteArray(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java index 26294c7714..dee58f9cfc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java @@ -13,7 +13,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertThrows; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -24,6 +24,32 @@ import org.junit.Test; public class CommitBuilderTest { + // @formatter:off + private static final String SIGNATURE = "-----BEGIN PGP SIGNATURE-----\n" + + "Version: BCPG v1.60\n" + + "\n" + + "iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + + "opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + + "gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + + "uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + + "3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + + "IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + + "=b9OI\n" + + "-----END PGP SIGNATURE-----"; + + private static final String EXPECTED = "-----BEGIN PGP SIGNATURE-----\n" + + " Version: BCPG v1.60\n" + + " \n" + + " iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + + " opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + + " gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + + " uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + + " 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + + " IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + + " =b9OI\n" + + " -----END PGP SIGNATURE-----"; + // @formatter:on + private void assertGpgSignatureStringOutcome(String signature, String expectedOutcome) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -33,47 +59,37 @@ public class CommitBuilderTest { } @Test - public void writeGpgSignatureString_1() throws Exception { - // @formatter:off - String signature = "-----BEGIN PGP SIGNATURE-----\n" + - "Version: BCPG v1.60\n" + - "\n" + - "iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + - "opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + - "gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + - "uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + - "3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + - "IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + - "=b9OI\n" + - "-----END PGP SIGNATURE-----"; - String expectedOutcome = "-----BEGIN PGP SIGNATURE-----\n" + - " Version: BCPG v1.60\n" + - " \n" + - " iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + - " opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + - " gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + - " uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + - " 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + - " IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + - " =b9OI\n" + - " -----END PGP SIGNATURE-----"; - // @formatter:on - assertGpgSignatureStringOutcome(signature, expectedOutcome); + public void writeGpgSignatureString() throws Exception { + assertGpgSignatureStringOutcome(SIGNATURE, EXPECTED); + } + + @Test + public void writeGpgSignatureStringTrailingLF() throws Exception { + assertGpgSignatureStringOutcome(SIGNATURE + '\n', EXPECTED); + } + + @Test + public void writeGpgSignatureStringCRLF() throws Exception { + assertGpgSignatureStringOutcome(SIGNATURE.replaceAll("\n", "\r\n"), + EXPECTED); + } + + @Test + public void writeGpgSignatureStringTrailingCRLF() throws Exception { + assertGpgSignatureStringOutcome( + SIGNATURE.replaceAll("\n", "\r\n") + "\r\n", EXPECTED); } @Test public void writeGpgSignatureString_failsForNonAscii() throws Exception { String signature = "Ü Ä"; - try { - CommitBuilder.writeGpgSignatureString(signature, - new ByteArrayOutputStream()); - fail("Exception expected"); - } catch (IllegalArgumentException e) { - // good - String message = MessageFormat.format(JGitText.get().notASCIIString, - signature); - assertEquals(message, e.getMessage()); - } + IllegalArgumentException e = assertThrows( + IllegalArgumentException.class, + () -> CommitBuilder.writeGpgSignatureString(signature, + new ByteArrayOutputStream())); + String message = MessageFormat.format(JGitText.get().notASCIIString, + signature); + assertEquals(message, e.getMessage()); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java index a272c8f2ee..b943486b1b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java @@ -2,41 +2,13 @@ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> * Copyright (C) 2008-2011, Shawn O. Pearce <spearce@spearce.org> * Copyright (C) 2008-2011, Robin Rosenberg <robin.rosenberg@dewire.com> - * Copyright (C) 2010-2011, Christian Halstrick <christian.halstrick@sap.com> - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, 2020 Christian Halstrick <christian.halstrick@sap.com> and others * * 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 + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://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. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.lib; @@ -85,6 +57,7 @@ import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.WorkingTreeIterator; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; +import org.eclipse.jgit.util.StringUtils; import org.junit.Assume; import org.junit.Test; @@ -284,6 +257,86 @@ public class DirCacheCheckoutTest extends RepositoryTestCase { } } + private void checkoutLineEndings(String inIndex, String expected, + String attributes) throws Exception { + try (Git git = new Git(db); + TestRepository<Repository> db_t = new TestRepository<>(db)) { + BranchBuilder master = db_t.branch("master"); + master.commit().add("f", inIndex).message("m0").create(); + if (!StringUtils.isEmptyOrNull(attributes)) { + master.commit().add(".gitattributes", attributes) + .message("attributes").create(); + } + File f = new File(db.getWorkTree(), "f"); + assertFalse(f.exists()); + git.checkout().setName("master").call(); + assertTrue(f.exists()); + checkFile(f, expected); + } + } + + @Test + public void testCheckoutWithCRLF() throws Exception { + checkoutLineEndings("first line\r\nsecond line\r\n", + "first line\r\nsecond line\r\n", null); + } + + @Test + public void testCheckoutWithCRLFAuto() throws Exception { + checkoutLineEndings("first line\r\nsecond line\r\n", + "first line\r\nsecond line\r\n", "f text=auto"); + } + + @Test + public void testCheckoutWithCRLFAutoEolLf() throws Exception { + checkoutLineEndings("first line\r\nsecond line\r\n", + "first line\r\nsecond line\r\n", "f text=auto eol=lf"); + } + + @Test + public void testCheckoutWithCRLFAutoEolNative() throws Exception { + checkoutLineEndings("first line\r\nsecond line\r\n", + "first line\r\nsecond line\r\n", "f text=auto eol=native"); + } + + @Test + public void testCheckoutWithCRLFAutoEolCrLf() throws Exception { + checkoutLineEndings("first line\r\nsecond line\r\n", + "first line\r\nsecond line\r\n", "f text=auto eol=crlf"); + } + + @Test + public void testCheckoutWithLF() throws Exception { + checkoutLineEndings("first line\nsecond line\n", + "first line\nsecond line\n", null); + } + + @Test + public void testCheckoutWithLFAuto() throws Exception { + checkoutLineEndings("first line\nsecond line\n", + "first line\nsecond line\n", "f text=auto"); + } + + @Test + public void testCheckoutWithLFAutoEolLf() throws Exception { + checkoutLineEndings("first line\nsecond line\n", + "first line\nsecond line\n", "f text=auto eol=lf"); + } + + @Test + public void testCheckoutWithLFAutoEolNative() throws Exception { + checkoutLineEndings( + "first line\nsecond line\n", "first line\nsecond line\n" + .replaceAll("\n", System.lineSeparator()), + "f text=auto eol=native"); + } + + @Test + public void testCheckoutWithLFAutoEolCrLf() throws Exception { + checkoutLineEndings("first line\nsecond line\n", + "first line\r\nsecond line\r\n", "f text=auto eol=crlf"); + } + private DirCacheCheckout resetHard(RevCommit commit) throws NoWorkTreeException, CorruptObjectException, IOException { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java new file mode 100644 index 0000000000..f410960bec --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2020, Google LLC 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 + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.merge; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.CommitBuilder; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.junit.Test; + +public class GitlinkMergeTest extends SampleDataRepositoryTestCase { + private static final String LINK_ID1 = "DEADBEEFDEADBEEFBABEDEADBEEFDEADBEEFBABE"; + private static final String LINK_ID2 = "DEADDEADDEADDEADDEADDEADDEADDEADDEADDEAD"; + private static final String LINK_ID3 = "BEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEF"; + + private static final String SUBMODULE_PATH = "submodule.link"; + + @Test + public void testGitLinkMerging_AddNew() throws Exception { + assertGitLinkValue( + testGitLink(null, null, LINK_ID3, newResolveMerger(), true), + LINK_ID3); + } + + @Test + public void testGitLinkMerging_Delete() throws Exception { + assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null, + newResolveMerger(), true)); + } + + @Test + public void testGitLinkMerging_UpdateDelete() throws Exception { + testGitLink(LINK_ID1, LINK_ID2, null, newResolveMerger(), false); + } + + @Test + public void testGitLinkMerging_DeleteUpdate() throws Exception { + testGitLink(LINK_ID1, null, LINK_ID3, newResolveMerger(), false); + } + + @Test + public void testGitLinkMerging_UpdateUpdate() throws Exception { + testGitLink(LINK_ID1, LINK_ID2, LINK_ID3, newResolveMerger(), false); + } + + @Test + public void testGitLinkMerging_bothAddedSameLink() throws Exception { + assertGitLinkValue( + testGitLink(null, LINK_ID2, LINK_ID2, newResolveMerger(), true), + LINK_ID2); + } + + @Test + public void testGitLinkMerging_bothAddedDifferentLink() throws Exception { + testGitLink(null, LINK_ID2, LINK_ID3, newResolveMerger(), false); + } + + @Test + public void testGitLinkMerging_AddNew_ignoreConflicts() throws Exception { + assertGitLinkValue( + testGitLink(null, null, LINK_ID3, newIgnoreConflictMerger(), + true), + LINK_ID3); + } + + @Test + public void testGitLinkMerging_Delete_ignoreConflicts() throws Exception { + assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null, + newIgnoreConflictMerger(), true)); + } + + @Test + public void testGitLinkMerging_UpdateDelete_ignoreConflicts() + throws Exception { + assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, null, + newIgnoreConflictMerger(), true), LINK_ID2); + } + + @Test + public void testGitLinkMerging_DeleteUpdate_ignoreConflicts() + throws Exception { + assertGitLinkDoesntExist(testGitLink(LINK_ID1, null, LINK_ID3, + newIgnoreConflictMerger(), true)); + } + + @Test + public void testGitLinkMerging_UpdateUpdate_ignoreConflicts() + throws Exception { + assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, LINK_ID3, + newIgnoreConflictMerger(), true), LINK_ID2); + } + + @Test + public void testGitLinkMerging_bothAddedSameLink_ignoreConflicts() + throws Exception { + assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID2, + newIgnoreConflictMerger(), true), LINK_ID2); + } + + @Test + public void testGitLinkMerging_bothAddedDifferentLink_ignoreConflicts() + throws Exception { + assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID3, + newIgnoreConflictMerger(), true), LINK_ID2); + } + + protected Merger testGitLink(@Nullable String baseLink, + @Nullable String oursLink, @Nullable String theirsLink, + Merger merger, boolean shouldMerge) + throws Exception { + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + maybeAddLink(bTreeBuilder, baseLink); + maybeAddLink(oTreeBuilder, oursLink); + maybeAddLink(tTreeBuilder, theirsLink); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + boolean merge = merger.merge(new ObjectId[] { o, t }); + assertEquals(Boolean.valueOf(shouldMerge), Boolean.valueOf(merge)); + + return merger; + } + + private Merger newResolveMerger() { + return MergeStrategy.RESOLVE.newMerger(db, true); + } + + private Merger newIgnoreConflictMerger() { + return new ResolveMerger(db, true) { + @Override + protected boolean mergeImpl() throws IOException { + // emulate call with ignore conflicts. + return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1], + true); + } + }; + } + + @Test + public void testGitLinkMerging_blobWithLink() throws Exception { + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + bTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob")); + oTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); + + maybeAddLink(tTreeBuilder, LINK_ID3); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); + boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + @Test + public void testGitLinkMerging_linkWithBlob() throws Exception { + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + maybeAddLink(bTreeBuilder, LINK_ID1); + maybeAddLink(oTreeBuilder, LINK_ID2); + tTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); + boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + @Test + public void testGitLinkMerging_linkWithLink() throws Exception { + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + bTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob")); + maybeAddLink(oTreeBuilder, LINK_ID2); + maybeAddLink(tTreeBuilder, LINK_ID3); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); + boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + @Test + public void testGitLinkMerging_blobWithBlobFromLink() throws Exception { + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + maybeAddLink(bTreeBuilder, LINK_ID1); + oTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); + tTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); + boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + @Test + public void testGitLinkMerging_linkBlobDeleted() throws Exception { + // We changed a link to a blob, others has deleted this link. + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + maybeAddLink(bTreeBuilder, LINK_ID1); + oTreeBuilder.add( + createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); + boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + private void maybeAddLink(DirCacheBuilder builder, + @Nullable String linkId) { + if (linkId == null) { + return; + } + DirCacheEntry newLink = createGitLink(SUBMODULE_PATH, + ObjectId.fromString(linkId)); + builder.add(newLink); + } + + private void assertGitLinkValue(Merger resolveMerger, String expectedValue) + throws Exception { + try (TreeWalk tw = new TreeWalk(db)) { + tw.setRecursive(true); + tw.reset(resolveMerger.getResultTreeId()); + + assertTrue(tw.next()); + assertEquals(SUBMODULE_PATH, tw.getPathString()); + assertEquals(ObjectId.fromString(expectedValue), tw.getObjectId(0)); + + assertFalse(tw.next()); + } + } + + private void assertGitLinkDoesntExist(Merger resolveMerger) + throws Exception { + try (TreeWalk tw = new TreeWalk(db)) { + tw.setRecursive(true); + tw.reset(resolveMerger.getResultTreeId()); + + assertFalse(tw.next()); + } + } + + private static ObjectId commit(ObjectInserter odi, DirCache treeB, + ObjectId[] parentIds) throws Exception { + CommitBuilder c = new CommitBuilder(); + c.setTreeId(treeB.writeTree(odi)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setCommitter(c.getAuthor()); + c.setParentIds(parentIds); + c.setMessage("Tree " + c.getTreeId().name()); + ObjectId id = odi.insert(c); + odi.flush(); + return id; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java index 7a244e1d8b..e2ac89be90 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, Robin Stocker <robin@nibor.org> and others + * Copyright (C) 2012, 2020 Robin Stocker <robin@nibor.org> 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 @@ -367,6 +367,48 @@ public class MergerTest extends RepositoryTestCase { } @Theory + public void mergeConflictWithCrLfTextAuto(MergeStrategy strategy) + throws IOException, GitAPIException { + Git git = Git.wrap(db); + writeTrashFile("crlf.txt", "a crlf file\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("base").call(); + assertEquals("[crlf.txt, mode:100644, content:a crlf file\r\n]", + indexState(CONTENT)); + writeTrashFile(".gitattributes", "crlf.txt text=auto"); + git.add().addFilepattern(".gitattributes").call(); + git.commit().setMessage("attributes").call(); + + git.branchCreate().setName("brancha").call(); + + writeTrashFile("crlf.txt", "a crlf file\r\na second line\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("on master").call(); + assertEquals( + "[.gitattributes, mode:100644, content:crlf.txt text=auto]" + + "[crlf.txt, mode:100644, content:a crlf file\r\na second line\r\n]", + indexState(CONTENT)); + + git.checkout().setName("brancha").call(); + File testFile = writeTrashFile("crlf.txt", + "a crlf file\r\nanother line\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("on brancha").call(); + + MergeResult mergeResult = git.merge().setStrategy(strategy) + .include(db.resolve("master")).call(); + assertEquals(MergeResult.MergeStatus.CONFLICTING, + mergeResult.getMergeStatus()); + checkFile(testFile, + "a crlf file\r\n" // + + "<<<<<<< HEAD\n" // + + "another line\r\n" // + + "=======\n" // + + "a second line\r\n" // + + ">>>>>>> 8e9e704742f1bc8a41eac88aac4aeefd338b7384\n"); + } + + @Theory public void mergeWithCrlfAutoCrlfTrue(MergeStrategy strategy) throws IOException, GitAPIException { Git git = Git.wrap(db); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java index 36805d3241..798aebe3b0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java @@ -109,33 +109,33 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_validSubtreeSort() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); - - b.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); - b.add(createEntry("libelf/c", FileMode.REGULAR_FILE)); - - o.add(createEntry("Makefile", FileMode.REGULAR_FILE)); - o.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); - o.add(createEntry("libelf/c", FileMode.REGULAR_FILE)); - - t.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); - t.add(createEntry("libelf/c", FileMode.REGULAR_FILE, "blah")); - - b.finish(); - o.finish(); - t.finish(); - } + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); + + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + bTreeBuilder.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("libelf/c", FileMode.REGULAR_FILE)); + + oTreeBuilder.add(createEntry("Makefile", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("libelf/c", FileMode.REGULAR_FILE)); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + tTreeBuilder.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE)); + tTreeBuilder + .add(createEntry("libelf/c", FileMode.REGULAR_FILE, "blah")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -163,32 +163,31 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_concurrentSubtreeChange() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); - - b.add(createEntry("d/o", FileMode.REGULAR_FILE)); - b.add(createEntry("d/t", FileMode.REGULAR_FILE)); - - o.add(createEntry("d/o", FileMode.REGULAR_FILE, "o !")); - o.add(createEntry("d/t", FileMode.REGULAR_FILE)); - - t.add(createEntry("d/o", FileMode.REGULAR_FILE)); - t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); - - b.finish(); - o.finish(); - t.finish(); - } + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + bTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE)); + + oTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE, "o !")); + oTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE)); + + tTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + tTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -212,32 +211,31 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_conflictSubtreeChange() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); - - b.add(createEntry("d/o", FileMode.REGULAR_FILE)); - b.add(createEntry("d/t", FileMode.REGULAR_FILE)); - - o.add(createEntry("d/o", FileMode.REGULAR_FILE)); - o.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !")); - - t.add(createEntry("d/o", FileMode.REGULAR_FILE, "t !")); - t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); - - b.finish(); - o.finish(); - t.finish(); - } + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); + + bTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE)); + + oTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !")); + + tTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE, "t !")); + tTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -246,31 +244,30 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_leftDFconflict1() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - b.add(createEntry("d/o", FileMode.REGULAR_FILE)); - b.add(createEntry("d/t", FileMode.REGULAR_FILE)); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); - o.add(createEntry("d", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE)); - t.add(createEntry("d/o", FileMode.REGULAR_FILE)); - t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); + oTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE)); - b.finish(); - o.finish(); - t.finish(); - } + tTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + tTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -279,31 +276,30 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_rightDFconflict1() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - b.add(createEntry("d/o", FileMode.REGULAR_FILE)); - b.add(createEntry("d/t", FileMode.REGULAR_FILE)); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); - o.add(createEntry("d/o", FileMode.REGULAR_FILE)); - o.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !")); + bTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE)); - t.add(createEntry("d", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !")); - b.finish(); - o.finish(); - t.finish(); - } + tTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE)); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -312,29 +308,28 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_leftDFconflict2() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - b.add(createEntry("d", FileMode.REGULAR_FILE)); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); - o.add(createEntry("d", FileMode.REGULAR_FILE, "o !")); + bTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE)); - t.add(createEntry("d/o", FileMode.REGULAR_FILE)); + oTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE, "o !")); - b.finish(); - o.finish(); - t.finish(); - } + tTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); + + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -343,29 +338,28 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { @Test public void testTrivialTwoWay_rightDFconflict2() throws Exception { - final DirCache treeB = db.readDirCache(); - final DirCache treeO = db.readDirCache(); - final DirCache treeT = db.readDirCache(); - { - final DirCacheBuilder b = treeB.builder(); - final DirCacheBuilder o = treeO.builder(); - final DirCacheBuilder t = treeT.builder(); + DirCache treeB = db.readDirCache(); + DirCache treeO = db.readDirCache(); + DirCache treeT = db.readDirCache(); - b.add(createEntry("d", FileMode.REGULAR_FILE)); + DirCacheBuilder bTreeBuilder = treeB.builder(); + DirCacheBuilder oTreeBuilder = treeO.builder(); + DirCacheBuilder tTreeBuilder = treeT.builder(); - o.add(createEntry("d/o", FileMode.REGULAR_FILE)); + bTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE)); - t.add(createEntry("d", FileMode.REGULAR_FILE, "t !")); + oTreeBuilder.add(createEntry("d/o", FileMode.REGULAR_FILE)); - b.finish(); - o.finish(); - t.finish(); - } + tTreeBuilder.add(createEntry("d", FileMode.REGULAR_FILE, "t !")); + + bTreeBuilder.finish(); + oTreeBuilder.finish(); + tTreeBuilder.finish(); - final ObjectInserter ow = db.newObjectInserter(); - final ObjectId b = commit(ow, treeB, new ObjectId[] {}); - final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); - final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + ObjectInserter ow = db.newObjectInserter(); + ObjectId b = commit(ow, treeB, new ObjectId[] {}); + ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + ObjectId t = commit(ow, treeT, new ObjectId[] { b }); Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); boolean merge = ourMerger.merge(new ObjectId[] { o, t }); @@ -377,10 +371,9 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { .getObjectId(0)); } - private static ObjectId commit(final ObjectInserter odi, - final DirCache treeB, - final ObjectId[] parentIds) throws Exception { - final CommitBuilder c = new CommitBuilder(); + private static ObjectId commit(ObjectInserter odi, DirCache treeB, + ObjectId[] parentIds) throws Exception { + CommitBuilder c = new CommitBuilder(); c.setTreeId(treeB.writeTree(odi)); c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); c.setCommitter(c.getAuthor()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java index 965a2faf8e..c0db83a820 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java @@ -9,6 +9,10 @@ */ package org.eclipse.jgit.transport; +import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; +import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT; +import static org.eclipse.jgit.lib.Constants.OBJ_TAG; +import static org.eclipse.jgit.lib.Constants.OBJ_TREE; import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -160,6 +164,10 @@ public class ProtocolV0ParserTest { assertThat(request.getWantIds(), hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", "f900c8326a43303685c46b279b9f70411bff1a4b")); + assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TREE)); + assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TAG)); assertEquals(13000, request.getFilterSpec().getBlobLimit()); assertEquals(-1, request.getFilterSpec().getTreeDepthLimit()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java index 038ce717b3..837bdce919 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java @@ -9,6 +9,10 @@ */ package org.eclipse.jgit.transport; +import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; +import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT; +import static org.eclipse.jgit.lib.Constants.OBJ_TAG; +import static org.eclipse.jgit.lib.Constants.OBJ_TREE; import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItems; @@ -195,7 +199,11 @@ public class ProtocolV2ParserTest { ProtocolV2Parser parser = new ProtocolV2Parser( ConfigBuilder.start().allowFilter().done()); FetchV2Request request = parser.parseFetchRequest(pckIn); - assertEquals(0, request.getFilterSpec().getBlobLimit()); + assertFalse(request.getFilterSpec().allowsType(OBJ_BLOB)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TREE)); + assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TAG)); + assertEquals(-1, request.getFilterSpec().getBlobLimit()); assertEquals(-1, request.getFilterSpec().getTreeDepthLimit()); } @@ -207,6 +215,10 @@ public class ProtocolV2ParserTest { ProtocolV2Parser parser = new ProtocolV2Parser( ConfigBuilder.start().allowFilter().done()); FetchV2Request request = parser.parseFetchRequest(pckIn); + assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TREE)); + assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TAG)); assertEquals(15, request.getFilterSpec().getBlobLimit()); assertEquals(-1, request.getFilterSpec().getTreeDepthLimit()); } @@ -219,6 +231,10 @@ public class ProtocolV2ParserTest { ProtocolV2Parser parser = new ProtocolV2Parser( ConfigBuilder.start().allowFilter().done()); FetchV2Request request = parser.parseFetchRequest(pckIn); + assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TREE)); + assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT)); + assertTrue(request.getFilterSpec().allowsType(OBJ_TAG)); assertEquals(-1, request.getFilterSpec().getBlobLimit()); assertEquals(3, request.getFilterSpec().getTreeDepthLimit()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java index 0179d8c26f..21fde3e76e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java @@ -162,7 +162,9 @@ public class PushConnectionTest { fail("server did not abort"); } catch (TransportException e) { String msg = e.getMessage(); - assertEquals("remote: Too many commands", msg); + assertEquals( + "remote: Commands size exceeds limit defined in receive.maxCommandBytes", + msg); } } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java index d58e576984..46ba3aa5d4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java @@ -38,6 +38,7 @@ import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.internal.storage.pack.CachedPack; import org.eclipse.jgit.internal.storage.pack.CachedPackUriProvider; import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; @@ -127,7 +128,7 @@ public class UploadPackTest { } @Test - public void testFetchWithBlobNoneFilter() throws Exception { + public void testFetchWithBlobZeroFilter() throws Exception { InMemoryRepository server2 = newRepo("server2"); try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( server2)) { @@ -298,6 +299,38 @@ public class UploadPackTest { } @Test + public void testFetchWithTreeZeroFilter() throws Exception { + InMemoryRepository server2 = newRepo("server2"); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob blob1 = remote2.blob("foobar"); + RevBlob blob2 = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", blob1), + remote2.file("2", blob2)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + testProtocol = new TestProtocol<>((Object req, Repository db) -> { + UploadPack up = new UploadPack(db); + return up; + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterSpec(FilterSpec.withTreeDepthLimit(0)); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + assertFalse(client.getObjectDatabase().has(tree.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob1.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob2.toObjectId())); + } + } + } + + @Test public void testFetchWithNonSupportingServer() throws Exception { InMemoryRepository server2 = newRepo("server2"); try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( @@ -338,7 +371,9 @@ public class UploadPackTest { ByteArrayInputStream send = linesAsInputStream(inputLines); - server.getConfig().setString("protocol", null, "version", "2"); + server.getConfig().setString(ConfigConstants.CONFIG_PROTOCOL_SECTION, + null, ConfigConstants.CONFIG_KEY_VERSION, + TransferConfig.ProtocolVersion.V2.version()); UploadPack up = new UploadPack(server); if (postConstructionSetup != null) { postConstructionSetup.accept(up); @@ -2133,7 +2168,9 @@ public class UploadPackTest { @Test public void testGetPeerAgentProtocolV2() throws Exception { - server.getConfig().setString("protocol", null, "version", "2"); + server.getConfig().setString(ConfigConstants.CONFIG_PROTOCOL_SECTION, + null, ConfigConstants.CONFIG_KEY_VERSION, + TransferConfig.ProtocolVersion.V2.version()); RevCommit one = remote.commit().message("1").create(); remote.update("one", one); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFInputStreamTest.java index fb90461e1a..c391694fbc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFInputStreamTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFInputStreamTest.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, Marc Strapetz <marc.strapetz@syntevo.com> - * Copyright (C) 2015, Ivan Motsch <ivan.motsch@bsiag.com> and others + * Copyright (C) 2015, 2020 Ivan Motsch <ivan.motsch@bsiag.com> 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 @@ -17,7 +17,9 @@ import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.function.Function; +import org.eclipse.jgit.util.io.AutoLFInputStream.StreamFlag; import org.junit.Test; public class AutoLFInputStreamTest { @@ -25,47 +27,65 @@ public class AutoLFInputStreamTest { @Test public void testLF() throws IOException { final byte[] bytes = asBytes("1\n2\n3"); - test(bytes, bytes, false); + test(bytes, bytes); } @Test public void testCR() throws IOException { final byte[] bytes = asBytes("1\r2\r3"); - test(bytes, bytes, false); + test(bytes, bytes); } @Test public void testCRLF() throws IOException { - test(asBytes("1\r\n2\r\n3"), asBytes("1\n2\n3"), false); + test(asBytes("1\r\n2\r\n3"), asBytes("1\n2\n3")); } @Test public void testLFCR() throws IOException { final byte[] bytes = asBytes("1\n\r2\n\r3"); - test(bytes, bytes, false); + test(bytes, bytes); } @Test public void testEmpty() throws IOException { final byte[] bytes = asBytes(""); - test(bytes, bytes, false); + test(bytes, bytes); } @Test public void testBinaryDetect() throws IOException { final byte[] bytes = asBytes("1\r\n2\r\n3\0"); - test(bytes, bytes, true); + test(bytes, bytes, StreamFlag.DETECT_BINARY); } @Test public void testBinaryDontDetect() throws IOException { - test(asBytes("1\r\n2\r\n3\0"), asBytes("1\n2\n3\0"), false); + test(asBytes("1\r\n2\r\n3\0"), asBytes("1\n2\n3\0")); + } + + @Test + public void testCrLf() throws IOException { + byte[] bytes = asBytes("1\r\n2\n3\r\n\r"); + test(bytes, bytes, in -> AutoLFInputStream.create(in, + StreamFlag.DETECT_BINARY, StreamFlag.FOR_CHECKOUT)); + } + + @Test + public void testCrLfDontDetect() throws IOException { + test(asBytes("1\r\n2\r\n"), asBytes("1\n2\n"), + in -> AutoLFInputStream.create(in, StreamFlag.DETECT_BINARY)); + } + + private static void test(byte[] input, byte[] expected, StreamFlag... flags) + throws IOException { + test(input, expected, in -> AutoLFInputStream.create(in, flags)); } private static void test(byte[] input, byte[] expected, - boolean detectBinary) throws IOException { + Function<InputStream, InputStream> factory) throws IOException { try (InputStream bis1 = new ByteArrayInputStream(input); - InputStream cis1 = new AutoLFInputStream(bis1, detectBinary)) { + InputStream cis1 = factory.apply(bis1)) { int index1 = 0; for (int b = cis1.read(); b != -1; b = cis1.read()) { assertEquals(expected[index1], (byte) b); @@ -77,8 +97,7 @@ public class AutoLFInputStreamTest { for (int bufferSize = 1; bufferSize < 10; bufferSize++) { final byte[] buffer = new byte[bufferSize]; try (InputStream bis2 = new ByteArrayInputStream(input); - InputStream cis2 = new AutoLFInputStream(bis2, - detectBinary)) { + InputStream cis2 = factory.apply(bis2)) { int read = 0; for (int readNow = cis2.read(buffer, 0, diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFOutputStreamTest.java new file mode 100644 index 0000000000..1b7e55e457 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/AutoLFOutputStreamTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2020, Thomas Wolf <thomas.wolf@paranor.ch> 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.util.io; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertArrayEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.junit.Test; + +public class AutoLFOutputStreamTest { + + @Test + public void testLF() throws IOException { + final byte[] bytes = asBytes("1\n2\n3"); + test(bytes, bytes, false); + } + + @Test + public void testCR() throws IOException { + final byte[] bytes = asBytes("1\r2\r3"); + test(bytes, bytes, false); + } + + @Test + public void testCRLFNoDetect() throws IOException { + test(asBytes("1\r\n2\r\n3"), asBytes("1\n2\n3"), false); + } + + @Test + public void testLFCR() throws IOException { + final byte[] bytes = asBytes("1\n\r2\n\r3"); + test(bytes, bytes, false); + } + + @Test + public void testEmpty() throws IOException { + final byte[] bytes = asBytes(""); + test(bytes, bytes, false); + } + + @Test + public void testBinaryDetect() throws IOException { + final byte[] bytes = asBytes("1\r\n2\r\n3\0"); + test(bytes, bytes, true); + } + + @Test + public void testBinaryDontDetect() throws IOException { + test(asBytes("1\r\n2\r\n3\0"), asBytes("1\n2\n3\0"), false); + } + + @Test + public void testCrLfDetect() throws IOException { + byte[] bytes = asBytes("1\r\n2\n3\r\n\r"); + test(bytes, bytes, true); + } + + private static void test(byte[] input, byte[] expected, + boolean detectBinary) throws IOException { + try (ByteArrayOutputStream result = new ByteArrayOutputStream(); + OutputStream out = new AutoLFOutputStream(result, + detectBinary)) { + out.write(input); + out.close(); + assertArrayEquals(expected, result.toByteArray()); + } + } + + private static byte[] asBytes(String in) { + return in.getBytes(UTF_8); + } +} |