IDEA-83764 Support git-svn in GitConfig

Use special GitRemote instance for "remote = . " typical for git-svn branch in .git/config.
Filter out the "refs/remotes/" prefix (as it is done for refs/heads) when creating GitBranch in GitBranch#tracked
Add a test with test data from the bugreport.
This commit is contained in:
Kirill Likhodedov
2012-04-20 13:18:10 +04:00
parent d8c4ce1f5c
commit 384c4d2e5d
10 changed files with 259 additions and 19 deletions
@@ -365,6 +365,9 @@ public class GitBranch extends GitReference {
if (branch.startsWith(REFS_HEADS_PREFIX)) {
branch = branch.substring(REFS_HEADS_PREFIX.length());
}
else if (branch.startsWith(REFS_REMOTES_PREFIX)) {
branch = branch.substring(REFS_REMOTES_PREFIX.length());
}
boolean remoteFlag;
if (!".".equals(remote)) {
branch = remote + "/" + branch;
@@ -51,11 +51,13 @@ public class GitConfig {
private static final Logger LOG = Logger.getInstance(GitConfig.class);
private static final Pattern REMOTE_SECTION = Pattern.compile("remote \"(.*)\"");
private static final Pattern REMOTE_SECTION = Pattern.compile("(?:svn-)?remote \"(.*)\"");
private static final Pattern URL_SECTION = Pattern.compile("url \"(.*)\"");
private static final Pattern BRANCH_INFO_SECTION = Pattern.compile("branch \"(.*)\"");
private static final Pattern BRANCH_COMMON_PARAMS_SECTION = Pattern.compile("branch");
private static final String DOT_REMOTE = "."; // used in git-svn "remote = . "
private final Collection<GitRemote> myRemotes;
private final Collection<GitBranchTrackInfo> myBranchTrackInfos;
@@ -161,17 +163,21 @@ public class GitConfig {
final String remoteBranch = (merge ? mergeName : rebaseName);
GitRemote branchRemote = null;
for (GitRemote remote : remotes) {
if (remote.getName().equals(remoteName)) {
branchRemote = remote;
break;
if (DOT_REMOTE.equals(remoteName)) {
branchRemote = GitRemote.DOT;
}
else {
for (GitRemote remote : remotes) {
if (remote.getName().equals(remoteName)) {
branchRemote = remote;
break;
}
}
if (branchRemote == null) {
LOG.info("No remote found with name " + remoteName);
return null;
}
}
if (branchRemote == null) {
LOG.info("No remote found with name " + remoteName);
return null;
}
assert remoteBranch != null; // this is checked in StringUtil.isEmptyOrSpaces
return new GitBranchTrackInfo(branchName, branchRemote, remoteBranch, merge);
}
@@ -198,7 +204,7 @@ public class GitConfig {
String sectionName = stringSectionEntry.getKey();
Profile.Section section = stringSectionEntry.getValue();
if (sectionName.startsWith("remote")) {
if (sectionName.startsWith("remote") || sectionName.startsWith("svn-remote")) {
Remote remote = parseRemoteSection(sectionName, section, classLoader);
if (remote != null) {
remotes.add(remote);
@@ -401,8 +407,8 @@ public class GitConfig {
}
private interface RemoteBean {
@Nullable String[] getFetch();
@Nullable String[] getPush();
@Nullable String[] getFetch();
@Nullable String[] getPush();
@Nullable String[] getUrl();
@Nullable String[] getPushUrl();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -59,6 +60,15 @@ import java.util.List;
*/
public final class GitRemote implements Comparable<GitRemote> {
/**
* This is a special instance of GitRemote used in typical git-svn configurations like:
* [branch "trunk"]
* remote = .
* merge = refs/remotes/git-svn
*/
public static final GitRemote DOT = new GitRemote(".", Collections.singletonList("."), Collections.<String>emptyList(),
Collections.<String>emptyList(), Collections.<String>emptyList());
private final String myName;
private final List<String> myUrls;
private final Collection<String> myPushUrls;
@@ -0,0 +1,69 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
packedGitWindowSize = 16m
packedGitLimit = 128m
[svn-remote "svn"]
url = svn+ssh://user@cvs.host/SVN/project/trunk/sourcecode
fetch = :refs/remotes/git-svn
[svn-remote "170"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_branch
fetch = :refs/remotes/170
[svn-remote "1702"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1702_branch
fetch = :refs/remotes/1702
[svn-remote "1701"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1701_branch
fetch = :refs/remotes/1701
[svn-remote "166"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_166_branch
fetch = :refs/remotes/166
[svn-remote "165"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_165_branch
fetch = :refs/remotes/165
[svn-remote "168"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_168_branch
fetch = :refs/remotes/168
[svn-remote "169"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_169_branch
fetch = :refs/remotes/169
[svn-remote "170_GA"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_GA_branch
fetch = :refs/remotes/170_GA
[svn-remote "UPDM_2"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UPDM_20_branch
fetch = :refs/remotes/UPDM_2
[gui]
wmstate = normal
geometry = 907x745+1421+65 510 188
matchtrackingbranch = true
[remote "h10"]
url = /opt/repo
fetch = +refs/heads/*:refs/remotes/h10/*
[pack]
threads = 2
deltaCacheSize = 1
windowMemory = 512m
[branch "trunk"]
remote = .
merge = refs/remotes/git-svn
[merge]
renameLimit = 999999
[branch "trunk2"]
remote = .
merge = refs/remotes/git-svn
[branch]
autosetupmerge = true
@@ -0,0 +1,3 @@
b5 Example of git-svn config
Inspired by IDEA-83764
Several svn-remotes defined for different svn branches.
@@ -0,0 +1,12 @@
BRANCH
trunk
. .
refs/remotes/git-svn
refs/remotes/git-svn
merge
BRANCH
trunk2
. .
refs/remotes/git-svn
refs/remotes/git-svn
merge
@@ -0,0 +1,69 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
packedGitWindowSize = 16m
packedGitLimit = 128m
[svn-remote "svn"]
url = svn+ssh://user@cvs.host/SVN/project/trunk/sourcecode
fetch = :refs/remotes/git-svn
[svn-remote "170"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_branch
fetch = :refs/remotes/170
[svn-remote "1702"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1702_branch
fetch = :refs/remotes/1702
[svn-remote "1701"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1701_branch
fetch = :refs/remotes/1701
[svn-remote "166"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_166_branch
fetch = :refs/remotes/166
[svn-remote "165"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_165_branch
fetch = :refs/remotes/165
[svn-remote "168"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_168_branch
fetch = :refs/remotes/168
[svn-remote "169"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_169_branch
fetch = :refs/remotes/169
[svn-remote "170_GA"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_GA_branch
fetch = :refs/remotes/170_GA
[svn-remote "UPDM_2"]
url = svn+ssh://user@cvs.host/SVN/project/branches/MD_UPDM_20_branch
fetch = :refs/remotes/UPDM_2
[gui]
wmstate = normal
geometry = 907x745+1421+65 510 188
matchtrackingbranch = true
[remote "h10"]
url = /opt/repo
fetch = +refs/heads/*:refs/remotes/h10/*
[pack]
threads = 2
deltaCacheSize = 1
windowMemory = 512m
[branch "trunk"]
remote = .
merge = refs/remotes/git-svn
[merge]
renameLimit = 999999
[branch "trunk2"]
remote = .
merge = refs/remotes/git-svn
[branch]
autosetupmerge = true
@@ -0,0 +1,3 @@
r11 Example of git-svn config
Inspired by IDEA-83764
Several svn-remotes defined for different svn branches.
@@ -0,0 +1,66 @@
REMOTE
svn
svn+ssh://user@cvs.host/SVN/project/trunk/sourcecode
svn+ssh://user@cvs.host/SVN/project/trunk/sourcecode
:refs/remotes/git-svn
:refs/remotes/git-svn
REMOTE
170
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_branch
:refs/remotes/170
:refs/remotes/170
REMOTE
1702
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1702_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1702_branch
:refs/remotes/1702
:refs/remotes/1702
REMOTE
1701
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1701_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_1701_branch
:refs/remotes/1701
:refs/remotes/1701
REMOTE
166
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_166_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_166_branch
:refs/remotes/166
:refs/remotes/166
REMOTE
165
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_165_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_165_branch
:refs/remotes/165
:refs/remotes/165
REMOTE
168
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_168_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_168_branch
:refs/remotes/168
:refs/remotes/168
REMOTE
169
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_169_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_169_branch
:refs/remotes/169
:refs/remotes/169
REMOTE
170_GA
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_GA_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UML_170_GA_branch
:refs/remotes/170_GA
:refs/remotes/170_GA
REMOTE
UPDM_2
svn+ssh://user@cvs.host/SVN/project/branches/MD_UPDM_20_branch
svn+ssh://user@cvs.host/SVN/project/branches/MD_UPDM_20_branch
:refs/remotes/UPDM_2
:refs/remotes/UPDM_2
REMOTE
h10
/opt/repo
/opt/repo
+refs/heads/*:refs/remotes/h10/*
+refs/heads/*:refs/remotes/h10/*
@@ -79,9 +79,8 @@ public class GitConfigTest {
private static GitRemote getRemote(String remoteString) {
String[] remoteInfo = remoteString.split(" ");
return new GitRemote(getOrEmpty(remoteInfo, 0), Collections.singletonList(getOrEmpty(remoteInfo, 1)),
Collections.singletonList(getOrEmpty(remoteInfo, 2)), Collections.singletonList(getOrEmpty(remoteInfo, 3)),
Collections.singletonList(getOrEmpty(remoteInfo, 4)));
return new GitRemote(remoteInfo[0], getSingletonOrEmpty(remoteInfo, 1), getSingletonOrEmpty(remoteInfo, 2),
getSingletonOrEmpty(remoteInfo, 3), getSingletonOrEmpty(remoteInfo, 4));
}
private static Set<GitRemote> readRemoteResults(File resultFile) throws IOException {
@@ -111,8 +110,8 @@ public class GitConfigTest {
return Arrays.asList(line.split(" "));
}
private static String getOrEmpty(String[] array, int i) {
return array.length < i + 1 ? "" : array[i];
private static List<String> getSingletonOrEmpty(String[] array, int i) {
return array.length < i + 1 ? Collections.<String>emptyList() : Collections.singletonList(array[i]);
}
}