diff options
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse')
13 files changed, 945 insertions, 393 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java index 40764b739b..a746823525 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java @@ -19,19 +19,13 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.eclipse.jgit.api.errors.PatchApplyException; import org.eclipse.jgit.api.errors.PatchFormatException; -import org.eclipse.jgit.attributes.FilterCommand; -import org.eclipse.jgit.attributes.FilterCommandFactory; -import org.eclipse.jgit.attributes.FilterCommandRegistry; import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.junit.RepositoryTestCase; -import org.eclipse.jgit.lib.Config; -import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.IO; import org.junit.Test; @@ -68,189 +62,6 @@ public class ApplyCommandTest extends RepositoryTestCase { } } - @Test - public void testCrLf() throws Exception { - try { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, true); - ApplyResult result = init("crlf", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "crlf"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "crlf"), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - @Test - public void testCrLfOff() throws Exception { - try { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, false); - ApplyResult result = init("crlf", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "crlf"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "crlf"), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - @Test - public void testCrLfEmptyCommitted() throws Exception { - try { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, true); - ApplyResult result = init("crlf3", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "crlf3"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "crlf3"), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - @Test - public void testCrLfNewFile() throws Exception { - try { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, true); - ApplyResult result = init("crlf4", false, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "crlf4"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "crlf4"), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - @Test - public void testPatchWithCrLf() throws Exception { - try { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, false); - ApplyResult result = init("crlf2", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "crlf2"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "crlf2"), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - @Test - public void testPatchWithCrLf2() throws Exception { - String name = "crlf2"; - try (Git git = new Git(db)) { - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, false); - a = new RawText(readFile(name + "_PreImage")); - write(new File(db.getWorkTree(), name), - a.getString(0, a.size(), false)); - - git.add().addFilepattern(name).call(); - git.commit().setMessage("PreImage").call(); - - b = new RawText(readFile(name + "_PostImage")); - - db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF, true); - ApplyResult result = git.apply() - .setPatch(getTestResource(name + ".patch")).call(); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), name), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), name), - b.getString(0, b.size(), false)); - } finally { - db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_AUTOCRLF); - } - } - - // Clean/smudge filter for testFiltering. The smudgetest test resources were - // created with C git using a clean filter sed -e "s/A/E/g" and the smudge - // filter sed -e "s/E/A/g". To keep the test independent of the presence of - // sed, implement this with a built-in filter. - private static class ReplaceFilter extends FilterCommand { - - private final char toReplace; - - private final char replacement; - - ReplaceFilter(InputStream in, OutputStream out, char toReplace, - char replacement) { - super(in, out); - this.toReplace = toReplace; - this.replacement = replacement; - } - - @Override - public int run() throws IOException { - int b = in.read(); - if (b < 0) { - in.close(); - out.close(); - return -1; - } - if ((b & 0xFF) == toReplace) { - b = replacement; - } - out.write(b); - return 1; - } - } - - @Test - public void testFiltering() throws Exception { - // Set up filter - FilterCommandFactory clean = (repo, in, out) -> { - return new ReplaceFilter(in, out, 'A', 'E'); - }; - FilterCommandFactory smudge = (repo, in, out) -> { - return new ReplaceFilter(in, out, 'E', 'A'); - }; - FilterCommandRegistry.register("jgit://builtin/a2e/clean", clean); - FilterCommandRegistry.register("jgit://builtin/a2e/smudge", smudge); - try (Git git = new Git(db)) { - Config config = db.getConfig(); - config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", - "clean", "jgit://builtin/a2e/clean"); - config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", - "smudge", "jgit://builtin/a2e/smudge"); - write(new File(db.getWorkTree(), ".gitattributes"), - "smudgetest filter=a2e"); - git.add().addFilepattern(".gitattributes").call(); - git.commit().setMessage("Attributes").call(); - ApplyResult result = init("smudgetest", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "smudgetest"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "smudgetest"), - b.getString(0, b.size(), false)); - - } finally { - // Tear down filter - FilterCommandRegistry.unregister("jgit://builtin/a2e/clean"); - FilterCommandRegistry.unregister("jgit://builtin/a2e/smudge"); - } - } - private void checkBinary(String name, boolean hasPreImage) throws Exception { checkBinary(name, hasPreImage, 1); @@ -280,21 +91,6 @@ public class ApplyCommandTest extends RepositoryTestCase { } @Test - public void testBinaryDelta() throws Exception { - checkBinary("delta", true); - } - - @Test - public void testBinaryLiteral() throws Exception { - checkBinary("literal", true); - } - - @Test - public void testBinaryLiteralAdd() throws Exception { - checkBinary("literal_add", false); - } - - @Test public void testEncodingChange() throws Exception { // This is a text patch that changes a file containing ÄÖÜ in UTF-8 to // the same characters in ISO-8859-1. The patch file itself uses mixed @@ -410,188 +206,6 @@ public class ApplyCommandTest extends RepositoryTestCase { b.getString(0, b.size(), false)); } - @Test - public void testModifyM2() throws Exception { - ApplyResult result = init("M2", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - if (FS.DETECTED.supportsExecute()) { - assertTrue(FS.DETECTED.canExecute(result.getUpdatedFiles().get(0))); - } - checkFile(new File(db.getWorkTree(), "M2"), - b.getString(0, b.size(), false)); - } - - @Test - public void testModifyM3() throws Exception { - ApplyResult result = init("M3", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - if (FS.DETECTED.supportsExecute()) { - assertFalse( - FS.DETECTED.canExecute(result.getUpdatedFiles().get(0))); - } - checkFile(new File(db.getWorkTree(), "M3"), - b.getString(0, b.size(), false)); - } - - @Test - public void testModifyX() throws Exception { - ApplyResult result = init("X"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "X"), result.getUpdatedFiles() - .get(0)); - checkFile(new File(db.getWorkTree(), "X"), - b.getString(0, b.size(), false)); - } - - @Test - public void testModifyY() throws Exception { - ApplyResult result = init("Y"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "Y"), result.getUpdatedFiles() - .get(0)); - checkFile(new File(db.getWorkTree(), "Y"), - b.getString(0, b.size(), false)); - } - - @Test - public void testModifyZ() throws Exception { - ApplyResult result = init("Z"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "Z"), result.getUpdatedFiles() - .get(0)); - checkFile(new File(db.getWorkTree(), "Z"), - b.getString(0, b.size(), false)); - } - - @Test - public void testModifyNL1() throws Exception { - ApplyResult result = init("NL1"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NL1"), result - .getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "NL1"), - b.getString(0, b.size(), false)); - } - - @Test - public void testNonASCII() throws Exception { - ApplyResult result = init("NonASCII"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NonASCII"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "NonASCII"), - b.getString(0, b.size(), false)); - } - - @Test - public void testNonASCII2() throws Exception { - ApplyResult result = init("NonASCII2"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NonASCII2"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "NonASCII2"), - b.getString(0, b.size(), false)); - } - - @Test - public void testNonASCIIAdd() throws Exception { - ApplyResult result = init("NonASCIIAdd"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NonASCIIAdd"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "NonASCIIAdd"), - b.getString(0, b.size(), false)); - } - - @Test - public void testNonASCIIAdd2() throws Exception { - ApplyResult result = init("NonASCIIAdd2", false, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NonASCIIAdd2"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "NonASCIIAdd2"), - b.getString(0, b.size(), false)); - } - - @Test - public void testNonASCIIDel() throws Exception { - ApplyResult result = init("NonASCIIDel", true, false); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "NonASCIIDel"), - result.getUpdatedFiles().get(0)); - assertFalse(new File(db.getWorkTree(), "NonASCIIDel").exists()); - } - - @Test - public void testRenameNoHunks() throws Exception { - ApplyResult result = init("RenameNoHunks", true, true); - assertEquals(2, result.getUpdatedFiles().size()); - assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "RenameNoHunks"))); - assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "nested/subdir/Renamed"))); - checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"), - b.getString(0, b.size(), false)); - } - - @Test - public void testRenameWithHunks() throws Exception { - ApplyResult result = init("RenameWithHunks", true, true); - assertEquals(2, result.getUpdatedFiles().size()); - assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "RenameWithHunks"))); - assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "nested/subdir/Renamed"))); - checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"), - b.getString(0, b.size(), false)); - } - - @Test - public void testCopyWithHunks() throws Exception { - ApplyResult result = init("CopyWithHunks", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "CopyResult"), result.getUpdatedFiles() - .get(0)); - checkFile(new File(db.getWorkTree(), "CopyResult"), - b.getString(0, b.size(), false)); - } - - @Test - public void testShiftUp() throws Exception { - ApplyResult result = init("ShiftUp"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "ShiftUp"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "ShiftUp"), - b.getString(0, b.size(), false)); - } - - @Test - public void testShiftUp2() throws Exception { - ApplyResult result = init("ShiftUp2"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "ShiftUp2"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "ShiftUp2"), - b.getString(0, b.size(), false)); - } - - @Test - public void testShiftDown() throws Exception { - ApplyResult result = init("ShiftDown"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "ShiftDown"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "ShiftDown"), - b.getString(0, b.size(), false)); - } - - @Test - public void testShiftDown2() throws Exception { - ApplyResult result = init("ShiftDown2"); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "ShiftDown2"), - result.getUpdatedFiles().get(0)); - checkFile(new File(db.getWorkTree(), "ShiftDown2"), - b.getString(0, b.size(), false)); - } - private static byte[] readFile(String patchFile) throws IOException { final InputStream in = getTestResource(patchFile); if (in == null) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java index 6053c8c568..63ab8094ae 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java @@ -9,8 +9,10 @@ */ package org.eclipse.jgit.api; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -121,9 +123,32 @@ public class CloneCommandTest extends RepositoryTestCase { } @Test - public void testCloneRepository_refLogForLocalRefs() + public void testCloneRepositoryNoCheckout() throws IOException, JGitInternalException, GitAPIException { - File directory = createTempDirectory("testCloneRepository"); + File directory = createTempDirectory("testCloneRepositoryNoCheckout"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setNoCheckout(true); + try (Git git2 = command.call()) { + Repository clonedRepo = git2.getRepository(); + Ref main = clonedRepo.exactRef(Constants.R_HEADS + "test"); + assertNotNull(main); + ObjectId id = main.getObjectId(); + assertNotNull(id); + assertNotEquals(id, ObjectId.zeroId()); + ObjectId headId = clonedRepo.resolve(Constants.HEAD); + assertEquals(id, headId); + assertArrayEquals(new String[] { Constants.DOT_GIT }, + directory.list()); + } + } + + @Test + public void testCloneRepositoryRefLogForLocalRefs() + throws IOException, JGitInternalException, GitAPIException { + File directory = createTempDirectory( + "testCloneRepositoryRefLogForLocalRefs"); CloneCommand command = Git.cloneRepository(); command.setDirectory(directory); command.setURI(fileUri()); @@ -331,7 +356,8 @@ public class CloneCommandTest extends RepositoryTestCase { allRefNames(git2.branchList().setListMode(ListMode.ALL).call())); // Same thing, but now without checkout - directory = createTempDirectory("testCloneRepositoryWithBranch_bare"); + directory = createTempDirectory( + "testCloneRepositoryWithBranch_noCheckout"); command = Git.cloneRepository(); command.setBranch("refs/heads/master"); command.setDirectory(directory); @@ -341,7 +367,8 @@ public class CloneCommandTest extends RepositoryTestCase { addRepoToClose(git2.getRepository()); assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); - assertEquals("refs/remotes/origin/master, refs/remotes/origin/test", + assertEquals( + "refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test", allRefNames(git2.branchList().setListMode(ListMode.ALL).call())); // Same thing, but now test with bare repo diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java index 6f7aa63edc..ff5f8b76cc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java @@ -16,9 +16,12 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.util.Properties; import org.eclipse.jgit.api.errors.DetachedHeadException; @@ -115,7 +118,7 @@ public class PushCommandTest extends RepositoryTestCase { + "\"\nexit 0"); try (Git git1 = new Git(db)) { - // create some refs via commits and tag + // create a commit RevCommit commit = git1.commit().setMessage("initial commit").call(); RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x"); @@ -126,6 +129,54 @@ public class PushCommandTest extends RepositoryTestCase { } } + @Test + public void testPrePushHookRedirects() throws JGitInternalException, + IOException, GitAPIException, URISyntaxException { + + // create other repository + Repository db2 = createWorkRepository(); + + // setup the first repository + final StoredConfig config = db.getConfig(); + RemoteConfig remoteConfig = new RemoteConfig(config, "test"); + URIish uri = new URIish(db2.getDirectory().toURI().toURL()); + remoteConfig.addURI(uri); + remoteConfig.update(config); + config.save(); + + writeHookFile(PrePushHook.NAME, "#!/bin/sh\n" + + "echo \"1:$1, 2:$2, 3:$3\"\n" // to stdout + + "cat - 1>&2\n" // to stderr + + "exit 0\n"); + + try (Git git1 = new Git(db)) { + // create a commit + RevCommit commit = git1.commit().setMessage("initial commit") + .call(); + + RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x"); + try (ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); + ByteArrayOutputStream errBytes = new ByteArrayOutputStream(); + PrintStream stdout = new PrintStream(outBytes, true, + StandardCharsets.UTF_8); + PrintStream stderr = new PrintStream(errBytes, true, + StandardCharsets.UTF_8)) { + git1.push() + .setRemote("test") + .setRefSpecs(spec) + .setHookOutputStream(stdout) + .setHookErrorStream(stderr) + .call(); + String out = outBytes.toString(StandardCharsets.UTF_8); + String err = errBytes.toString(StandardCharsets.UTF_8); + assertEquals("1:test, 2:" + uri + ", 3:\n", out); + assertEquals("refs/heads/master " + commit.getName() + + " refs/heads/x " + ObjectId.zeroId().name() + '\n', + err); + } + } + } + private File writeHookFile(String name, String data) throws IOException { File path = new File(db.getWorkTree() + "/.git/hooks/", name); 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 index 4238ee6bf0..bce62b9371 100644 --- 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 @@ -19,6 +19,8 @@ import java.io.IOException; import java.util.Collections; import java.util.Set; +import org.eclipse.jgit.api.GarbageCollectCommand; +import org.eclipse.jgit.api.Git; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.Ref; @@ -44,7 +46,7 @@ public class DfsBundleWriterTest { } @Test - public void testRepo() throws Exception { + public void makeBundle_containsUnreferencedObject() throws Exception { RevCommit commit0 = git.commit().message("0").create(); RevCommit commit1 = git.commit().message("1").parent(commit0).create(); git.update("master", commit1); @@ -64,6 +66,31 @@ public class DfsBundleWriterTest { } } + @Test + public void makeBundle_containsObjectInGcRestPack() 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(); + + // This moves unreachable commit2 to GC_REST pack. + GarbageCollectCommand gc = Git.wrap(repo).gc(); + gc.call(); + + 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 in GC_REST pack are included as well. + assertTrue(newRepo.getObjectDatabase().has(commit2)); + } + } + private byte[] makeBundle() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); DfsBundleWriter.writeEntireRepositoryAsBundle( diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstCommandTest.java new file mode 100644 index 0000000000..29819a4c3b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstCommandTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022, 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 + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.internal.transport.parser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; + +public class FirstCommandTest { + @Test + public void testClientSID() { + String oldStr = "0000000000000000000000000000000000000000"; + String newStr = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + String refName = "refs/heads/master"; + String command = oldStr + " " + newStr + " " + refName; + String fl = command + "\0" + + "some capabilities session-id=the-clients-SID and more unknownCap=some-value"; + FirstCommand fc = FirstCommand.fromLine(fl); + + Map<String, String> options = fc.getCapabilities(); + + assertEquals("the-clients-SID", options.get("session-id")); + assertEquals(command, fc.getLine()); + assertTrue(options.containsKey("unknownCap")); + assertEquals(6, options.size()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstWantTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstWantTest.java index 1e8ce8ef11..230f6a4081 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstWantTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/transport/parser/FirstWantTest.java @@ -27,7 +27,8 @@ public class FirstWantTest { @Test public void testFirstWantWithOptions() throws PackProtocolException { String line = "want b9d4d1eb2f93058814480eae9e1b67550f46ee38 " - + "no-progress include-tag ofs-delta agent=JGit/unknown"; + + "no-progress include-tag ofs-delta agent=JGit/unknown " + + "session-id=the.client.sid"; FirstWant r = FirstWant.fromLine(line); assertEquals("want b9d4d1eb2f93058814480eae9e1b67550f46ee38", @@ -37,6 +38,7 @@ public class FirstWantTest { Arrays.asList("no-progress", "include-tag", "ofs-delta")); assertEquals(expectedCapabilities, capabilities); assertEquals("JGit/unknown", r.getAgent()); + assertEquals("the.client.sid", r.getClientSID()); } @Test @@ -94,4 +96,12 @@ public class FirstWantTest { assertEquals(r.getCapabilities().size(), 0); assertEquals("pack.age/Version", r.getAgent()); } + + @Test + public void testFirstWantValidSessionID() throws PackProtocolException { + FirstWant r = FirstWant + .fromLine(makeFirstWantLine("session-id=client.session.id")); + assertEquals(r.getCapabilities().size(), 0); + assertEquals("client.session.id", r.getClientSID()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java new file mode 100644 index 0000000000..c77a19f1b4 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2022, 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 + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.patch; + +import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.PatchApplyException; +import org.eclipse.jgit.api.errors.PatchFormatException; +import org.eclipse.jgit.attributes.FilterCommand; +import org.eclipse.jgit.attributes.FilterCommandFactory; +import org.eclipse.jgit.attributes.FilterCommandRegistry; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.patch.PatchApplier.Result; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.IO; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + PatchApplierTest.WithWorktree. class, // + PatchApplierTest.InCore.class, // +}) +public class PatchApplierTest { + + public abstract static class Base extends RepositoryTestCase { + + protected String name; + + /** data before patching. */ + protected byte[] preImage; + /** expected data after patching. */ + protected byte[] postImage; + + protected String expectedText; + protected RevTree baseTip; + public boolean inCore; + + Base(boolean inCore) { + this.inCore = inCore; + } + + protected void init(final String name, final boolean preExists, + final boolean postExists) throws Exception { + /* Patch and pre/postimage are read from data org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ */ + this.name = name; + if (postExists) { + postImage = IO + .readWholeStream(getTestResource(name + "_PostImage"), 0) + .array(); + expectedText = new String(postImage, StandardCharsets.UTF_8); + } + + File f = new File(db.getWorkTree(), name); + if (preExists) { + preImage = IO + .readWholeStream(getTestResource(name + "_PreImage"), 0) + .array(); + try (Git git = new Git(db)) { + Files.write(f.toPath(), preImage); + git.add().addFilepattern(name).call(); + } + } + try (Git git = new Git(db)) { + RevCommit base = git.commit().setMessage("PreImage").call(); + baseTip = base.getTree(); + } + } + + void init(final String name) throws Exception { + init(name, true, true); + } + + protected Result applyPatch() + throws PatchApplyException, PatchFormatException, IOException { + InputStream patchStream = getTestResource(name + ".patch"); + if (inCore) { + try (ObjectInserter oi = db.newObjectInserter()) { + return new PatchApplier(db, baseTip, oi).applyPatch(patchStream); + } + } + return new PatchApplier(db).applyPatch(patchStream); + } + + protected static InputStream getTestResource(String patchFile) { + return PatchApplierTest.class.getClassLoader() + .getResourceAsStream("org/eclipse/jgit/diff/" + patchFile); + } + void verifyChange(Result result, String name) throws Exception { + verifyChange(result, name, true); + } + + protected void verifyContent(Result result, String path, boolean exists) throws Exception { + if (inCore) { + byte[] output = readBlob(result.getTreeId(), path); + if (!exists) + assertNull(output); + else { + assertNotNull(output); + assertEquals(new String(output, StandardCharsets.UTF_8), expectedText); + } + } else { + File f = new File(db.getWorkTree(), path); + if (!exists) + assertFalse(f.exists()); + else + checkFile(f, expectedText); + } + } + + void verifyChange(Result result, String name, boolean exists) throws Exception { + assertEquals(1, result.getPaths().size()); + verifyContent(result, name, exists); + } + + protected byte[] readBlob(ObjectId treeish, String path) throws Exception { + try (TestRepository<?> tr = new TestRepository<>(db); + RevWalk rw = tr.getRevWalk()) { + db.incrementOpen(); + RevTree tree = rw.parseTree(treeish); + try (TreeWalk tw = TreeWalk.forPath(db,path,tree)){ + if (tw == null) { + return null; + } + return tw.getObjectReader().open(tw.getObjectId(0), OBJ_BLOB).getBytes(); + } + } + } + + protected void checkBinary(Result result, int numberOfFiles) throws Exception { + assertEquals(numberOfFiles, result.getPaths().size()); + if (inCore) { + assertArrayEquals(postImage, readBlob(result.getTreeId(), result.getPaths().get(0))); + } else { + File f = new File(db.getWorkTree(), name); + assertArrayEquals(postImage, Files.readAllBytes(f.toPath())); + } + } + + /* tests */ + + @Test + public void testBinaryDelta() throws Exception { + init("delta"); + checkBinary(applyPatch(), 1); + } + + @Test + public void testBinaryLiteral() throws Exception { + init("literal"); + checkBinary(applyPatch(), 1); + } + + @Test + public void testBinaryLiteralAdd() throws Exception { + init("literal_add", false, true); + checkBinary(applyPatch(), 1); + } + + @Test + public void testModifyM2() throws Exception { + init("M2", true, true); + + Result result = applyPatch(); + + if (!inCore && FS.DETECTED.supportsExecute()) { + assertEquals(1, result.getPaths().size()); + File f = new File(db.getWorkTree(), result.getPaths().get(0)); + assertTrue(FS.DETECTED.canExecute(f)); + } + + verifyChange(result, "M2"); + } + + @Test + public void testModifyM3() throws Exception { + init("M3", true, true); + + Result result = applyPatch(); + + verifyChange(result, "M3"); + if (!inCore && FS.DETECTED.supportsExecute()) { + File f = new File(db.getWorkTree(), result.getPaths().get(0)); + assertFalse(FS.DETECTED.canExecute(f)); + } + } + + @Test + public void testModifyX() throws Exception { + init("X"); + + Result result = applyPatch(); + verifyChange(result, "X"); + } + + @Test + public void testModifyY() throws Exception { + init("Y"); + + Result result = applyPatch(); + + verifyChange(result, "Y"); + } + + @Test + public void testModifyZ() throws Exception { + init("Z"); + + Result result = applyPatch(); + verifyChange(result, "Z"); + } + + @Test + public void testNonASCII() throws Exception { + init("NonASCII"); + + Result result = applyPatch(); + verifyChange(result, "NonASCII"); + } + + @Test + public void testNonASCII2() throws Exception { + init("NonASCII2"); + + Result result = applyPatch(); + verifyChange(result, "NonASCII2"); + } + + @Test + public void testNonASCIIAdd() throws Exception { + init("NonASCIIAdd"); + + Result result = applyPatch(); + verifyChange(result, "NonASCIIAdd"); + } + + @Test + public void testNonASCIIAdd2() throws Exception { + init("NonASCIIAdd2", false, true); + + Result result = applyPatch(); + verifyChange(result, "NonASCIIAdd2"); + } + + @Test + public void testNonASCIIDel() throws Exception { + init("NonASCIIDel", true, false); + + Result result = applyPatch(); + verifyChange(result, "NonASCIIDel", false); + assertEquals("NonASCIIDel", result.getPaths().get(0)); + } + + @Test + public void testRenameNoHunks() throws Exception { + init("RenameNoHunks", true, true); + + Result result = applyPatch(); + + assertEquals(2, result.getPaths().size()); + assertTrue(result.getPaths().contains("RenameNoHunks")); + assertTrue(result.getPaths().contains("nested/subdir/Renamed")); + + verifyContent(result,"nested/subdir/Renamed", true); + } + + @Test + public void testRenameWithHunks() throws Exception { + init("RenameWithHunks", true, true); + + Result result = applyPatch(); + assertEquals(2, result.getPaths().size()); + assertTrue(result.getPaths().contains("RenameWithHunks")); + assertTrue(result.getPaths().contains("nested/subdir/Renamed")); + + verifyContent(result,"nested/subdir/Renamed", true); + } + + @Test + public void testCopyWithHunks() throws Exception { + init("CopyWithHunks", true, true); + + Result result = applyPatch(); + verifyChange(result, "CopyResult", true); + } + + @Test + public void testShiftUp() throws Exception { + init("ShiftUp"); + + Result result = applyPatch(); + verifyChange(result, "ShiftUp"); + } + + @Test + public void testShiftUp2() throws Exception { + init("ShiftUp2"); + + Result result = applyPatch(); + verifyChange(result, "ShiftUp2"); + } + + @Test + public void testShiftDown() throws Exception { + init("ShiftDown"); + + Result result = applyPatch(); + verifyChange(result, "ShiftDown"); + } + + @Test + public void testShiftDown2() throws Exception { + init("ShiftDown2"); + + Result result = applyPatch(); + verifyChange(result, "ShiftDown2"); + } + } + + public static class InCore extends Base { + + public InCore() { + super(true); + } + } + + public static class WithWorktree extends Base { + public WithWorktree() { super(false); } + + @Test + public void testModifyNL1() throws Exception { + init("NL1"); + + Result result = applyPatch(); + verifyChange(result, "NL1"); + } + + @Test + public void testCrLf() throws Exception { + try { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, true); + init("crlf", true, true); + + Result result = applyPatch(); + + verifyChange(result, "crlf"); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + @Test + public void testCrLfOff() throws Exception { + try { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, false); + init("crlf", true, true); + + Result result = applyPatch(); + + verifyChange(result, "crlf"); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + @Test + public void testCrLfEmptyCommitted() throws Exception { + try { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, true); + init("crlf3", true, true); + + Result result = applyPatch(); + + verifyChange(result, "crlf3"); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + @Test + public void testCrLfNewFile() throws Exception { + try { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, true); + init("crlf4", false, true); + + Result result = applyPatch(); + + verifyChange(result, "crlf4"); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + @Test + public void testPatchWithCrLf() throws Exception { + try { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, false); + init("crlf2", true, true); + + Result result = applyPatch(); + + verifyChange(result, "crlf2"); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + @Test + public void testPatchWithCrLf2() throws Exception { + String name = "crlf2"; + try (Git git = new Git(db)) { + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, false); + init(name, true, true); + db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, true); + + Result result = applyPatch(); + + verifyChange(result, name); + } finally { + db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF); + } + } + + // Clean/smudge filter for testFiltering. The smudgetest test resources were + // created with C git using a clean filter sed -e "s/A/E/g" and the smudge + // filter sed -e "s/E/A/g". To keep the test independent of the presence of + // sed, implement this with a built-in filter. + private static class ReplaceFilter extends FilterCommand { + + private final char toReplace; + + private final char replacement; + + ReplaceFilter(InputStream in, OutputStream out, char toReplace, + char replacement) { + super(in, out); + this.toReplace = toReplace; + this.replacement = replacement; + } + + @Override + public int run() throws IOException { + int b = in.read(); + if (b < 0) { + in.close(); + out.close(); + return -1; + } + if ((b & 0xFF) == toReplace) { + b = replacement; + } + out.write(b); + return 1; + } + } + + @Test + public void testFiltering() throws Exception { + // Set up filter + FilterCommandFactory clean = (repo, in, out) -> new ReplaceFilter(in, out, 'A', 'E'); + FilterCommandFactory smudge = (repo, in, out) -> new ReplaceFilter(in, out, 'E', 'A'); + FilterCommandRegistry.register("jgit://builtin/a2e/clean", clean); + FilterCommandRegistry.register("jgit://builtin/a2e/smudge", smudge); + Config config = db.getConfig(); + try (Git git = new Git(db)) { + config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", + "clean", "jgit://builtin/a2e/clean"); + config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", + "smudge", "jgit://builtin/a2e/smudge"); + write(new File(db.getWorkTree(), ".gitattributes"), + "smudgetest filter=a2e"); + git.add().addFilepattern(".gitattributes").call(); + git.commit().setMessage("Attributes").call(); + init("smudgetest", true, true); + + Result result = applyPatch(); + + verifyChange(result, name); + } finally { + config.unset(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", + "clean"); + config.unset(ConfigConstants.CONFIG_FILTER_SECTION, "a2e", + "smudge"); + // Tear down filter + FilterCommandRegistry.unregister("jgit://builtin/a2e/clean"); + FilterCommandRegistry.unregister("jgit://builtin/a2e/smudge"); + } + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java index 93bedb3c97..f02428efc9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java @@ -24,6 +24,9 @@ import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.zip.Deflater; import org.eclipse.jgit.errors.TooLargeObjectInPackException; @@ -76,6 +79,49 @@ public class PackParserTest extends RepositoryTestCase { } } + @Test + public void testParsePack1ReadsObjectSizes() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile( + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack"); + + // Sizes from git cat-file -s after unpacking in a local repo + Map<String, Long> expected = new HashMap<>(); + // Commits + expected.put("540a36d136cf413e4b064c2b0e0a4db60f77feab", + Long.valueOf(191)); + expected.put("c59759f143fb1fe21c197981df75a7ee00290799", + Long.valueOf(240)); + expected.put("82c6b885ff600be425b4ea96dee75dca255b69e7", + Long.valueOf(245)); + + // Trees + expected.put("4b825dc642cb6eb9a060e54bf8d69288fbee4904", + Long.valueOf(0)); // empty + expected.put("902d5476fa249b7abc9d84c611577a81381f0327", + Long.valueOf(35)); + expected.put("aabf2ffaec9b497f0950352b3e582d73035c2035", + Long.valueOf(35)); + + // Blobs + expected.put("6ff87c4664981e4397625791c8ea3bbb5f2279a3", + Long.valueOf(18787)); + + // Deltas + expected.put("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", + Long.valueOf(18009)); // delta-oid blob + + + try (InputStream is = new FileInputStream(packFile)) { + ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(is); + p.parse(NullProgressMonitor.INSTANCE); + List<PackedObjectInfo> parsedObjects = p.getSortedObjectList(null); + for (PackedObjectInfo objInfo: parsedObjects) { + assertEquals(objInfo.getName(), objInfo.getFullSize(), + expected.get(objInfo.getName()).longValue()); + } + } + } + /** * This is just another pack. It so happens that we have two convenient pack to * test with in the repository. @@ -107,6 +153,39 @@ public class PackParserTest extends RepositoryTestCase { } @Test + public void testParsePack2ReadsObjectSizes() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile( + "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack"); + Map<String, Long> expected = new HashMap<>(); + // Deltified commit + expected.put("d0114ab8ac326bab30e3a657a0397578c5a1af88", + Long.valueOf(222)); + // Delta of delta of commit + expected.put("f73b95671f326616d66b2afb3bdfcdbbce110b44", + Long.valueOf(221)); + // Deltified tree + expected.put("be9b45333b66013bde1c7314efc50fabd9b39c6d", + Long.valueOf(94)); + + try (InputStream is = new FileInputStream(packFile)) { + ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(is); + p.parse(NullProgressMonitor.INSTANCE); + List<PackedObjectInfo> parsedObjects = p.getSortedObjectList(null); + // Check only the interesting objects + int assertedObjs = 0; + for (PackedObjectInfo objInfo : parsedObjects) { + if (!expected.containsKey(objInfo.getName())) { + continue; + } + assertEquals(objInfo.getName(), objInfo.getFullSize(), + expected.get(objInfo.getName()).longValue()); + assertedObjs += 1; + } + assertEquals(assertedObjs, expected.size()); + } + } + + @Test public void testTinyThinPack() throws Exception { RevBlob a; try (TestRepository d = new TestRepository<Repository>(db)) { @@ -150,6 +229,45 @@ public class PackParserTest extends RepositoryTestCase { } @Test + public void testParseOfsDeltaFullSize() throws Exception { + final byte[] data = Constants.encode("0123456789"); + try (TestRepository<Repository> d = new TestRepository<>(db)) { + db.incrementOpen(); + assertTrue(db.getObjectDatabase().has(d.blob(data))); + } + + TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 2); + pack.write((Constants.OBJ_BLOB) << 4 | 10); // offset 12 + deflate(pack, data); + pack.write((Constants.OBJ_OFS_DELTA) << 4 | 4); // offset 31 + pack.write(19); + deflate(pack, new byte[] { 0xA, 0xB, 0x1, 'b' }); + digest(pack); + + PackParser p = index(new ByteArrayInputStream(pack.toByteArray())); + p.parse(NullProgressMonitor.INSTANCE); + + List<PackedObjectInfo> sortedObjectList = p.getSortedObjectList(null); + assertEquals(sortedObjectList.size(), 2); + + // Deltified comes first because they are sorted by SHA1 + PackedObjectInfo deltifiedObj = sortedObjectList.get(0); + assertEquals(deltifiedObj.getName(), + "16646543f87fb53e30b032eec7dfc88f2e717966"); + assertEquals(deltifiedObj.getOffset(), 31); + assertEquals(deltifiedObj.getType(), Constants.OBJ_BLOB); + assertEquals(deltifiedObj.getFullSize(), 11); + + PackedObjectInfo baseObj = sortedObjectList.get(1); + assertEquals(baseObj.getName(), + "ad471007bd7f5983d273b9584e5629230150fd54"); + assertEquals(baseObj.getOffset(), 12); + assertEquals(baseObj.getType(), Constants.OBJ_BLOB); + assertEquals(baseObj.getFullSize(), 10); + } + + @Test public void testPackWithTrailingGarbage() throws Exception { RevBlob a; try (TestRepository d = new TestRepository<Repository>(db)) { 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 b2a4af30ab..61b7fb619a 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 @@ -98,6 +98,25 @@ public class ProtocolV0ParserTest { "f900c8326a43303685c46b279b9f70411bff1a4b")); } + @Test + public void testRecvWantsWithSessionID() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine(String.join(" ", "want", + "4624442d68ee402a94364191085b77137618633e", "thin-pack", + "agent=JGit.test/0.0.1", "session-id=client-session-id", "\n"), + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + PacketLineIn.end()); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities() + .contains(GitProtocolConstants.OPTION_THIN_PACK)); + assertEquals(1, request.getClientCapabilities().size()); + assertEquals("client-session-id", request.getClientSID()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + /* * First round of protocol v0 negotiation. Client send wants, no * capabilities. 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 167b5b72c6..bab4a36cc4 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 @@ -361,4 +361,28 @@ public class ProtocolV2ParserTest { assertEquals(2, req.getRefPrefixes().size()); assertThat(req.getRefPrefixes(), hasItems("refs/for", "refs/heads")); } + + @Test + public void testFetchWithSessionID() throws IOException { + PacketLineIn pckIn = formatAsPacketLine("session-id=the.client.sid", + PacketLineIn.end()); + + ProtocolV2Parser parser = new ProtocolV2Parser( + ConfigBuilder.start().allowFilter().done()); + FetchV2Request request = parser.parseFetchRequest(pckIn); + + assertEquals("the.client.sid", request.getClientSID()); + } + + @Test + public void testLsRefsWithSessionID() throws IOException { + PacketLineIn pckIn = formatAsPacketLine("session-id=the.client.sid", + PacketLineIn.delimiter(), PacketLineIn.end()); + + ProtocolV2Parser parser = new ProtocolV2Parser( + ConfigBuilder.getDefault()); + LsRefsV2Request req = parser.parseLsRefsRequest(pckIn); + + assertEquals("the.client.sid", req.getClientSID()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java index d9b85fb003..8dad571e5a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransferConfigTest.java @@ -11,6 +11,8 @@ package org.eclipse.jgit.transport; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import org.eclipse.jgit.lib.Config; import org.junit.Test; @@ -66,4 +68,19 @@ public class TransferConfigTest { TransferConfig tc = new TransferConfig(rc); assertNull(tc.protocolVersion); } + + @Test + public void testParseAdvertiseSIDDefault() { + Config rc = new Config(); + TransferConfig tc = new TransferConfig(rc); + assertFalse(tc.isAllowReceiveClientSID()); + } + + @Test + public void testParseAdvertiseSIDSet() { + Config rc = new Config(); + rc.setBoolean("transfer", null, "advertiseSID", true); + TransferConfig tc = new TransferConfig(rc); + assertTrue(tc.isAllowReceiveClientSID()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java index 5ae440f1d2..2019c263fb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java @@ -242,6 +242,37 @@ public class TransportTest extends SampleDataRepositoryTestCase { } @Test + public void testOpenPushUseBitmaps() throws Exception { + URIish uri = new URIish("file://" + db.getWorkTree().getAbsolutePath()); + // default + try (Transport transport = Transport.open(uri)) { + try (PushConnection pushConnection = transport.openPush()) { + assertTrue(pushConnection instanceof BasePackPushConnection); + BasePackPushConnection basePackPushConnection = (BasePackPushConnection) pushConnection; + assertEquals(true, basePackPushConnection.isUseBitmaps()); + } + } + // true + try (Transport transport = Transport.open(uri)) { + transport.setPushUseBitmaps(true); + try (PushConnection pushConnection = transport.openPush()) { + assertTrue(pushConnection instanceof BasePackPushConnection); + BasePackPushConnection basePackPushConnection = (BasePackPushConnection) pushConnection; + assertEquals(true, basePackPushConnection.isUseBitmaps()); + } + } + // false + try (Transport transport = Transport.open(uri)) { + transport.setPushUseBitmaps(false); + try (PushConnection pushConnection = transport.openPush()) { + assertTrue(pushConnection instanceof BasePackPushConnection); + BasePackPushConnection basePackPushConnection = (BasePackPushConnection) pushConnection; + assertEquals(false, basePackPushConnection.isUseBitmaps()); + } + } + } + + @Test public void testSpi() { List<TransportProtocol> protocols = Transport.getTransportProtocols(); assertNotNull(protocols); 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 7131905850..df48afef35 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 @@ -2429,6 +2429,24 @@ public class UploadPackTest { } @Test + public void testGetSessionIDValueProtocolV0() throws Exception { + RevCommit one = remote.commit().message("1").create(); + remote.update("one", one); + + UploadPack up = new UploadPack(server); + ByteArrayInputStream send = linesAsInputStream( + "want " + one.getName() + " agent=JGit-test/1.2.3" + + " session-id=client-session-id\n", + PacketLineIn.end(), + "have 11cedf1b796d44207da702f7d420684022fc0f09\n", "done\n"); + + ByteArrayOutputStream recv = new ByteArrayOutputStream(); + up.upload(send, recv, null); + + assertEquals(up.getClientSID(), "client-session-id"); + } + + @Test public void testGetPeerAgentProtocolV2() throws Exception { server.getConfig().setString(ConfigConstants.CONFIG_PROTOCOL_SECTION, null, ConfigConstants.CONFIG_KEY_VERSION, @@ -2452,6 +2470,30 @@ public class UploadPackTest { assertEquals(up.getPeerUserAgent(), "JGit-test/1.2.4"); } + @Test + public void testGetSessionIDValueProtocolV2() throws Exception { + 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); + + UploadPack up = new UploadPack(server); + up.setExtraParameters(Sets.of("version=2")); + + ByteArrayInputStream send = linesAsInputStream("command=fetch\n", + "agent=JGit-test/1.2.4\n", "session-id=client-session-id\n", + PacketLineIn.delimiter(), "want " + one.getName() + "\n", + "have 11cedf1b796d44207da702f7d420684022fc0f09\n", "done\n", + PacketLineIn.end()); + + ByteArrayOutputStream recv = new ByteArrayOutputStream(); + up.upload(send, recv, null); + + assertEquals(up.getClientSID(), "client-session-id"); + } + private static class RejectAllRefFilter implements RefFilter { @Override public Map<String, Ref> filter(Map<String, Ref> refs) { |