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>
This commit is contained in:
parent
504001228b
commit
855a734875
|
@ -26,6 +26,7 @@
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||||
import org.eclipse.jgit.api.errors.TransportException;
|
import org.eclipse.jgit.api.errors.TransportException;
|
||||||
import org.eclipse.jgit.errors.MissingObjectException;
|
import org.eclipse.jgit.errors.MissingObjectException;
|
||||||
|
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
|
||||||
import org.eclipse.jgit.hooks.PrePushHook;
|
import org.eclipse.jgit.hooks.PrePushHook;
|
||||||
import org.eclipse.jgit.junit.JGitTestUtil;
|
import org.eclipse.jgit.junit.JGitTestUtil;
|
||||||
import org.eclipse.jgit.junit.RepositoryTestCase;
|
import org.eclipse.jgit.junit.RepositoryTestCase;
|
||||||
|
@ -633,8 +634,7 @@ public void testPushDefaultSimpleTriangular() throws Exception {
|
||||||
|
|
||||||
config = git.getRepository().getConfig();
|
config = git.getRepository().getConfig();
|
||||||
// Don't set remote, it'll default to "origin". Configure a
|
// Don't set remote, it'll default to "origin". Configure a
|
||||||
// different
|
// different branch name; should be ignored.
|
||||||
// branch name; should be ignored.
|
|
||||||
config.setString("branch", "branchtopush", "merge",
|
config.setString("branch", "branchtopush", "merge",
|
||||||
"refs/heads/upstreambranch");
|
"refs/heads/upstreambranch");
|
||||||
config.save();
|
config.save();
|
||||||
|
@ -852,6 +852,176 @@ public void testPushDefaultFromConfigDefault() throws Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Check that missing refs don't cause errors during push
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
import org.eclipse.jgit.internal.JGitText;
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.BranchConfig;
|
import org.eclipse.jgit.lib.BranchConfig;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.ConfigConstants;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||||
|
@ -58,7 +59,7 @@
|
||||||
public class PushCommand extends
|
public class PushCommand extends
|
||||||
TransportCommand<PushCommand, Iterable<PushResult>> {
|
TransportCommand<PushCommand, Iterable<PushResult>> {
|
||||||
|
|
||||||
private String remote = Constants.DEFAULT_REMOTE_NAME;
|
private String remote;
|
||||||
|
|
||||||
private final List<RefSpec> refSpecs;
|
private final List<RefSpec> refSpecs;
|
||||||
|
|
||||||
|
@ -114,6 +115,7 @@ public Iterable<PushResult> call() throws GitAPIException,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Config config = repo.getConfig();
|
Config config = repo.getConfig();
|
||||||
|
remote = determineRemote(config, remote);
|
||||||
if (refSpecs.isEmpty()) {
|
if (refSpecs.isEmpty()) {
|
||||||
RemoteConfig rc = new RemoteConfig(config,
|
RemoteConfig rc = new RemoteConfig(config,
|
||||||
getRemote());
|
getRemote());
|
||||||
|
@ -181,6 +183,34 @@ public Iterable<PushResult> call() throws GitAPIException,
|
||||||
return pushResults;
|
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()
|
private String getCurrentBranch()
|
||||||
throws IOException, DetachedHeadException {
|
throws IOException, DetachedHeadException {
|
||||||
Ref head = repo.exactRef(Constants.HEAD);
|
Ref head = repo.exactRef(Constants.HEAD);
|
||||||
|
|
|
@ -137,6 +137,18 @@ public String getRemote() {
|
||||||
branchName, ConfigConstants.CONFIG_KEY_REMOTE);
|
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
|
* Get the name of the upstream branch as it is called on the remote
|
||||||
*
|
*
|
||||||
|
|
|
@ -329,6 +329,20 @@ public final class ConfigConstants {
|
||||||
/** The "remote" key */
|
/** The "remote" key */
|
||||||
public static final String CONFIG_KEY_REMOTE = "remote";
|
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 */
|
/** The "merge" key */
|
||||||
public static final String CONFIG_KEY_MERGE = "merge";
|
public static final String CONFIG_KEY_MERGE = "merge";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue