From 6605255d9906c5277d215396ebcc395484b9f10c Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Sat, 26 Apr 2014 10:55:42 +0200 Subject: Add methods to Repository to handle remote names Instead of requiring the caller to know how to list remote names or parse remote branch names, add a few utilities for that. Change-Id: Ib6b2403532f4abbce594a03c0b9da49d30b19f70 Signed-off-by: Robin Rosenberg --- .../tst/org/eclipse/jgit/lib/RefTest.java | 46 ++++++++++++++++++++++ .../src/org/eclipse/jgit/lib/Repository.java | 43 ++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java index 26c4d12cc0..f2ed684511 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java @@ -58,9 +58,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; +import java.util.TreeSet; import org.eclipse.jgit.lib.Ref.Storage; import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; import org.junit.Test; @@ -82,6 +84,50 @@ public class RefTest extends SampleDataRepositoryTestCase { } } + @Test + public void testRemoteNames() throws Exception { + FileBasedConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION, + "origin", "dummy", true); + config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION, + "ab/c", "dummy", true); + config.save(); + assertEquals("[ab/c, origin]", + new TreeSet(db.getRemoteNames()).toString()); + + // one-level deep remote branch + assertEquals("master", + db.shortenRemoteBranchName("refs/remotes/origin/master")); + assertEquals("origin", db.getRemoteName("refs/remotes/origin/master")); + + // two-level deep remote branch + assertEquals("masta/r", + db.shortenRemoteBranchName("refs/remotes/origin/masta/r")); + assertEquals("origin", db.getRemoteName("refs/remotes/origin/masta/r")); + + // Remote with slash and one-level deep branch name + assertEquals("xmaster", + db.shortenRemoteBranchName("refs/remotes/ab/c/xmaster")); + assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmaster")); + + // Remote with slash and two-level deep branch name + assertEquals("xmasta/r", + db.shortenRemoteBranchName("refs/remotes/ab/c/xmasta/r")); + assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmasta/r")); + + // no such remote + assertNull(db.getRemoteName("refs/remotes/nosuchremote/x")); + assertNull(db.shortenRemoteBranchName("refs/remotes/nosuchremote/x")); + + // no such remote too, no branch name either + assertNull(db.getRemoteName("refs/remotes/abranch")); + assertNull(db.shortenRemoteBranchName("refs/remotes/abranch")); + + // // local branch + assertNull(db.getRemoteName("refs/heads/abranch")); + assertNull(db.shortenRemoteBranchName("refs/heads/abranch")); + } + @Test public void testReadAllIncludingSymrefs() throws Exception { ObjectId masterId = db.resolve("refs/heads/master"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index c350dddb25..1538d277b1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -1274,6 +1274,40 @@ public abstract class Repository { return refName; } + /** + * @param refName + * @return the remote branch name part of refName, i.e. without + * the refs/remotes/<remote> prefix, if + * refName represents a remote tracking branch; + * otherwise null. + * @since 3.4 + */ + public String shortenRemoteBranchName(String refName) { + for (String remote : getRemoteNames()) { + String remotePrefix = Constants.R_REMOTES + remote + "/"; //$NON-NLS-1$ + if (refName.startsWith(remotePrefix)) + return refName.substring(remotePrefix.length()); + } + return null; + } + + /** + * @param refName + * @return the remote name part of refName, i.e. without the + * refs/remotes/<remote> prefix, if + * refName represents a remote tracking branch; + * otherwise null. + * @since 3.4 + */ + public String getRemoteName(String refName) { + for (String remote : getRemoteNames()) { + String remotePrefix = Constants.R_REMOTES + remote + "/"; //$NON-NLS-1$ + if (refName.startsWith(remotePrefix)) + return remote; + } + return null; + } + /** * @param refName * @return a {@link ReflogReader} for the supplied refname, or null if the @@ -1613,4 +1647,13 @@ public abstract class Repository { throws IOException { new RebaseTodoFile(this).writeRebaseTodoFile(path, steps, append); } + + /** + * @return the names of all known remotes + * @since 3.4 + */ + public Set getRemoteNames() { + return getConfig() + .getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION); + } } -- cgit v1.2.3 From 36f58ef867fc180aaca20dfa58a1b14f6b79e59a Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Sat, 26 Apr 2014 13:05:53 +0200 Subject: Fix ArrayIndexOutOfBoundsException in CreateBranchCommand If remote name contains / or there was a branch directly under the refs/remotes namespace (wrong) the computation of remote name and suggested local branch name would fail. Fix this by looking at the configured remotes. A ref under refs/remotes that does not match a remote configuration is not considered a remote tracking branch anymore. This patch does not fix all similar errors in EGit/JGit. Bug: 411002 Bug: 400414 Change-Id: I2515a6ed05f9104c387ce4e43b24dae942ae2473 --- .../src/org/eclipse/jgit/api/CreateBranchCommand.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java index aa1484c0f9..92e8b466b0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java @@ -246,12 +246,11 @@ public class CreateBranchCommand extends GitCommand { if (doConfigure) { StoredConfig config = repo.getConfig(); - String[] tokens = baseBranch.split("/", 4); //$NON-NLS-1$ - boolean isRemote = tokens[1].equals("remotes"); //$NON-NLS-1$ - if (isRemote) { - // refs/remotes// - String remoteName = tokens[2]; - String branchName = tokens[3]; + + String remoteName = repo.getRemoteName(baseBranch); + if (remoteName != null) { + String branchName = repo + .shortenRemoteBranchName(baseBranch); config .setString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE, -- cgit v1.2.3