aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test/tst/org/eclipse/jgit
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java15
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java53
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java37
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java55
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java13
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/BitmapIndexTest.java85
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java40
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java8
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java51
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java1
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RequestValidatorTestCase.java18
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java132
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java23
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java19
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/ByteBufferInputStreamTest.java152
17 files changed, 699 insertions, 7 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
index 87be813c85..7c1cbc37d6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BranchCommandTest.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import java.util.List;
@@ -160,6 +161,20 @@ public class BranchCommandTest extends RepositoryTestCase {
- allBefore);
}
+ @Test
+ public void testExistingNameInBothBranchesAndTags() throws Exception {
+ git.branchCreate().setName("test").call();
+ git.tag().setName("test").call();
+
+ // existing name not allowed w/o force
+ assertThrows("Create branch with existing ref name should fail",
+ RefAlreadyExistsException.class,
+ () -> git.branchCreate().setName("test").call());
+
+ // existing name allowed with force option
+ git.branchCreate().setName("test").setForce(true).call();
+ }
+
@Test(expected = InvalidRefNameException.class)
public void testInvalidBranchHEAD() throws Exception {
git.branchCreate().setName("HEAD").call();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
index 7f820b0433..16f7cd1eb0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
@@ -2221,7 +2221,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkoutBranch("refs/heads/master");
writeTrashFile(FILE1, "modified file1");
git.add().addFilepattern(FILE1).call();
- git.commit().setMessage("commit3").call();
+ git.commit().setMessage("commit2").call();
// checkout topic branch / modify file0
checkoutBranch("refs/heads/topic");
@@ -2240,6 +2240,57 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
}
+ @Test
+ public void testFastForwardRebaseWithAutoStashConflict() throws Exception {
+ // create file0, add and commit
+ db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
+ writeTrashFile("file0", "file0");
+ git.add().addFilepattern("file0").call();
+ git.commit().setMessage("commit0").call();
+ // create file1, add and commit
+ writeTrashFile(FILE1, "file1");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit commit = git.commit().setMessage("commit1").call();
+
+ // create topic branch
+ createBranch(commit, "refs/heads/topic");
+
+ // checkout master branch / modify file1, add and commit
+ checkoutBranch("refs/heads/master");
+ writeTrashFile(FILE1, "modified file1");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit master = git.commit().setMessage("commit2").call();
+
+ // checkout topic branch / modify file0 and file1
+ checkoutBranch("refs/heads/topic");
+ writeTrashFile("file0", "unstaged modified file0");
+ writeTrashFile(FILE1, "unstaged modified file1");
+
+ // rebase
+ assertEquals(Status.STASH_APPLY_CONFLICTS,
+ git.rebase().setUpstream("refs/heads/master").call()
+ .getStatus());
+ checkFile(new File(db.getWorkTree(), "file0"),
+ "unstaged modified file0");
+ checkFile(new File(db.getWorkTree(), FILE1),
+ "<<<<<<< HEAD\n"
+ + "modified file1\n"
+ + "=======\n"
+ + "unstaged modified file1\n"
+ + ">>>>>>> stash\n");
+ // If there is a merge conflict, the index is not reset, and thus file0
+ // is staged here. This is the same behavior as in C git.
+ String expected = "[file0, mode:100644, content:unstaged modified file0]"
+ + "[file1, mode:100644, stage:1, content:file1]"
+ + "[file1, mode:100644, stage:2, content:modified file1]"
+ + "[file1, mode:100644, stage:3, content:unstaged modified file1]";
+ assertEquals(expected, indexState(CONTENT));
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ assertEquals(master, db.resolve(Constants.HEAD));
+ assertEquals(master, db.resolve("refs/heads/topic"));
+ }
+
private List<DiffEntry> getStashedDiff() throws AmbiguousObjectException,
IncorrectObjectTypeException, IOException, MissingObjectException {
ObjectId stashId = db.resolve("stash@{0}");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
index 1c7b8d13a8..4ebe994ef7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
@@ -39,6 +39,7 @@ import org.junit.Test;
* Test revert command
*/
public class RevertCommandTest extends RepositoryTestCase {
+
@Test
public void testRevert() throws IOException, JGitInternalException,
GitAPIException {
@@ -90,7 +91,43 @@ public class RevertCommandTest extends RepositoryTestCase {
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
}
+ }
+
+ @Test
+ public void testRevertWithChangeId()
+ throws IOException, JGitInternalException, GitAPIException {
+ try (Git git = new Git(db)) {
+ writeTrashFile("a", "first line\nthird line\n");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("create a").call();
+
+ writeTrashFile("a", "first line\nsecond line\nthird line\n");
+ git.add().addFilepattern("a").call();
+ RevCommit second = git.commit().setMessage("changed a").call();
+
+ writeTrashFile("a",
+ "first line\nsecond line\nthird line\nfourth line\n");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("changed a again").call();
+
+ git.revert().include(second).setInsertChangeId(true).call();
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+
+ checkFile(new File(db.getWorkTree(), "a"),
+ "first line\nthird line\nfourth line\n");
+ Iterator<RevCommit> history = git.log().call().iterator();
+ RevCommit revertCommit = history.next();
+ String expectedMessage = "Revert \"changed a\"\n\n"
+ + "This reverts commit " + second.getId().getName() + ".\n";
+ String commitMessage = revertCommit.getFullMessage();
+ assertTrue(commitMessage.matches("^\\Q" + expectedMessage
+ + "\\E\nChange-Id: I[a-fA-F0-9]{40}\n$"));
+ assertEquals("changed a again", history.next().getFullMessage());
+ assertEquals("changed a", history.next().getFullMessage());
+ assertEquals("create a", history.next().getFullMessage());
+ assertFalse(history.hasNext());
+ }
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
index 5040a3b6ad..9f65ee2074 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/commitgraph/CommitGraphWriterTest.java
@@ -14,6 +14,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
@@ -31,6 +32,7 @@ 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.ProgressMonitor;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -135,6 +137,59 @@ public class CommitGraphWriterTest extends RepositoryTestCase {
NB.decodeInt32(data, 56));
}
+ @Test
+ public void testProgressMonitor() throws Exception {
+ RevCommit root = commit();
+ RevCommit a = commit(root);
+ RevCommit b = commit(root);
+ RevCommit tip = commit(a, b);
+ Set<ObjectId> wants = Collections.singleton(tip);
+
+ NonNestedTasksProgressMonitor nonNested = new NonNestedTasksProgressMonitor();
+ GraphCommits graphCommits = GraphCommits.fromWalk(nonNested, wants,
+ walk);
+ writer = new CommitGraphWriter(graphCommits, true);
+ writer.write(nonNested, os);
+ }
+
+ private static class NonNestedTasksProgressMonitor
+ implements ProgressMonitor {
+
+ boolean inTask;
+
+ @Override
+ public void start(int totalTasks) {
+ // empty
+ }
+
+ @Override
+ public void beginTask(String title, int totalWork) {
+ assertFalse("Previous monitoring task is not closed", inTask);
+ inTask = true;
+ }
+
+ @Override
+ public void update(int completed) {
+ // empty
+ }
+
+ @Override
+ public void endTask() {
+ assertTrue("Closing task that wasn't started", inTask);
+ inTask = false;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public void showDuration(boolean enabled) {
+ // empty
+ }
+ }
+
static HashSet<String> changedPathStrings(byte[] data) {
int oidf_offset = -1;
int bidx_offset = -1;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
index 48f6e06385..8b27b829b2 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTestCase.java
@@ -61,6 +61,7 @@ public abstract class GcTestCase extends LocalDiskRepositoryTestCase {
* the depth of the commit chain.
* @return the commit that is the tip of the commit chain
* @throws Exception
+ * if an error occurred
*/
protected RevCommit commitChain(int depth) throws Exception {
if (depth <= 0)
@@ -93,6 +94,7 @@ public abstract class GcTestCase extends LocalDiskRepositoryTestCase {
* number of files added per commit
* @return the commit that is the tip of the commit chain
* @throws Exception
+ * if an error occurred
*/
protected RevCommit commitChain(int depth, int width) throws Exception {
if (depth <= 0) {
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 67bba18e2b..24bdc4a97a 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
@@ -66,7 +66,9 @@ public abstract class PackIndexTestCase extends RepositoryTestCase {
* Verify CRC32 support.
*
* @throws MissingObjectException
+ * object is missing in the underlying index
* @throws UnsupportedOperationException
+ * the index doesn't have CRC
*/
public abstract void testCRC32() throws MissingObjectException,
UnsupportedOperationException;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
index 619e585a90..2bafde65d3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java
@@ -51,6 +51,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.StringUtils;
import org.junit.Before;
import org.junit.Test;
@@ -1349,6 +1350,18 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase {
assertEquals(Storage.LOOSE, ref.getStorage());
}
+ @Test
+ public void testCommonRefPrefix() {
+ assertEquals("", StringUtils.commonPrefix());
+ assertEquals("HEAD", StringUtils.commonPrefix("HEAD"));
+ assertEquals("", StringUtils.commonPrefix("HEAD", ""));
+ assertEquals("", StringUtils.commonPrefix("HEAD", "refs/heads/"));
+ assertEquals("refs/heads/",
+ StringUtils.commonPrefix("refs/heads/master", "refs/heads/"));
+ assertEquals("refs/heads/",
+ StringUtils.commonPrefix("refs/heads/", "refs/heads/main"));
+ }
+
void writePackedRef(String name, AnyObjectId id) throws IOException {
writePackedRefs(id.name() + " " + name + "\n");
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/BitmapIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/BitmapIndexTest.java
new file mode 100644
index 0000000000..ee4fa8bcc7
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/BitmapIndexTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024, 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.lib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.internal.storage.file.GC;
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BitmapIndexTest extends LocalDiskRepositoryTestCase {
+
+ private static final String MAIN = "refs/heads/main";
+
+ TestRepository<FileRepository> repo;
+
+ RevCommit tipWithBitmap;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ FileRepository db = createWorkRepository();
+ repo = new TestRepository<>(db);
+
+ RevCommit base = repo.commit().create();
+ RevCommit one = repo.commit().parent(base).create();
+ tipWithBitmap = repo.commit().parent(one).create();
+ repo.update(MAIN, tipWithBitmap);
+
+ GC gc = new GC(repo.getRepository());
+ gc.setAuto(false);
+ gc.gc().get();
+
+ assertNotNull(repo.getRevWalk().getObjectReader().getBitmapIndex());
+ }
+
+
+ @Test
+ public void listener_getBitmap_counted() throws Exception {
+ try (RevWalk rw = repo.getRevWalk();
+ ObjectReader or = rw.getObjectReader()) {
+ BitmapLookupCounter counter = new BitmapLookupCounter();
+ BitmapIndex bitmapIndex = or.getBitmapIndex();
+ bitmapIndex.addBitmapLookupListener(counter);
+
+ bitmapIndex.getBitmap(tipWithBitmap);
+ bitmapIndex.getBitmap(tipWithBitmap);
+ bitmapIndex.getBitmap(ObjectId.zeroId());
+
+ assertEquals(2, counter.bitmapFound);
+ assertEquals(1, counter.bitmapNotFound);
+ }
+ }
+
+ private static class BitmapLookupCounter
+ implements BitmapIndex.BitmapLookupListener {
+ int bitmapFound = 0;
+
+ int bitmapNotFound = 0;
+
+ @Override
+ public void onBitmapFound(AnyObjectId oid) {
+ bitmapFound += 1;
+ }
+
+ @Override
+ public void onBitmapNotFound(AnyObjectId oid) {
+ bitmapNotFound += 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
index 36cf77bb01..0c0257df90 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
@@ -507,6 +507,35 @@ public class ConfigTest {
}
@Test
+ public void testRemoveBranchSection() throws ConfigInvalidException {
+ Config c = parse("" //
+ + "[branch \"keep\"]\n"
+ + " merge = master.branch.to.keep.in.the.file\n"
+ + "\n"
+ + "[branch \"remove\"]\n"
+ + " merge = this.will.get.deleted\n"
+ + " remote = origin-for-some-long-gone-place\n"
+ + "\n"
+ + "\n"
+ + "[core-section-not-to-remove-in-test]\n"
+ + " packedGitLimit = 14\n"
+ + "\n"
+ + "[other]\n"
+ + " foo = bar\n");
+ assertFalse(c.removeSection("branch", "does.not.exist"));
+ assertTrue(c.removeSection("branch", "remove"));
+ assertEquals("" //
+ + "[branch \"keep\"]\n"
+ + " merge = master.branch.to.keep.in.the.file\n"
+ + "\n"
+ + "[core-section-not-to-remove-in-test]\n"
+ + " packedGitLimit = 14\n"
+ + "\n"
+ + "[other]\n"
+ + " foo = bar\n", c.toText());
+ }
+
+ @Test
public void testUnsetBranchSection() throws ConfigInvalidException {
Config c = parse("" //
+ "[branch \"keep\"]\n"
@@ -516,8 +545,12 @@ public class ConfigTest {
+ " merge = this.will.get.deleted\n"
+ " remote = origin-for-some-long-gone-place\n"
+ "\n"
+ + "\n"
+ "[core-section-not-to-remove-in-test]\n"
- + " packedGitLimit = 14\n");
+ + " packedGitLimit = 14\n"
+ + "\n"
+ + "[other]\n"
+ + " foo = bar\n");
c.unsetSection("branch", "does.not.exist");
c.unsetSection("branch", "remove");
assertEquals("" //
@@ -525,7 +558,10 @@ public class ConfigTest {
+ " merge = master.branch.to.keep.in.the.file\n"
+ "\n"
+ "[core-section-not-to-remove-in-test]\n"
- + " packedGitLimit = 14\n", c.toText());
+ + " packedGitLimit = 14\n"
+ + "\n"
+ + "[other]\n"
+ + " foo = bar\n", c.toText());
}
@Test
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
index 92d47c2966..2aac15bbb6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java
@@ -496,6 +496,14 @@ public class PatchApplierTest {
Result result = applyPatch();
verifyChange(result, "x_last_rm_nl");
}
+
+ @Test
+ public void testVeryLongFile() throws Exception {
+ init("very_long_file");
+
+ Result result = applyPatch();
+ verifyChange(result, "very_long_file");
+ }
}
public static class WithWorktree extends Base {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
index 01f6a3a0a0..303aedcd00 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java
@@ -318,6 +318,57 @@ public class FooterLineTest extends RepositoryTestCase {
assertFalse("not CC", line.matches(FooterKey.CC));
}
+ @Test
+ public void testMultilineFooters() {
+ String msg = buildMessage("subject\n\nbody of commit\n"
+ + "Not-A-Footer-Line: this line must not be read as a footer\n"
+ + "\n" // paragraph break, now footers appear in final block
+ + "Notes: The change must not be merged until dependency ABC is\n"
+ + " updated.\n"
+ + "CC: <some.mailing.list@example.com>\n"
+ + "not really a footer line but we'll skip it anyway\n"
+ + "Acked-by: Some Reviewer <sr@example.com>\n");
+ List<FooterLine> footers = FooterLine.fromMessage(msg);
+ FooterLine f;
+
+ assertNotNull(footers);
+ assertEquals(3, footers.size());
+
+ f = footers.get(0);
+ assertEquals("Notes", f.getKey());
+ assertEquals(
+ "The change must not be merged until dependency ABC is updated.",
+ f.getValue());
+
+ f = footers.get(1);
+ assertEquals("CC", f.getKey());
+ assertEquals("<some.mailing.list@example.com>", f.getValue());
+
+ f = footers.get(2);
+ assertEquals("Acked-by", f.getKey());
+ assertEquals("Some Reviewer <sr@example.com>", f.getValue());
+ }
+
+ @Test
+ public void testMultilineFooters_multipleWhitespaceAreAllowed() {
+ String msg = buildMessage("subject\n\nbody of commit\n"
+ + "Not-A-Footer-Line: this line must not be read as a footer\n"
+ + "\n" // paragraph break, now footers appear in final block
+ + "Notes: The change must not be merged until dependency ABC is\n"
+ + " updated.\n");
+ List<FooterLine> footers = FooterLine.fromMessage(msg);
+ FooterLine f;
+
+ assertNotNull(footers);
+ assertEquals(1, footers.size());
+
+ f = footers.get(0);
+ assertEquals("Notes", f.getKey());
+ assertEquals(
+ "The change must not be merged until dependency ABC is updated.",
+ f.getValue());
+ }
+
private String buildMessage(String msg) {
StringBuilder buf = new StringBuilder();
buf.append("tree " + ObjectId.zeroId().name() + "\n");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
index 578128326f..4f5e35f129 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java
@@ -35,6 +35,7 @@ public abstract class SampleDataRepositoryTestCase extends RepositoryTestCase {
* @param repo
* test repository to receive packfile copies
* @throws IOException
+ * an error occurred
*/
public static void copyCGitTestPacks(FileRepository repo) throws IOException {
final String[] packs = {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RequestValidatorTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RequestValidatorTestCase.java
index cc910b3b9f..f589a399a4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RequestValidatorTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RequestValidatorTestCase.java
@@ -70,20 +70,30 @@ public abstract class RequestValidatorTestCase {
}
/**
+ * Check if the validator accepts a reachable commit
+ *
* @return true if a commit reachable from a visible tip (but not directly
* the tip) is valid
*/
protected abstract boolean isReachableCommitValid();
- /** @return true if a commit not reachable from any tip is valid */
+ /**
+ * Check if the validator accepts an unreachable commit
+ *
+ * @return true if a commit not reachable from any tip is valid
+ **/
protected abstract boolean isUnreachableCommitValid();
/**
+ * Check if the validator accepts a previously advertised tip
+ *
* @return true if the commit directly pointed by an advertised ref is valid
*/
protected abstract boolean isAdvertisedTipValid();
/**
+ * Check if the validator accepts a previous unadvertised tip
+ *
* @return true if the object directly pointed by a non-advertised ref is
* valid
*/
@@ -92,17 +102,23 @@ public abstract class RequestValidatorTestCase {
// UploadPack doesn't allow to ask for blobs when there is no
// bitmap. Test both cases separately.
/**
+ * Check if the validator accepts a reachable blob (repo with bitmaps)
+ *
* @return true if a reachable blob is valid (and the repo has bitmaps)
*/
protected abstract boolean isReachableBlobValid_withBitmaps();
/**
+ * Check if the validator accepts a reachable blob (repo without bitmaps)
+ *
* @return true if a reachable blob is valid (and the repo does NOT have
* bitmaps)
*/
protected abstract boolean isReachableBlobValid_withoutBitmaps();
/**
+ * Check if the validator accepts an unreachable blob
+ *
* @return true if a blob unreachable from any tip is valid
*/
protected abstract boolean isUnreachableBlobValid();
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 f9687f9f82..026492f7b6 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
@@ -2215,7 +2215,8 @@ public class UploadPackTest {
uri = testProtocol.register(ctx, server);
- TestProtocol.setFetchConfig(new FetchConfig(true, MAX_HAVES, true));
+ TestProtocol.setFetchConfig(new FetchConfig(true, MAX_HAVES,
+ /* useNegotiationTip= */true));
try (Transport tn = testProtocol.open(uri,
clientRepo.getRepository(), "server")) {
@@ -2335,7 +2336,8 @@ public class UploadPackTest {
}, null);
uri = testProtocol.register(ctx, server);
- TestProtocol.setFetchConfig(new FetchConfig(true, MAX_HAVES, true));
+ TestProtocol.setFetchConfig(new FetchConfig(true, MAX_HAVES,
+ /* useNegotiationTip= */true));
try (Transport tn = testProtocol.open(uri,
clientRepo.getRepository(), "server")) {
@@ -2362,6 +2364,67 @@ public class UploadPackTest {
}
}
+ /**
+ * <pre>
+ * remote:
+ * foo &lt;- foofoo &lt;-- branchFoo
+ * bar &lt;- barbar &lt;-- branchBar
+ *
+ * client:
+ * none
+ *
+ * fetch(branchFoo) should not send have and should get only branchFoo back
+ * </pre>
+ */
+ @Test
+ public void testNegotiationTipDoesNotDoFullClone() throws Exception {
+ RevCommit fooParent = remote.commit().message("foo").create();
+ RevCommit fooChild = remote.commit().message("foofoo").parent(fooParent)
+ .create();
+ RevCommit barParent = remote.commit().message("bar").create();
+ RevCommit barChild = remote.commit().message("barbar").parent(barParent)
+ .create();
+
+ // Remote has branchFoo at fooChild and branchBar at barChild
+ remote.update("branchFoo", fooChild);
+ remote.update("branchBar", barChild);
+
+ AtomicReference<UploadPack> uploadPack = new AtomicReference<>();
+ CountHavesPreUploadHook countHavesHook = new CountHavesPreUploadHook();
+
+ // Client does not have branchFoo & branchBar
+ try (TestRepository<InMemoryRepository> clientRepo = new TestRepository<>(
+ client)) {
+ testProtocol = new TestProtocol<>((Object req, Repository db) -> {
+ UploadPack up = new UploadPack(db);
+ up.setPreUploadHook(countHavesHook);
+ uploadPack.set(up);
+ return up;
+ }, null);
+
+ uri = testProtocol.register(ctx, server);
+
+ TestProtocol.setFetchConfig(new FetchConfig(true, MAX_HAVES,
+ /* useNegotiationTip= */true));
+ try (Transport tn = testProtocol.open(uri,
+ clientRepo.getRepository(), "server")) {
+
+ tn.fetch(NullProgressMonitor.INSTANCE,
+ Collections.singletonList(
+ new RefSpec("refs/heads/branchFoo")),
+ "branchFoo");
+ }
+ }
+
+ assertTrue(client.getObjectDatabase().has(fooParent.toObjectId()));
+ assertTrue(client.getObjectDatabase().has(fooChild.toObjectId()));
+ assertFalse(client.getObjectDatabase().has(barParent.toObjectId()));
+ assertFalse(client.getObjectDatabase().has(barChild.toObjectId()));
+
+ assertEquals(0, uploadPack.get().getStatistics().getHaves());
+ assertTrue(countHavesHook.havesSentDuringNegotiation.isEmpty());
+ }
+
private static class CountHavesPreUploadHook implements PreUploadHook {
Set<ObjectId> havesSentDuringNegotiation = new HashSet<>();
@@ -2937,7 +3000,70 @@ public class UploadPackTest {
assertThat(pckIn.readString(), is("packfile"));
parsePack(recvStream);
assertTrue(client.getObjectDatabase().has(one.toObjectId()));
- assertEquals(1, ((RefCallsCountingRepository)server).numRefCalls());
+ assertEquals(0, ((RefCallsCountingRepository)server).numRefCalls());
+ }
+
+ /*
+ * Invokes UploadPack with specified protocol version and sends it the given
+ * lines, and returns UploadPack statistics (use uploadPackSetup to get the
+ * output stream)
+ */
+ private PackStatistics uploadPackV2SetupStats(String... inputLines)
+ throws Exception {
+
+ ByteArrayInputStream send = linesAsInputStream(inputLines);
+ String version = TransferConfig.ProtocolVersion.V2.version();
+ server.getConfig().setString(ConfigConstants.CONFIG_PROTOCOL_SECTION,
+ null, ConfigConstants.CONFIG_KEY_VERSION, version);
+ try (UploadPack up = new UploadPack(server)) {
+ up.setExtraParameters(Sets.of("version=".concat(version)));
+
+ ByteArrayOutputStream recv = new ByteArrayOutputStream();
+ up.upload(send, recv, null);
+ return up.getStatistics();
+ }
+ }
+
+ @Test
+ public void testUseWantedRefsAsAdvertisedSetV2_onlyWantedRefs()
+ throws Exception {
+ server = new RefCallsCountingRepository(
+ new DfsRepositoryDescription("server"));
+ remote = new TestRepository<>(server);
+ RevCommit one = remote.commit().message("1").create();
+ RevCommit two = remote.commit().message("2").create();
+ RevCommit three = remote.commit().message("3").create();
+ remote.update("one", one);
+ remote.update("two", two);
+ remote.update("three", three);
+ server.getConfig().setBoolean("uploadpack", null, "allowrefinwant",
+ true);
+ PackStatistics packStats = uploadPackV2SetupStats("command=fetch\n",
+ PacketLineIn.delimiter(), "want-ref refs/heads/one\n",
+ "want-ref refs/heads/two\n", "done\n", PacketLineIn.end());
+ assertEquals("only wanted-refs", 2, packStats.getAdvertised());
+ assertEquals(0, ((RefCallsCountingRepository) server).numRefCalls());
+ }
+
+ @Test
+ public void testUseWantedRefsAsAdvertisedSetV2_withWantId()
+ throws Exception {
+ server = new RefCallsCountingRepository(
+ new DfsRepositoryDescription("server"));
+ remote = new TestRepository<>(server);
+ RevCommit one = remote.commit().message("1").create();
+ RevCommit two = remote.commit().message("2").create();
+ RevCommit three = remote.commit().message("3").create();
+ remote.update("one", one);
+ remote.update("two", two);
+ remote.update("three", three);
+ server.getConfig().setBoolean("uploadpack", null, "allowrefinwant",
+ true);
+ PackStatistics packStats = uploadPackV2SetupStats("command=fetch\n",
+ PacketLineIn.delimiter(), "want-ref refs/heads/one\n",
+ "want " + one.getName() + "\n", "done\n", PacketLineIn.end());
+ assertEquals("all refs", 3, packStats.getAdvertised());
+ assertEquals(1, ((RefCallsCountingRepository) server).numRefCalls());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
index 171d80c3da..51236e1cc0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
@@ -13,6 +13,7 @@ package org.eclipse.jgit.util;
import static java.time.Instant.EPOCH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue;
@@ -233,4 +234,26 @@ public class FSTest {
assertFalse(RepositoryCache.FileKey
.isGitRepository(new File("repo.git"), FS.DETECTED));
}
+
+ @Test
+ public void testSearchPath() throws IOException {
+ File f1 = new File(trash, "file1");
+ FileUtils.createNewFile(f1);
+ f1.setExecutable(true);
+ File f2 = new File(trash, "file2");
+ FileUtils.createNewFile(f2);
+ assertEquals(f1, FS.searchPath(trash.getAbsolutePath(), "file1"));
+ assertNull(FS.searchPath(trash.getAbsolutePath(), "file2"));
+ }
+
+ @Test
+ public void testSearchPathEmptyPath() {
+ assertNull(FS.searchPath("", "file1"));
+ assertNull(FS.searchPath(File.pathSeparator, "file1"));
+ assertNull(FS.searchPath(File.pathSeparator + File.pathSeparator,
+ "file1"));
+ assertNull(FS.searchPath(
+ " " + File.pathSeparator + " " + File.pathSeparator + " \t",
+ "file1"));
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
index aa7247e105..015da164c3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
@@ -153,4 +153,23 @@ public class StringUtilsTest {
() -> StringUtils.parseLongWithSuffix("8000000000000000000G",
false));
}
+
+ @Test
+ public void testCommonPrefix() {
+ assertEquals("", StringUtils.commonPrefix((String[]) null));
+ assertEquals("", StringUtils.commonPrefix(new String[] {}));
+ assertEquals("", StringUtils.commonPrefix(new String[] { null }));
+ assertEquals("", StringUtils.commonPrefix(null, null));
+ assertEquals("", StringUtils.commonPrefix("", ""));
+ assertEquals("", StringUtils.commonPrefix(null, ""));
+ assertEquals("", StringUtils.commonPrefix("abcd", null, null));
+ assertEquals("", StringUtils.commonPrefix(null, null, "abcd"));
+ assertEquals("", StringUtils.commonPrefix("", "abcd"));
+ assertEquals("", StringUtils.commonPrefix("abcd", "efgh"));
+ assertEquals("abcd", StringUtils.commonPrefix("abcd"));
+ assertEquals("ab", StringUtils.commonPrefix("abcd", "ab"));
+ assertEquals("abcd", StringUtils.commonPrefix("abcd", "abcdefgh"));
+ assertEquals("foo bar ",
+ StringUtils.commonPrefix("foo bar 42", "foo bar 24"));
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/ByteBufferInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/ByteBufferInputStreamTest.java
new file mode 100644
index 0000000000..ec9f96ed96
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/ByteBufferInputStreamTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023, SAP SE 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 org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ByteBufferInputStreamTest {
+
+ private static final byte data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+
+ private ByteBuffer buf;
+
+ private ByteBufferInputStream is;
+
+ @Before
+ public void setup() {
+ buf = ByteBuffer.wrap(data);
+ is = new ByteBufferInputStream(buf);
+ }
+
+ @After
+ public void tearDown() {
+ is.close();
+ }
+
+ @Test
+ public void testRead() throws IOException {
+ assertEquals(0x00, is.read());
+ assertEquals(0x01, is.read());
+ assertEquals(0x02, is.read());
+ assertEquals(0x03, is.read());
+ assertEquals(0x04, is.read());
+ assertEquals(0x05, is.read());
+ assertEquals(0x06, is.read());
+ assertEquals(0x07, is.read());
+ assertEquals(0x08, is.read());
+ assertEquals(0x09, is.read());
+ assertEquals(0x0A, is.read());
+ assertEquals(0x0B, is.read());
+ assertEquals(0x0C, is.read());
+ assertEquals(0x0D, is.read());
+ assertEquals(0x0E, is.read());
+ assertEquals(0x0F, is.read());
+ assertEquals(-1, is.read());
+ }
+
+ @Test
+ public void testReadMultiple() throws IOException {
+ byte[] x = new byte[5];
+ int n = is.read(x);
+ assertEquals(5, n);
+ assertArrayEquals(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, x);
+ }
+
+ @Test
+ public void testReadMultipleOffset() throws IOException {
+ byte[] x = new byte[7];
+ int n = is.read(x, 4, 3);
+ assertEquals(3, n);
+ assertArrayEquals(
+ new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 },
+ x);
+ }
+
+ @Test
+ public void testReadAll() throws IOException {
+ byte[] x = is.readAllBytes();
+ assertEquals(16, x.length);
+ assertArrayEquals(data, x);
+ }
+
+ @Test
+ public void testMarkReset() throws IOException {
+ byte[] x = new byte[5];
+ int n = is.read(x);
+ assertEquals(11, is.available());
+ assertTrue(is.markSupported());
+ is.mark(is.available());
+ is.reset();
+ byte[] y = new byte[5];
+ int m = is.read(y);
+ assertEquals(n, m);
+ assertArrayEquals(new byte[] { 0x05, 0x06, 0x07, 0x08, 0x09 }, y);
+ }
+
+ @Test
+ public void testClosed() {
+ is.close();
+ Exception e = assertThrows(IOException.class, () -> is.read());
+ assertEquals(JGitText.get().inputStreamClosed, e.getMessage());
+ }
+
+ @Test
+ public void testReadNBytes() throws IOException {
+ byte[] x = is.readNBytes(4);
+ assertArrayEquals(new byte[] { 0x00, 0x01, 0x02, 0x03 }, x);
+ }
+
+ @Test
+ public void testReadNBytesOffset() throws IOException {
+ byte[] x = new byte[10];
+ Arrays.fill(x, (byte) 0x0F);
+ is.readNBytes(x, 3, 4);
+ assertArrayEquals(new byte[] { 0x0F, 0x0F, 0x0F, 0x00, 0x01, 0x02, 0x03,
+ 0x0F, 0x0F, 0x0F }, x);
+ }
+
+ @Test
+ public void testRead0() throws IOException {
+ byte[] x = new byte[7];
+ int n = is.read(x, 4, 0);
+ assertEquals(0, n);
+
+ is.readAllBytes();
+ n = is.read(x, 4, 3);
+ assertEquals(-1, n);
+ }
+
+ @Test
+ public void testSkip() throws IOException {
+ assertEquals(15, is.skip(15));
+ assertEquals(0x0F, is.read());
+ assertEquals(-1, is.read());
+ }
+
+ @Test
+ public void testSkip0() throws IOException {
+ assertEquals(0, is.skip(0));
+ assertEquals(0x00, is.read());
+ }
+}