2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.jetbrains
.idea
.svn
.branchConfig
;
18 import com
.intellij
.openapi
.diagnostic
.Logger
;
19 import com
.intellij
.openapi
.project
.Project
;
20 import com
.intellij
.openapi
.vfs
.VirtualFile
;
21 import org
.jetbrains
.annotations
.Nullable
;
22 import org
.jetbrains
.idea
.svn
.SvnUtil
;
23 import org
.jetbrains
.idea
.svn
.SvnVcs
;
24 import org
.jetbrains
.idea
.svn
.integrate
.SvnBranchItem
;
25 import org
.tmatesoft
.svn
.core
.SVNException
;
26 import org
.tmatesoft
.svn
.core
.SVNURL
;
27 import org
.tmatesoft
.svn
.core
.internal
.util
.SVNURLUtil
;
28 import org
.tmatesoft
.svn
.core
.wc
.SVNInfo
;
29 import org
.tmatesoft
.svn
.core
.wc
.SVNRevision
;
30 import org
.tmatesoft
.svn
.core
.wc
.SVNWCClient
;
35 public class SvnBranchConfigurationNew
{
36 private static final Logger LOG
= Logger
.getInstance("#org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew");
37 private String myTrunkUrl
;
38 // need public for serialization
39 public Map
<String
, InfoStorage
<List
<SvnBranchItem
>>> myBranchMap
;
40 private boolean myUserinfoInUrl
;
42 public SvnBranchConfigurationNew() {
44 myBranchMap
= new HashMap
<String
, InfoStorage
<List
<SvnBranchItem
>>>();
47 public boolean isUserinfoInUrl() {
48 return myUserinfoInUrl
;
51 public void setUserinfoInUrl(final boolean userinfoInUrl
) {
52 myUserinfoInUrl
= userinfoInUrl
;
55 public void setTrunkUrl(final String trunkUrl
) {
56 myTrunkUrl
= trunkUrl
;
59 public String
getTrunkUrl() {
63 public List
<String
> getBranchUrls() {
64 final ArrayList
<String
> result
= new ArrayList
<String
>(myBranchMap
.keySet());
65 Collections
.sort(result
);
69 public void addBranches(final String branchParentName
, final InfoStorage
<List
<SvnBranchItem
>> items
) {
70 InfoStorage
<List
<SvnBranchItem
>> current
= myBranchMap
.get(branchParentName
);
71 if (current
!= null) {
72 LOG
.info("Branches list not added for : '" + branchParentName
+ "; this branch parent URL is already present.");
75 myBranchMap
.put(branchParentName
, items
);
78 public void updateBranch(final String branchParentName
, final InfoStorage
<List
<SvnBranchItem
>> items
) {
79 final InfoStorage
<List
<SvnBranchItem
>> current
= myBranchMap
.get(branchParentName
);
80 if (current
== null) {
81 LOG
.info("Branches list not updated for : '" + branchParentName
+ "; since config has changed.");
84 current
.accept(items
, null);
87 public Map
<String
, InfoStorage
<List
<SvnBranchItem
>>> getBranchMap() {
91 public List
<SvnBranchItem
> getBranches(String url
) {
92 return myBranchMap
.get(url
).getValue();
95 /*public SvnBranchConfiguration createFromVcsRootBranches() {
96 final SvnBranchConfiguration result = new SvnBranchConfiguration();
97 result.setTrunkUrl(myTrunkUrl);
98 final Map<String, List<SvnBranchItem>> branchMap = result.getBranchMap();
99 for (String key : myBranchMap.keySet()) {
100 result.setTrunkUrl(key);
101 final List<SvnBranchItem> list = myBranchMap.get(key).getT();
102 branchMap.put(key, list);
107 public SvnBranchConfigurationNew
copy() {
108 SvnBranchConfigurationNew result
= new SvnBranchConfigurationNew();
109 result
.myUserinfoInUrl
= myUserinfoInUrl
;
110 result
.myTrunkUrl
= myTrunkUrl
;
111 result
.myBranchMap
= new HashMap
<String
, InfoStorage
<List
<SvnBranchItem
>>>();
112 for (Map
.Entry
<String
, InfoStorage
<List
<SvnBranchItem
>>> entry
: myBranchMap
.entrySet()) {
113 final InfoStorage
<List
<SvnBranchItem
>> infoStorage
= entry
.getValue();
114 result
.myBranchMap
.put(entry
.getKey(), new InfoStorage
<List
<SvnBranchItem
>>(
115 new ArrayList
<SvnBranchItem
>(infoStorage
.getValue()), infoStorage
.getInfoReliability()));
121 public String
getBaseUrl(String url
) {
122 if ((myTrunkUrl
!= null) && url
.startsWith(myTrunkUrl
)) {
125 for(String branchUrl
: myBranchMap
.keySet()) {
126 if (url
.startsWith(branchUrl
)) {
127 int pos
= url
.indexOf('/', branchUrl
.length()+1);
129 return url
.substring(0, pos
);
138 public String
getBaseName(String url
) {
139 String baseUrl
= getBaseUrl(url
);
140 if (baseUrl
== null) {
143 if (myBranchMap
.isEmpty()) {
146 int commonPrefixLength
= getCommonPrefixLength(url
, myTrunkUrl
);
147 for (String branchUrl
: myBranchMap
.keySet()) {
148 commonPrefixLength
= Math
.min(commonPrefixLength
, getCommonPrefixLength(url
, branchUrl
));
149 if (commonPrefixLength
<= 0) {
153 return baseUrl
.substring(commonPrefixLength
);
156 private static int getCommonPrefixLength(final String s1
, final String s2
) {
157 final int minLength
= Math
.min(s1
.length(), s2
.length());
158 for(int i
=0; i
< minLength
; i
++) {
159 if (s1
.charAt(i
) != s2
.charAt(i
)) {
167 public String
getRelativeUrl(String url
) {
168 String baseUrl
= getBaseUrl(url
);
169 return baseUrl
== null ?
null : url
.substring(baseUrl
.length());
173 public SVNURL
getWorkingBranch(final SVNURL someUrl
) throws SVNException
{
174 final BranchSearcher branchSearcher
= new BranchSearcher(someUrl
);
175 iterateUrls(branchSearcher
);
177 return branchSearcher
.getResult();
180 private void iterateUrls(final UrlListener listener
) throws SVNException
{
181 if (listener
.accept(myTrunkUrl
)) {
185 for (String branchUrl
: myBranchMap
.keySet()) {
186 // use more exact comparison first (paths longer)
187 final List
<SvnBranchItem
> children
= myBranchMap
.get(branchUrl
).getValue();
188 for (SvnBranchItem child
: children
) {
189 if (listener
.accept(child
.getUrl())) {
194 if (listener
.accept(branchUrl
)) {
201 public Map
<String
,String
> getUrl2FileMappings(final Project project
, final VirtualFile root
) {
203 final BranchRootSearcher searcher
= new BranchRootSearcher(SvnVcs
.getInstance(project
), root
);
204 iterateUrls(searcher
);
205 return searcher
.getBranchesUnder();
206 } catch (SVNException e
) {
211 public void removeBranch(final String url
) {
212 myBranchMap
.remove(url
);
215 private static class BranchRootSearcher
implements UrlListener
{
216 private final VirtualFile myRoot
;
217 private final SVNURL myRootUrl
;
218 // url path to file path
219 private final Map
<String
, String
> myBranchesUnder
;
221 private BranchRootSearcher(final SvnVcs vcs
, final VirtualFile root
) throws SVNException
{
223 myBranchesUnder
= new HashMap
<String
, String
>();
224 final SVNWCClient client
= vcs
.createWCClient();
225 final SVNInfo info
= client
.doInfo(new File(myRoot
.getPath()), SVNRevision
.WORKING
);
226 myRootUrl
= info
.getURL();
229 public boolean accept(final String url
) throws SVNException
{
230 if (myRootUrl
!= null) {
231 final File baseDir
= new File(myRoot
.getPath());
232 final String baseUrl
= myRootUrl
.getPath();
234 final SVNURL branchUrl
= SVNURL
.parseURIEncoded(url
);
235 if (myRootUrl
.equals(SVNURLUtil
.getCommonURLAncestor(myRootUrl
, branchUrl
))) {
236 final File file
= SvnUtil
.fileFromUrl(baseDir
, baseUrl
, branchUrl
.getPath());
237 myBranchesUnder
.put(url
, file
.getAbsolutePath());
240 return false; // iterate everything
243 public Map
<String
, String
> getBranchesUnder() {
244 return myBranchesUnder
;
248 private interface UrlListener
{
249 boolean accept(final String url
) throws SVNException
;
252 private static class BranchSearcher
implements UrlListener
{
253 private final SVNURL mySomeUrl
;
254 private SVNURL myResult
;
256 private BranchSearcher(final SVNURL someUrl
) {
260 public boolean accept(final String url
) throws SVNException
{
261 myResult
= urlIsParent(url
, mySomeUrl
);
262 return myResult
!= null;
265 public SVNURL
getResult() {
271 private static SVNURL
urlIsParent(final String parentCandidate
, final SVNURL child
) throws SVNException
{
272 final SVNURL parentUrl
= SVNURL
.parseURIEncoded(parentCandidate
);
273 if(parentUrl
.equals(SVNURLUtil
.getCommonURLAncestor(parentUrl
, child
))) {