aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java1287
1 files changed, 1090 insertions, 197 deletions
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 19f074ea55..d1696d62a8 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
@@ -1,71 +1,55 @@
/*
- * Copyright (C) 2010, 2014 Chris Aniszczyk <caniszczyk@gmail.com>
- * and other copyright owners as documented in the project's IP log.
+ * Copyright (C) 2010, 2014 Chris Aniszczyk <caniszczyk@gmail.com> and others
*
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
*
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.api;
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;
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.time.Instant;
import java.util.Properties;
+import org.eclipse.jgit.api.errors.DetachedHeadException;
import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.NoRemoteRepositoryException;
+import org.eclipse.jgit.hooks.PrePushHook;
+import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PushConfig.PushDefault;
import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RefLeaseSpec;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.util.FS;
import org.junit.Test;
public class PushCommandTest extends RepositoryTestCase {
@@ -76,6 +60,12 @@ public class PushCommandTest extends RepositoryTestCase {
// create other repository
Repository db2 = createWorkRepository();
+ addRepoToClose(db2);
+ final StoredConfig config2 = db2.getConfig();
+
+ // this tests that this config can be parsed properly
+ config2.setString("fsck", "", "missingEmail", "ignore");
+ config2.save();
// setup the first repository
final StoredConfig config = db.getConfig();
@@ -85,75 +75,165 @@ public class PushCommandTest extends RepositoryTestCase {
remoteConfig.update(config);
config.save();
- Git git1 = new Git(db);
- // create some refs via commits and tag
- RevCommit commit = git1.commit().setMessage("initial commit").call();
- Ref tagRef = git1.tag().setName("tag").call();
+ try (Git git1 = new Git(db)) {
+ // create some refs via commits and tag
+ RevCommit commit = git1.commit().setMessage("initial commit").call();
+ Ref tagRef = git1.tag().setName("tag").call();
- try {
- db2.resolve(commit.getId().getName() + "^{commit}");
- fail("id shouldn't exist yet");
- } catch (MissingObjectException e) {
- // we should get here
- }
+ try {
+ db2.resolve(commit.getId().getName() + "^{commit}");
+ fail("id shouldn't exist yet");
+ } catch (MissingObjectException e) {
+ // we should get here
+ }
- RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
- git1.push().setRemote("test").setRefSpecs(spec)
- .call();
+ RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
+ git1.push().setRemote("test").setRefSpecs(spec)
+ .call();
- assertEquals(commit.getId(),
- db2.resolve(commit.getId().getName() + "^{commit}"));
- assertEquals(tagRef.getObjectId(),
- db2.resolve(tagRef.getObjectId().getName()));
+ assertEquals(commit.getId(),
+ db2.resolve(commit.getId().getName() + "^{commit}"));
+ assertEquals(tagRef.getObjectId(),
+ db2.resolve(tagRef.getObjectId().getName()));
+ }
}
@Test
- public void testTrackingUpdate() throws Exception {
- Repository db2 = createBareRepository();
+ public void testPrePushHook() throws JGitInternalException, IOException,
+ GitAPIException, URISyntaxException {
- String remote = "origin";
- String branch = "refs/heads/master";
- String trackingBranch = "refs/remotes/" + remote + "/master";
+ // 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();
+
+ File hookOutput = new File(getTemporaryDirectory(), "hookOutput");
+ writeHookFile(PrePushHook.NAME, "#!/bin/sh\necho 1:$1, 2:$2, 3:$3 >\""
+ + hookOutput.toPath() + "\"\ncat - >>\"" + hookOutput.toPath()
+ + "\"\nexit 0");
- Git git = new Git(db);
+ try (Git git1 = new Git(db)) {
+ // create a commit
+ RevCommit commit = git1.commit().setMessage("initial commit").call();
- RevCommit commit1 = git.commit().setMessage("Initial commit")
- .call();
+ RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
+ git1.push().setRemote("test").setRefSpecs(spec).call();
+ assertEquals("1:test, 2:" + uri + ", 3:\n" + "refs/heads/master "
+ + commit.getName() + " refs/heads/x "
+ + ObjectId.zeroId().name() + "\n", read(hookOutput));
+ }
+ }
- RefUpdate branchRefUpdate = db.updateRef(branch);
- branchRefUpdate.setNewObjectId(commit1.getId());
- branchRefUpdate.update();
+ @Test
+ public void testPrePushHookRedirects() throws JGitInternalException,
+ IOException, GitAPIException, URISyntaxException {
- RefUpdate trackingBranchRefUpdate = db.updateRef(trackingBranch);
- trackingBranchRefUpdate.setNewObjectId(commit1.getId());
- trackingBranchRefUpdate.update();
+ // create other repository
+ Repository db2 = createWorkRepository();
+ // setup the first repository
final StoredConfig config = db.getConfig();
- RemoteConfig remoteConfig = new RemoteConfig(config, remote);
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
URIish uri = new URIish(db2.getDirectory().toURI().toURL());
remoteConfig.addURI(uri);
- remoteConfig.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/"
- + remote + "/*"));
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");
- RevCommit commit2 = git.commit().setMessage("Commit to push").call();
+ try (Git git1 = new Git(db)) {
+ // create a commit
+ RevCommit commit = git1.commit().setMessage("initial commit")
+ .call();
- RefSpec spec = new RefSpec(branch + ":" + branch);
- Iterable<PushResult> resultIterable = git.push().setRemote(remote)
- .setRefSpecs(spec).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);
+ }
+ }
+ }
- PushResult result = resultIterable.iterator().next();
- TrackingRefUpdate trackingRefUpdate = result
- .getTrackingRefUpdate(trackingBranch);
+ private File writeHookFile(String name, String data)
+ throws IOException {
+ File path = new File(db.getWorkTree() + "/.git/hooks/", name);
+ JGitTestUtil.write(path, data);
+ FS.DETECTED.setExecute(path, true);
+ return path;
+ }
- assertNotNull(trackingRefUpdate);
- assertEquals(trackingBranch, trackingRefUpdate.getLocalName());
- assertEquals(branch, trackingRefUpdate.getRemoteName());
- assertEquals(commit2.getId(), trackingRefUpdate.getNewObjectId());
- assertEquals(commit2.getId(), db.resolve(trackingBranch));
- assertEquals(commit2.getId(), db2.resolve(branch));
+
+ @Test
+ public void testTrackingUpdate() throws Exception {
+ Repository db2 = createBareRepository();
+
+ String remote = "origin";
+ String branch = "refs/heads/master";
+ String trackingBranch = "refs/remotes/" + remote + "/master";
+
+ try (Git git = new Git(db)) {
+ RevCommit commit1 = git.commit().setMessage("Initial commit")
+ .call();
+
+ RefUpdate branchRefUpdate = db.updateRef(branch);
+ branchRefUpdate.setNewObjectId(commit1.getId());
+ branchRefUpdate.update();
+
+ RefUpdate trackingBranchRefUpdate = db.updateRef(trackingBranch);
+ trackingBranchRefUpdate.setNewObjectId(commit1.getId());
+ trackingBranchRefUpdate.update();
+
+ final StoredConfig config = db.getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, remote);
+ URIish uri = new URIish(db2.getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/"
+ + remote + "/*"));
+ remoteConfig.update(config);
+ config.save();
+
+
+ RevCommit commit2 = git.commit().setMessage("Commit to push").call();
+
+ RefSpec spec = new RefSpec(branch + ":" + branch);
+ Iterable<PushResult> resultIterable = git.push().setRemote(remote)
+ .setRefSpecs(spec).call();
+
+ PushResult result = resultIterable.iterator().next();
+ TrackingRefUpdate trackingRefUpdate = result
+ .getTrackingRefUpdate(trackingBranch);
+
+ assertNotNull(trackingRefUpdate);
+ assertEquals(trackingBranch, trackingRefUpdate.getLocalName());
+ assertEquals(branch, trackingRefUpdate.getRemoteName());
+ assertEquals(commit2.getId(), trackingRefUpdate.getNewObjectId());
+ assertEquals(commit2.getId(), db.resolve(trackingBranch));
+ assertEquals(commit2.getId(), db2.resolve(branch));
+ }
}
/**
@@ -163,113 +243,872 @@ public class PushCommandTest extends RepositoryTestCase {
*/
@Test
public void testPushRefUpdate() throws Exception {
- Git git = new Git(db);
- Git git2 = new Git(createBareRepository());
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
+ .toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addPushRefSpec(new RefSpec("+refs/heads/*:refs/heads/*"));
+ remoteConfig.update(config);
+ config.save();
- final StoredConfig config = git.getRepository().getConfig();
- RemoteConfig remoteConfig = new RemoteConfig(config, "test");
- URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
- .toURL());
- remoteConfig.addURI(uri);
- remoteConfig.addPushRefSpec(new RefSpec("+refs/heads/*:refs/heads/*"));
- remoteConfig.update(config);
- config.save();
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
- writeTrashFile("f", "content of f");
- git.add().addFilepattern("f").call();
- RevCommit commit = git.commit().setMessage("adding f").call();
+ assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
+ git.push().setRemote("test").call();
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/master"));
- assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
- git.push().setRemote("test").call();
- assertEquals(commit.getId(),
- git2.getRepository().resolve("refs/heads/master"));
+ git.branchCreate().setName("refs/heads/test").call();
+ git.checkout().setName("refs/heads/test").call();
- git.branchCreate().setName("refs/heads/test").call();
- git.checkout().setName("refs/heads/test").call();
+ for (int i = 0; i < 6; i++) {
+ writeTrashFile("f" + i, "content of f" + i);
+ git.add().addFilepattern("f" + i).call();
+ commit = git.commit().setMessage("adding f" + i).call();
+ git.push().setRemote("test").call();
+ git2.getRepository().getRefDatabase().getRefs();
+ assertEquals("failed to update on attempt " + i, commit.getId(),
+ git2.getRepository().resolve("refs/heads/test"));
+ }
+ }
+ }
+ /**
+ * Check that the push refspec is read from config.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushWithRefSpecFromConfig() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
+ .toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addPushRefSpec(new RefSpec("HEAD:refs/heads/newbranch"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
- for (int i = 0; i < 6; i++) {
- writeTrashFile("f" + i, "content of f" + i);
- git.add().addFilepattern("f" + i).call();
- commit = git.commit().setMessage("adding f" + i).call();
+ assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
git.push().setRemote("test").call();
- git2.getRepository().getAllRefs();
- assertEquals("failed to update on attempt " + i, commit.getId(),
- git2.getRepository().resolve("refs/heads/test"));
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/newbranch"));
+ }
+ }
+ /**
+ * Check that only HEAD is pushed if no refspec is given.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushWithoutPushRefSpec() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
+ .toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(new RefSpec(
+ "+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").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/not-pushed"));
+ assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
+ git.push().setRemote("test").call();
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null, git2.getRepository()
+ .resolve("refs/heads/not-pushed"));
+ assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
}
}
/**
- * Check that the push refspec is read from config.
+ * Check that pushing from a detached HEAD without refspec throws a
+ * DetachedHeadException.
*
* @throws Exception
*/
@Test
- public void testPushWithRefSpecFromConfig() throws Exception {
- Git git = new Git(db);
- Git git2 = new Git(createBareRepository());
+ public void testPushDefaultDetachedHead() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
- final StoredConfig config = git.getRepository().getConfig();
- RemoteConfig remoteConfig = new RemoteConfig(config, "test");
- URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
- .toURL());
- remoteConfig.addURI(uri);
- remoteConfig.addPushRefSpec(new RefSpec("HEAD:refs/heads/newbranch"));
- remoteConfig.update(config);
- config.save();
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
- writeTrashFile("f", "content of f");
- git.add().addFilepattern("f").call();
- RevCommit commit = git.commit().setMessage("adding f").call();
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+ git.checkout().setName(commit.getName()).call();
+ String head = git.getRepository().getFullBranch();
+ assertTrue(ObjectId.isId(head));
+ assertEquals(commit.getName(), head);
+ assertThrows(DetachedHeadException.class,
+ () -> git.push().setRemote("test").call());
+ }
+ }
- assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
- git.push().setRemote("test").call();
- assertEquals(commit.getId(),
- git2.getRepository().resolve("refs/heads/newbranch"));
+ /**
+ * Check that push.default=nothing without refspec throws an
+ * InvalidRefNameException.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultNothing() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").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/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertThrows(InvalidRefNameException.class,
+ () -> git.push().setRemote("test")
+ .setPushDefault(PushDefault.NOTHING).call());
+ }
}
/**
- * Check that only HEAD is pushed if no refspec is given.
+ * Check that push.default=matching without refspec pushes all matching
+ * branches.
*
* @throws Exception
*/
@Test
- public void testPushWithoutPushRefSpec() throws Exception {
- Git git = new Git(db);
- Git git2 = new Git(createBareRepository());
+ public void testPushDefaultMatching() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ final StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
- final StoredConfig config = git.getRepository().getConfig();
- RemoteConfig remoteConfig = new RemoteConfig(config, "test");
- URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
- .toURL());
- remoteConfig.addURI(uri);
- remoteConfig.addFetchRefSpec(new RefSpec(
- "+refs/heads/*:refs/remotes/origin/*"));
- remoteConfig.update(config);
- config.save();
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").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/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ // 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/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<PushResult> 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(bCommit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ assertEquals(null, git.getRepository()
+ .resolve("refs/remotes/origin/not-pushed"));
+ assertEquals(mCommit.getId(),
+ git.getRepository().resolve("refs/remotes/origin/master"));
+ }
+ }
+
+ /**
+ * Check that push.default=upstream without refspec pushes only the current
+ * branch to the configured upstream.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultUpstream() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/upstreambranch");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ git.push().setRemote("test").setPushDefault(PushDefault.UPSTREAM)
+ .call();
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/upstreambranch"));
+ assertEquals(null, git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
+ }
+
+ /**
+ * Check that push.default=upstream without refspec throws an
+ * InvalidRefNameException if the current branch has no upstream.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultUpstreamNoTracking() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class,
+ () -> git.push().setRemote("test")
+ .setPushDefault(PushDefault.UPSTREAM).call());
+ }
+ }
+
+ /**
+ * Check that push.default=upstream without refspec throws an
+ * InvalidRefNameException if the push remote is not the same as the fetch
+ * remote.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultUpstreamTriangular() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ // Don't configure a remote; it'll default to "origin".
+ config.setString("branch", "branchtopush", "merge",
+ "upstreambranch");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class,
+ () -> git.push().setRemote("test")
+ .setPushDefault(PushDefault.UPSTREAM).call());
+ }
+ }
+
+ /**
+ * Check that push.default=simple without refspec pushes only the current
+ * branch to the configured upstream name.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultSimple() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/branchtopush");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ git.push().setRemote("test").setPushDefault(PushDefault.SIMPLE)
+ .call();
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
+ }
+
+ /**
+ * Check that push.default=simple without refspec pushes only the current
+ * branch to a branch with the same name in a triangular workflow.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultSimpleTriangular() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ // Don't set remote, it'll default to "origin". Configure a
+ // different branch name; should be ignored.
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/upstreambranch");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ git.push().setRemote("test").setPushDefault(PushDefault.SIMPLE)
+ .call();
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
+ }
+
+ /**
+ * Check that push.default=simple without refspec throws an
+ * InvalidRefNameException if the current branch has no upstream.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultSimpleNoTracking() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
- writeTrashFile("f", "content of f");
- git.add().addFilepattern("f").call();
- RevCommit commit = git.commit().setMessage("adding f").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/not-pushed"));
- assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
- git.push().setRemote("test").call();
- assertEquals(commit.getId(),
- git2.getRepository().resolve("refs/heads/branchtopush"));
- assertEquals(null, git2.getRepository()
- .resolve("refs/heads/not-pushed"));
- assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class,
+ () -> git.push().setRemote("test")
+ .setPushDefault(PushDefault.SIMPLE).call());
+ }
+ }
+
+ /**
+ * Check that push.default=simple without refspec throws an
+ * InvalidRefNameException if the current branch has an upstream with a
+ * different name.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultSimpleDifferentTracking() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/upstreambranch");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class,
+ () -> git.push().setRemote("test")
+ .setPushDefault(PushDefault.SIMPLE).call());
+ }
+ }
+
+ /**
+ * Check that if no PushDefault is set, the value is read from the git
+ * config.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultFromConfig() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.setString("push", null, "default", "upstream");
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/upstreambranch");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ PushCommand cmd = git.push();
+ cmd.setRemote("test").setPushDefault(null).call();
+ assertEquals(PushDefault.UPSTREAM, cmd.getPushDefault());
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/upstreambranch"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/upstreambranch"));
+ assertEquals(null, git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
+ }
+
+ /**
+ * Check that if no PushDefault is set and none is set in the git config, it
+ * defaults to "simple".
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPushDefaultFromConfigDefault() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/branchtopush");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ PushCommand cmd = git.push();
+ cmd.setRemote("test").setPushDefault(null).call();
+ assertEquals(PushDefault.SIMPLE, cmd.getPushDefault());
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
+ }
+
+ /**
+ * Check that branch.&lt;name&gt;.pushRemote overrides anything else.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testBranchPushRemote() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.setString("remote", null, "pushDefault", "test");
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "pushremote", "origin");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/branchtopush");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class, () -> git.push()
+ .setPushDefault(PushDefault.UPSTREAM).call());
+ }
+ }
+
+ /**
+ * Check that remote.pushDefault overrides branch.&lt;name&gt;.remote
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testRemotePushDefault() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.setString("remote", null, "pushDefault", "origin");
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/branchtopush");
+ config.save();
+
+ assertThrows(InvalidRefNameException.class, () -> git.push()
+ .setPushDefault(PushDefault.UPSTREAM).call());
+ }
+ }
+
+ /**
+ * Check that ultimately we fall back to "origin".
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testDefaultRemote() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "merge",
+ "refs/heads/branchtopush");
+ config.save();
+
+ PushCommand cmd = git.push().setPushDefault(PushDefault.UPSTREAM);
+ TransportException e = assertThrows(TransportException.class,
+ () -> cmd.call());
+ assertEquals(NoRemoteRepositoryException.class,
+ e.getCause().getClass());
+ assertEquals("origin", cmd.getRemote());
+ }
+ }
+
+ /**
+ * Check that a push without specifying a remote or mode or anything can
+ * succeed if the git config is correct.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testDefaultPush() throws Exception {
+ try (Git git = new Git(db);
+ Git git2 = new Git(createBareRepository())) {
+ StoredConfig config = git.getRepository().getConfig();
+ RemoteConfig remoteConfig = new RemoteConfig(config, "test");
+ URIish uri = new URIish(
+ git2.getRepository().getDirectory().toURI().toURL());
+ remoteConfig.addURI(uri);
+ remoteConfig.addFetchRefSpec(
+ new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
+ remoteConfig.update(config);
+ config.save();
+
+ writeTrashFile("f", "content of f");
+ git.add().addFilepattern("f").call();
+ RevCommit commit = git.commit().setMessage("adding f").call();
+
+ git.checkout().setName("not-pushed").setCreateBranch(true).call();
+ git.checkout().setName("branchtopush").setCreateBranch(true).call();
+
+ config = git.getRepository().getConfig();
+ config.setString("branch", "branchtopush", "remote", "test");
+ config.save();
+
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ // Should use remote "test", push.default=current
+ PushCommand cmd = git.push();
+ cmd.call();
+ assertEquals("test", cmd.getRemote());
+ assertEquals(PushDefault.CURRENT, cmd.getPushDefault());
+ assertEquals(commit.getId(),
+ git2.getRepository().resolve("refs/heads/branchtopush"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/not-pushed"));
+ assertEquals(null,
+ git2.getRepository().resolve("refs/heads/master"));
+ assertEquals(commit.getId(), git.getRepository()
+ .resolve("refs/remotes/origin/branchtopush"));
+ }
}
/**
@@ -281,6 +1120,7 @@ public class PushCommandTest extends RepositoryTestCase {
public void testPushAfterGC() throws Exception {
// create other repository
Repository db2 = createWorkRepository();
+ addRepoToClose(db2);
// setup the first repository
final StoredConfig config = db.getConfig();
@@ -290,51 +1130,104 @@ public class PushCommandTest extends RepositoryTestCase {
remoteConfig.update(config);
config.save();
- Git git1 = new Git(db);
- Git git2 = new Git(db2);
+ try (Git git1 = new Git(db);
+ Git git2 = new Git(db2)) {
+ // push master (with a new commit) to the remote
+ git1.commit().setMessage("initial commit").call();
- // push master (with a new commit) to the remote
- git1.commit().setMessage("initial commit").call();
+ RefSpec spec = new RefSpec("refs/heads/*:refs/heads/*");
+ git1.push().setRemote("test").setRefSpecs(spec).call();
- RefSpec spec = new RefSpec("refs/heads/*:refs/heads/*");
- git1.push().setRemote("test").setRefSpecs(spec).call();
+ // create an unrelated ref and a commit on our remote
+ git2.branchCreate().setName("refs/heads/other").call();
+ git2.checkout().setName("refs/heads/other").call();
- // create an unrelated ref and a commit on our remote
- git2.branchCreate().setName("refs/heads/other").call();
- git2.checkout().setName("refs/heads/other").call();
+ writeTrashFile("a", "content of a");
+ git2.add().addFilepattern("a").call();
+ RevCommit commit2 = git2.commit().setMessage("adding a").call();
- writeTrashFile("a", "content of a");
- git2.add().addFilepattern("a").call();
- RevCommit commit2 = git2.commit().setMessage("adding a").call();
+ // run a gc to ensure we have a bitmap index
+ Properties res = git1.gc().setExpire((Instant) null).call();
+ assertEquals(8, res.size());
- // run a gc to ensure we have a bitmap index
- Properties res = git1.gc().setExpire(null).call();
- assertEquals(7, res.size());
+ // create another commit so we have something else to push
+ writeTrashFile("b", "content of b");
+ git1.add().addFilepattern("b").call();
+ RevCommit commit3 = git1.commit().setMessage("adding b").call();
- // create another commit so we have something else to push
- writeTrashFile("b", "content of b");
- git1.add().addFilepattern("b").call();
- RevCommit commit3 = git1.commit().setMessage("adding b").call();
+ try {
+ // Re-run the push. Failure may happen here.
+ git1.push().setRemote("test").setRefSpecs(spec).call();
+ } catch (TransportException e) {
+ assertTrue("should be caused by a MissingObjectException", e
+ .getCause().getCause() instanceof MissingObjectException);
+ fail("caught MissingObjectException for a change we don't have");
+ }
- try {
- // Re-run the push. Failure may happen here.
- git1.push().setRemote("test").setRefSpecs(spec).call();
- } catch (TransportException e) {
- assertTrue("should be caused by a MissingObjectException", e
- .getCause().getCause() instanceof MissingObjectException);
- fail("caught MissingObjectException for a change we don't have");
+ // Remote will have both a and b. Master will have only b
+ try {
+ db.resolve(commit2.getId().getName() + "^{commit}");
+ fail("id shouldn't exist locally");
+ } catch (MissingObjectException e) {
+ // we should get here
+ }
+ assertEquals(commit2.getId(),
+ db2.resolve(commit2.getId().getName() + "^{commit}"));
+ assertEquals(commit3.getId(),
+ db2.resolve(commit3.getId().getName() + "^{commit}"));
}
+ }
+
+ @Test
+ public void testPushWithLease() throws JGitInternalException, IOException,
+ GitAPIException, URISyntaxException {
+
+ // create other repository
+ Repository db2 = createWorkRepository();
+ addRepoToClose(db2);
+
+ // 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();
+
+ try (Git git1 = new Git(db)) {
+ // create one commit and push it
+ RevCommit commit = git1.commit().setMessage("initial commit").call();
+ git1.branchCreate().setName("initial").call();
+
+ RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
+ git1.push().setRemote("test").setRefSpecs(spec)
+ .call();
+
+ assertEquals(commit.getId(),
+ db2.resolve(commit.getId().getName() + "^{commit}"));
+ //now try to force-push a new commit, with a good lease
+
+ git1.commit().setMessage("second commit").call();
+ Iterable<PushResult> results =
+ git1.push().setRemote("test").setRefSpecs(spec)
+ .setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
+ .call();
+ for (PushResult result : results) {
+ RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
+ assertEquals(update.getStatus(), RemoteRefUpdate.Status.OK);
+ }
+
+ git1.commit().setMessage("third commit").call();
+ //now try to force-push a new commit, with a bad lease
- // Remote will have both a and b. Master will have only b
- try {
- db.resolve(commit2.getId().getName() + "^{commit}");
- fail("id shouldn't exist locally");
- } catch (MissingObjectException e) {
- // we should get here
+ results =
+ git1.push().setRemote("test").setRefSpecs(spec)
+ .setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
+ .call();
+ for (PushResult result : results) {
+ RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
+ assertEquals(update.getStatus(), RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED);
+ }
}
- assertEquals(commit2.getId(),
- db2.resolve(commit2.getId().getName() + "^{commit}"));
- assertEquals(commit3.getId(),
- db2.resolve(commit3.getId().getName() + "^{commit}"));
}
}