diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java index a41a1727f48f..6e178b9cbc0f 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java +++ b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java @@ -228,7 +228,11 @@ public class GitBranchUtil { String branchName = stdName.substring(slash + 1); GitRemote remote = findRemoteByName(remoteName, remotes); if (remote == null) { - return null; + // user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes + LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes)); + GitRemote fakeRemote = new GitRemote(remoteName, ContainerUtil.emptyList(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); + return new GitStandardRemoteBranch(fakeRemote, branchName, hash); } return new GitStandardRemoteBranch(remote, branchName, hash); } @@ -241,8 +245,6 @@ public class GitBranchUtil { return remote; } } - // user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes - LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes)); return null; } diff --git a/plugins/git4idea/src/git4idea/repo/GitRemote.java b/plugins/git4idea/src/git4idea/repo/GitRemote.java index a0695d281bd7..b2e289ce7d40 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRemote.java +++ b/plugins/git4idea/src/git4idea/repo/GitRemote.java @@ -39,7 +39,7 @@ import java.util.List; *

*

* GitRemote instance constructed by {@link GitConfig#read(GitPlatformFacade, File)}} has all these rules applied. - * Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote, + * Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote, * both {@link #getUrls()} and {@link #getPushUrls()} will return this url.
* This is made to avoid urls transformation logic from the code using GitRemote, leaving it all in GitConfig parsing. *

@@ -47,14 +47,14 @@ import java.util.List; * Same applies to fetch and push specs: {@link #getPushRefSpecs()} returns the spec, * even if there are no separate record in {@code .git/config} *

- * + * *

* NB: Not all remote preferences (defined in {@code .git/config} are stored in the object. * If some additional data is needed, add the field, getter, constructor parameter and populate it in {@link GitConfig}. *

- * + * *

Remotes are compared (via equals, hashcode and compareTo) only by names.

- * + * * @author Kirill Likhodedov */ public final class GitRemote implements Comparable { @@ -80,8 +80,8 @@ public final class GitRemote implements Comparable { @NotNull final List myFetchRefSpecs; @NotNull private final List myPushRefSpecs; - GitRemote(@NotNull String name, @NotNull List urls, @NotNull Collection pushUrls, - @NotNull List fetchRefSpecs, @NotNull List pushRefSpecs) { + public GitRemote(@NotNull String name, @NotNull List urls, @NotNull Collection pushUrls, + @NotNull List fetchRefSpecs, @NotNull List pushRefSpecs) { myName = name; myUrls = urls; myPushUrls = pushUrls; diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java index 89f382806658..9570cbdc06fe 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderNewTest.java @@ -16,10 +16,14 @@ package git4idea.repo; import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.util.Condition; +import com.intellij.util.containers.ContainerUtil; import git4idea.GitLocalBranch; +import git4idea.GitRemoteBranch; import git4idea.test.GitSingleRepoTest; import java.io.File; +import java.util.Collection; import static git4idea.test.GitExecutor.git; import static git4idea.test.GitScenarios.commit; @@ -46,4 +50,24 @@ public class GitRepositoryReaderNewTest extends GitSingleRepoTest { assertEquals("State value is incorrect", Repository.State.REBASING, state); } + // inspired by IDEA-124052 + public void test_remote_reference_without_remote() { + final String INVALID_REMOTE = "invalid-remote"; + final String INVALID_REMOTE_BRANCH = "master"; + git("update-ref refs/remotes/" + INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH + " HEAD"); + + File gitDir = new File(myRepo.getRoot().getPath(), ".git"); + GitRepositoryReader reader = new GitRepositoryReader(gitDir); + GitConfig config = GitConfig.read(myPlatformFacade, new File(gitDir, "config")); + Collection remotes = config.parseRemotes(); + + Collection remoteBranches = reader.readBranches(remotes).getRemoteBranches(); + assertTrue("Remote branch not found", ContainerUtil.exists(remoteBranches, new Condition() { + @Override + public boolean value(GitRemoteBranch branch) { + return branch.getNameForLocalOperations().equals(INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH); + } + })); + } + }