From 8a2c76941729629dce06e2238464e114f2ccc79a Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Sun, 20 Feb 2022 18:11:49 +0100 Subject: [push] support the "matching" RefSpecs ":" and "+:" The implementation of push.default=matching was not correct. It used the RefSpec "refs/heads/*:refs/heads/*", which would push _all_ local branches. But "matching" must push only those local branches for which a remote branch with the same name already exists at the remote. This RefSpec can be expanded only once the advertisement from the remote has been received. Enhance RefSpec so that ":" and "+:" can be represented. Introduce a special RemoteRefUpdate for such a RefSpec; it must carry through the fetch RefSpecs to be able to fill in the remote tracking updates as needed. Implement the expansion in PushProcess. Bug: 353405 Change-Id: I54a4bfbb0a6a7d77b9128bf4a9c951d6586c3df4 Signed-off-by: Thomas Wolf --- .../tst/org/eclipse/jgit/api/PushCommandTest.java | 57 ++++++++++++++++++---- .../org/eclipse/jgit/transport/RefSpecTest.java | 14 ++++++ 2 files changed, 61 insertions(+), 10 deletions(-) (limited to 'org.eclipse.jgit.test/tst/org/eclipse') 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 1a1f5b487e..6f7aa63edc 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 @@ -10,6 +10,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -392,28 +393,64 @@ public class PushCommandTest extends RepositoryTestCase { git.add().addFilepattern("f").call(); RevCommit commit = git.commit().setMessage("adding f").call(); - git.checkout().setName("also-pushed").setCreateBranch(true).call(); + git.checkout().setName("not-pushed").setCreateBranch(true).call(); git.checkout().setName("branchtopush").setCreateBranch(true).call(); assertEquals(null, git2.getRepository().resolve("refs/heads/branchtopush")); assertEquals(null, - git2.getRepository().resolve("refs/heads/also-pushed")); + git2.getRepository().resolve("refs/heads/not-pushed")); assertEquals(null, git2.getRepository().resolve("refs/heads/master")); - git.push().setRemote("test").setPushDefault(PushDefault.MATCHING) + // push master and branchtopush + git.push().setRemote("test").setRefSpecs( + new RefSpec("refs/heads/master:refs/heads/master"), + new RefSpec( + "refs/heads/branchtopush:refs/heads/branchtopush")) .call(); assertEquals(commit.getId(), - git2.getRepository().resolve("refs/heads/branchtopush")); - assertEquals(commit.getId(), - git2.getRepository().resolve("refs/heads/also-pushed")); + git2.getRepository().resolve("refs/heads/master")); assertEquals(commit.getId(), + git2.getRepository().resolve("refs/heads/branchtopush")); + assertEquals(null, + git2.getRepository().resolve("refs/heads/not-pushed")); + // Create two different commits on these two branches + writeTrashFile("b", "on branchtopush"); + git.add().addFilepattern("b").call(); + RevCommit bCommit = git.commit().setMessage("on branchtopush") + .call(); + git.checkout().setName("master").call(); + writeTrashFile("m", "on master"); + git.add().addFilepattern("m").call(); + RevCommit mCommit = git.commit().setMessage("on master").call(); + // Now push with mode "matching": should push both branches. + Iterable result = git.push().setRemote("test") + .setPushDefault(PushDefault.MATCHING) + .call(); + int n = 0; + for (PushResult r : result) { + n++; + assertEquals(1, n); + assertEquals(2, r.getRemoteUpdates().size()); + for (RemoteRefUpdate update : r.getRemoteUpdates()) { + assertFalse(update.isMatching()); + assertTrue(update.getSrcRef() + .equals("refs/heads/branchtopush") + || update.getSrcRef().equals("refs/heads/master")); + assertEquals(RemoteRefUpdate.Status.OK, update.getStatus()); + } + } + assertEquals(bCommit.getId(), + git2.getRepository().resolve("refs/heads/branchtopush")); + assertEquals(null, + git2.getRepository().resolve("refs/heads/not-pushed")); + assertEquals(mCommit.getId(), git2.getRepository().resolve("refs/heads/master")); - assertEquals(commit.getId(), git.getRepository() + assertEquals(bCommit.getId(), git.getRepository() .resolve("refs/remotes/origin/branchtopush")); - assertEquals(commit.getId(), git.getRepository() - .resolve("refs/remotes/origin/also-pushed")); - assertEquals(commit.getId(), + assertEquals(null, git.getRepository() + .resolve("refs/remotes/origin/not-pushed")); + assertEquals(mCommit.getId(), git.getRepository().resolve("refs/remotes/origin/master")); } } 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 5569bca23c..b56308cb72 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 @@ -466,4 +466,18 @@ public class RefSpecTest { assertTrue(a.matchSource("refs/heads/master")); assertNull(a.getDestination()); } + + @Test + public void matching() { + RefSpec a = new RefSpec(":"); + assertTrue(a.isMatching()); + assertFalse(a.isForceUpdate()); + } + + @Test + public void matchingForced() { + RefSpec a = new RefSpec("+:"); + assertTrue(a.isMatching()); + assertTrue(a.isForceUpdate()); + } } -- cgit v1.2.3