From 384c4d2e5d5cf346c45316e154c97bb6263ea0f6 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 20 Apr 2012 13:04:17 +0400 Subject: [PATCH] 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. --- plugins/git4idea/src/git4idea/GitBranch.java | 3 + .../git4idea/src/git4idea/repo/GitConfig.java | 32 +++++---- .../git4idea/src/git4idea/repo/GitRemote.java | 12 +++- .../config/branch/b5_git-svn/b5_config.txt | 69 +++++++++++++++++++ .../config/branch/b5_git-svn/b5_desc.txt | 3 + .../config/branch/b5_git-svn/b5_result.txt | 12 ++++ .../config/remote/r11_git-svn/r11_config.txt | 69 +++++++++++++++++++ .../config/remote/r11_git-svn/r11_desc.txt | 3 + .../config/remote/r11_git-svn/r11_result.txt | 66 ++++++++++++++++++ .../tests/git4idea/repo/GitConfigTest.java | 9 ++- 10 files changed, 259 insertions(+), 19 deletions(-) create mode 100644 plugins/git4idea/testData/config/branch/b5_git-svn/b5_config.txt create mode 100644 plugins/git4idea/testData/config/branch/b5_git-svn/b5_desc.txt create mode 100644 plugins/git4idea/testData/config/branch/b5_git-svn/b5_result.txt create mode 100644 plugins/git4idea/testData/config/remote/r11_git-svn/r11_config.txt create mode 100644 plugins/git4idea/testData/config/remote/r11_git-svn/r11_desc.txt create mode 100644 plugins/git4idea/testData/config/remote/r11_git-svn/r11_result.txt diff --git a/plugins/git4idea/src/git4idea/GitBranch.java b/plugins/git4idea/src/git4idea/GitBranch.java index 90b63fbb28dd..a6d01112aa55 100644 --- a/plugins/git4idea/src/git4idea/GitBranch.java +++ b/plugins/git4idea/src/git4idea/GitBranch.java @@ -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; diff --git a/plugins/git4idea/src/git4idea/repo/GitConfig.java b/plugins/git4idea/src/git4idea/repo/GitConfig.java index 61b7e6d7aa80..8fce5a9631b6 100644 --- a/plugins/git4idea/src/git4idea/repo/GitConfig.java +++ b/plugins/git4idea/src/git4idea/repo/GitConfig.java @@ -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 myRemotes; private final Collection 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(); } diff --git a/plugins/git4idea/src/git4idea/repo/GitRemote.java b/plugins/git4idea/src/git4idea/repo/GitRemote.java index ee0909fbe830..4cdcfd86f324 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRemote.java +++ b/plugins/git4idea/src/git4idea/repo/GitRemote.java @@ -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 { + /** + * 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.emptyList(), + Collections.emptyList(), Collections.emptyList()); + private final String myName; private final List myUrls; private final Collection myPushUrls; diff --git a/plugins/git4idea/testData/config/branch/b5_git-svn/b5_config.txt b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_config.txt new file mode 100644 index 000000000000..bffce42ba974 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_config.txt @@ -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 \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b5_git-svn/b5_desc.txt b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_desc.txt new file mode 100644 index 000000000000..575e0b33a7c6 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_desc.txt @@ -0,0 +1,3 @@ +b5 Example of git-svn config +Inspired by IDEA-83764 +Several svn-remotes defined for different svn branches. \ No newline at end of file diff --git a/plugins/git4idea/testData/config/branch/b5_git-svn/b5_result.txt b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_result.txt new file mode 100644 index 000000000000..bbf4537bd714 --- /dev/null +++ b/plugins/git4idea/testData/config/branch/b5_git-svn/b5_result.txt @@ -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 \ No newline at end of file diff --git a/plugins/git4idea/testData/config/remote/r11_git-svn/r11_config.txt b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_config.txt new file mode 100644 index 000000000000..bffce42ba974 --- /dev/null +++ b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_config.txt @@ -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 \ No newline at end of file diff --git a/plugins/git4idea/testData/config/remote/r11_git-svn/r11_desc.txt b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_desc.txt new file mode 100644 index 000000000000..c572650b426d --- /dev/null +++ b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_desc.txt @@ -0,0 +1,3 @@ +r11 Example of git-svn config +Inspired by IDEA-83764 +Several svn-remotes defined for different svn branches. \ No newline at end of file diff --git a/plugins/git4idea/testData/config/remote/r11_git-svn/r11_result.txt b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_result.txt new file mode 100644 index 000000000000..b31746c5060a --- /dev/null +++ b/plugins/git4idea/testData/config/remote/r11_git-svn/r11_result.txt @@ -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/* diff --git a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java index 6c1a8b33b8aa..637610d13917 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java @@ -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 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 getSingletonOrEmpty(String[] array, int i) { + return array.length < i + 1 ? Collections.emptyList() : Collections.singletonList(array[i]); } }