summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf <thomas.wolf@paranor.ch>2022-02-10 19:04:21 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2022-02-14 10:45:15 +0100
commit855a734875c2f178a8adfd0789527afc8754117f (patch)
treeb488222bb7573e9c06862b7bf1b2832ae92c8eeb
parent504001228ba6a43179a72e56ce03aa217c2bdea4 (diff)
downloadjgit-855a734875c2f178a8adfd0789527afc8754117f.tar.gz
jgit-855a734875c2f178a8adfd0789527afc8754117f.zip
PushCommand: determine remote from git config if not given
Add ConfigConstants and expose branch.<name>.pushRemote in the BranchConfig. Use the branch configuration and remote.pushDefault if no remote is given explicitly. If nothing is configured, fall back to "origin". Bug: 578676 Change-Id: I6bb141ff02c8b04980ec34b26ef248b72614c3c9 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java174
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java32
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java14
4 files changed, 229 insertions, 3 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 3f8921c152..1a1f5b487e 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
@@ -26,6 +26,7 @@ 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;
@@ -633,8 +634,7 @@ public class PushCommandTest extends RepositoryTestCase {
config = git.getRepository().getConfig();
// Don't set remote, it'll default to "origin". Configure a
- // different
- // branch name; should be ignored.
+ // different branch name; should be ignored.
config.setString("branch", "branchtopush", "merge",
"refs/heads/upstreambranch");
config.save();
@@ -853,6 +853,176 @@ public class PushCommandTest extends RepositoryTestCase {
}
/**
+ * Check that branch.<name>.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.<name>.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"));
+ }
+ }
+
+ /**
* Check that missing refs don't cause errors during push
*
* @throws Exception
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
index 0deb7ed29c..4f57f35127 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
@@ -33,6 +33,7 @@ import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.BranchConfig;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ProgressMonitor;
@@ -58,7 +59,7 @@ import org.eclipse.jgit.transport.Transport;
public class PushCommand extends
TransportCommand<PushCommand, Iterable<PushResult>> {
- private String remote = Constants.DEFAULT_REMOTE_NAME;
+ private String remote;
private final List<RefSpec> refSpecs;
@@ -114,6 +115,7 @@ public class PushCommand extends
try {
Config config = repo.getConfig();
+ remote = determineRemote(config, remote);
if (refSpecs.isEmpty()) {
RemoteConfig rc = new RemoteConfig(config,
getRemote());
@@ -181,6 +183,34 @@ public class PushCommand extends
return pushResults;
}
+ private String determineRemote(Config config, String remoteName)
+ throws IOException {
+ if (remoteName != null) {
+ return remoteName;
+ }
+ Ref head = repo.exactRef(Constants.HEAD);
+ String effectiveRemote = null;
+ BranchConfig branchCfg = null;
+ if (head != null && head.isSymbolic()) {
+ String currentBranch = head.getLeaf().getName();
+ branchCfg = new BranchConfig(config,
+ Repository.shortenRefName(currentBranch));
+ effectiveRemote = branchCfg.getPushRemote();
+ }
+ if (effectiveRemote == null) {
+ effectiveRemote = config.getString(
+ ConfigConstants.CONFIG_REMOTE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_PUSH_DEFAULT);
+ if (effectiveRemote == null && branchCfg != null) {
+ effectiveRemote = branchCfg.getRemote();
+ }
+ }
+ if (effectiveRemote == null) {
+ effectiveRemote = Constants.DEFAULT_REMOTE_NAME;
+ }
+ return effectiveRemote;
+ }
+
private String getCurrentBranch()
throws IOException, DetachedHeadException {
Ref head = repo.exactRef(Constants.HEAD);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
index 6da6f1204a..aa613d07eb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
@@ -138,6 +138,18 @@ public class BranchConfig {
}
/**
+ * Get the remote this branch is configured to push to.
+ *
+ * @return the remote this branch is configured to push to, or {@code null}
+ * if not defined
+ * @since 6.1
+ */
+ public String getPushRemote() {
+ return config.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
+ branchName, ConfigConstants.CONFIG_KEY_PUSH_REMOTE);
+ }
+
+ /**
* Get the name of the upstream branch as it is called on the remote
*
* @return the name of the upstream branch as it is called on the remote, or
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index 205999f8c9..42d8aa5447 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -329,6 +329,20 @@ public final class ConfigConstants {
/** The "remote" key */
public static final String CONFIG_KEY_REMOTE = "remote";
+ /**
+ * The "pushRemote" key.
+ *
+ * @since 6.1
+ */
+ public static final String CONFIG_KEY_PUSH_REMOTE = "pushRemote";
+
+ /**
+ * The "pushDefault" key.
+ *
+ * @since 6.1
+ */
+ public static final String CONFIG_KEY_PUSH_DEFAULT = "pushDefault";
+
/** The "merge" key */
public static final String CONFIG_KEY_MERGE = "merge";