From eca101fc0570e739cc722bf2977973ac2a4ce147 Mon Sep 17 00:00:00 2001 From: yunjieli Date: Mon, 28 Mar 2022 14:47:02 -0700 Subject: Fetch: Introduce negative refspecs. Implement negative refspecs in JGit fetch, following C Git. Git supports negative refspecs in source only while this change supports them in both source and destination. If one branch is equal to any branch or matches any pattern in the negative refspecs collection, the branch will not be fetched even if it's in the toFetch collection. With this feature, users can express more complex patterns during fetch. Change-Id: Iaa1cd4de5c08c273e198b72e12e3dadae7be709f Sign-off-by: Yunjie Li --- .../tst/org/eclipse/jgit/api/FetchCommandTest.java | 47 +++++++++++++++++++++ .../org/eclipse/jgit/transport/RefSpecTest.java | 48 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) (limited to 'org.eclipse.jgit.test/tst/org/eclipse') diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java index 6479d157eb..0884d72235 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java @@ -95,6 +95,53 @@ public class FetchCommandTest extends RepositoryTestCase { res.getTrackingRefUpdate("refs/heads/master").getResult()); } + @Test + public void testFetchSimpleNegativeRefSpec() throws Exception { + remoteGit.commit().setMessage("commit").call(); + + FetchResult res = git.fetch().setRemote("test") + .setRefSpecs("refs/heads/master:refs/heads/test", + "^:refs/heads/test") + .call(); + assertNull(res.getTrackingRefUpdate("refs/heads/test")); + + res = git.fetch().setRemote("test") + .setRefSpecs("refs/heads/master:refs/heads/test", + "^refs/heads/master") + .call(); + assertNull(res.getTrackingRefUpdate("refs/heads/test")); + } + + @Test + public void negativeRefSpecFilterBySource() throws Exception { + remoteGit.commit().setMessage("commit").call(); + remoteGit.branchCreate().setName("test").call(); + remoteGit.commit().setMessage("commit1").call(); + remoteGit.branchCreate().setName("dev").call(); + + FetchResult res = git.fetch().setRemote("test") + .setRefSpecs("refs/*:refs/origins/*", "^refs/*/test") + .call(); + assertNotNull(res.getTrackingRefUpdate("refs/origins/heads/master")); + assertNull(res.getTrackingRefUpdate("refs/origins/heads/test")); + assertNotNull(res.getTrackingRefUpdate("refs/origins/heads/dev")); + } + + @Test + public void negativeRefSpecFilterByDestination() throws Exception { + remoteGit.commit().setMessage("commit").call(); + remoteGit.branchCreate().setName("meta").call(); + remoteGit.commit().setMessage("commit1").call(); + remoteGit.branchCreate().setName("data").call(); + + FetchResult res = git.fetch().setRemote("test") + .setRefSpecs("refs/*:refs/secret/*", "^:refs/secret/*/meta") + .call(); + assertNotNull(res.getTrackingRefUpdate("refs/secret/heads/master")); + assertNull(res.getTrackingRefUpdate("refs/secret/heads/meta")); + assertNotNull(res.getTrackingRefUpdate("refs/secret/heads/data")); + } + @Test public void fetchAddsBranches() throws Exception { final String branch1 = "b1"; diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java index b56308cb72..ef0817adb8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java @@ -443,6 +443,26 @@ public class RefSpecTest { a.setDestination("refs/remotes/origin/*/*"); } + @Test(expected = IllegalArgumentException.class) + public void invalidNegativeAndForce() { + assertNotNull(new RefSpec("^+refs/heads/master")); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidForceAndNegative() { + assertNotNull(new RefSpec("+^refs/heads/master")); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidNegativeNoSrcDest() { + assertNotNull(new RefSpec("^")); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidNegativeBothSrcDest() { + assertNotNull(new RefSpec("^refs/heads/*:refs/heads/*")); + } + @Test public void sourceOnlywithWildcard() { RefSpec a = new RefSpec("refs/heads/*", @@ -480,4 +500,32 @@ public class RefSpecTest { assertTrue(a.isMatching()); assertTrue(a.isForceUpdate()); } + + @Test + public void negativeRefSpecWithDest() { + RefSpec a = new RefSpec("^:refs/readonly/*"); + assertTrue(a.isNegative()); + assertNull(a.getSource()); + assertEquals(a.getDestination(), "refs/readonly/*"); + } + + // Because of some of the API's existing behavior, without a colon at the + // end of the refspec, dest will be null. + @Test + public void negativeRefSpecWithSrcAndNullDest() { + RefSpec a = new RefSpec("^refs/testdata/*"); + assertTrue(a.isNegative()); + assertNull(a.getDestination()); + assertEquals(a.getSource(), "refs/testdata/*"); + } + + // Because of some of the API's existing behavior, with a colon at the end + // of the refspec, dest will be empty. + @Test + public void negativeRefSpecWithSrcAndEmptyDest() { + RefSpec a = new RefSpec("^refs/testdata/*:"); + assertTrue(a.isNegative()); + assertTrue(a.getDestination().isEmpty()); + assertEquals(a.getSource(), "refs/testdata/*"); + } } -- cgit v1.2.3