]> source.dussan.org Git - jgit.git/commitdiff
PushCommand: determine remote from git config if not given 28/190728/2
authorThomas Wolf <thomas.wolf@paranor.ch>
Thu, 10 Feb 2022 18:04:21 +0000 (19:04 +0100)
committerMatthias Sohn <matthias.sohn@sap.com>
Mon, 14 Feb 2022 09:45:15 +0000 (10:45 +0100)
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>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java

index 3f8921c152c0e4c0d518644881ec91a235156d54..1a1f5b487eba8015547990b26bb2aa885460a361 100644 (file)
@@ -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();
@@ -852,6 +852,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
         *
index 0deb7ed29c31af80b0227396a2a2623c5f5ab0dd..4f57f351272a79beda2d2fa0822e410f9cbec910 100644 (file)
@@ -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);
index 6da6f1204aa814107122af38c79a6b5c11e4e0ef..aa613d07ebd108cbec3c16cfb983eb93d4054953 100644 (file)
@@ -137,6 +137,18 @@ public class BranchConfig {
                                branchName, ConfigConstants.CONFIG_KEY_REMOTE);
        }
 
+       /**
+        * 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
         *
index 205999f8c98b981a6a8175f31f20d0a7e04e3c98..42d8aa5447d8e06a8b8b135e4949c2e3eabd6cc8 100644 (file)
@@ -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";