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
;
18 import com
.intellij
.openapi
.util
.Getter
;
19 import com
.intellij
.openapi
.vcs
.impl
.VcsRootIterator
;
20 import com
.intellij
.openapi
.vfs
.VfsUtil
;
21 import com
.intellij
.openapi
.vfs
.VirtualFile
;
22 import com
.intellij
.openapi
.progress
.ProcessCanceledException
;
23 import org
.jetbrains
.annotations
.Nullable
;
24 import org
.tmatesoft
.svn
.core
.internal
.util
.SVNEncodingUtil
;
25 import org
.tmatesoft
.svn
.core
.internal
.util
.SVNPathUtil
;
26 import org
.tmatesoft
.svn
.core
.wc
.SVNInfo
;
27 import org
.tmatesoft
.svn
.core
.wc
.SVNWCClient
;
31 public class ForNestedRootChecker
{
32 static class DirInfo
{
33 private final VirtualFile myFile
;
34 private final String myUrl
;
36 DirInfo(final VirtualFile file
, final String url
) {
41 public VirtualFile
getFile() {
45 public String
getUrl() {
50 private static class UrlConstructor
{
52 final SVNWCClient myClient
;
54 private UrlConstructor(final SvnVcs vcs
) {
56 myClient
= myVcs
.createWCClient();
60 public Real
createReal(final VirtualFile file
, final VirtualFile vcsRoot
) {
61 final SVNInfo info
= myVcs
.getInfo(file
);
62 if (info
== null || info
.getRepositoryRootURL() == null || info
.getURL() == null) {
65 return new Real(file
, info
, vcsRoot
);
68 public Node
createReplaceable(final VirtualFile file
) {
69 return new Node(file
, null);
72 public Node
createSupposed(final Real parent
, final VirtualFile child
) {
73 return new Node(child
, getForChild(parent
.getUrl(), child
.getName()));
76 public boolean replaceWithReal(final Real real
, final Node supposed
) {
77 return supposed
.getUrl() == null || ((supposed
.getUrl() != null) && (! supposed
.getUrl().equals(real
.getUrl())));
81 private String
getSupposedUrl(final String parentUrl
, final List
<String
> subpath
) {
82 if (parentUrl
== null) return null;
83 final StringBuilder sb
= new StringBuilder();
84 for (String s
: subpath
) {
85 sb
.append(s
).append('/');
87 if (sb
.length() > 0) {
88 sb
.deleteCharAt(sb
.length() - 1);
90 return SVNPathUtil
.append(parentUrl
, sb
.toString());
93 public String
getForChild(final String parentUrl
, final String childName
) {
94 return parentUrl
== null ?
null : SVNPathUtil
.append(parentUrl
, SVNEncodingUtil
.uriEncode(childName
));
98 public static<T
extends RootUrlPair
> void filterOutSuperfluousChildren(final SvnVcs vcs
, final List
<T
> list
,
99 final List
<T
> result
) {
100 final UrlConstructor constructor
= new UrlConstructor(vcs
);
102 Collections
.sort(list
, new Comparator
<RootUrlPair
>() {
103 public int compare(final RootUrlPair o1
, final RootUrlPair o2
) {
104 return o1
.getVirtualFile().getPath().compareTo(o2
.getVirtualFile().getPath());
108 for (int i
= 0; i
< list
.size(); i
++) {
109 final T child
= list
.get(i
);
111 for (T parent
: result
) {
112 if (parent
.getVirtualFile().getPath().equals(child
.getVirtualFile().getPath())) {
116 final List
<String
> subpath
= subpathIfAncestor(parent
.getVirtualFile(), child
.getVirtualFile());
117 if (subpath
!= null) {
118 // get child's supposed and real urls
119 final String supposed
= constructor
.getSupposedUrl(parent
.getUrl(), subpath
);
120 if (supposed
.equals(child
.getUrl())) {
133 private static List
<String
> subpathIfAncestor(final VirtualFile parent
, final VirtualFile child
) {
134 if (! VfsUtil
.isAncestor(parent
, child
, true)) return null;
136 final List
<String
> result
= new ArrayList
<String
>();
137 VirtualFile tmp
= child
;
138 final String parentPath
= parent
.getPath();
139 while ((tmp
!= null) && (! tmp
.getPath().equals(parentPath
))) {
140 result
.add(tmp
.getName());
141 tmp
= tmp
.getParent();
143 Collections
.reverse(result
);
147 /*public static List<Real> getAllNestedWorkingCopies(final VirtualFile[] roots, final SvnVcs vcs, final boolean goIntoNested) {
149 FilterDescendantVirtualFiles.filter(Arrays.asList(roots));
152 final VcsRootIterator rootIterator = new VcsRootIterator(vcs.getProject(), vcs);
153 final List<Real> result = new ArrayList<Real>();
154 for (VirtualFile root : roots) {
155 result.addAll(getForOne(root, vcs, goIntoNested, rootIterator));
158 if (! goIntoNested) {
159 final List<Real> filtered = new ArrayList<Real>(result.size());
160 filterOutSuperfluousChildren(vcs, result, filtered);
167 public static List
<Real
> getAllNestedWorkingCopies(final VirtualFile root
, final SvnVcs vcs
, final boolean goIntoNested
, final Getter
<Boolean
> cancelledGetter
) {
168 final VcsRootIterator rootIterator
= new VcsRootIterator(vcs
.getProject(), vcs
);
169 return getForOne(root
, vcs
, goIntoNested
, rootIterator
, cancelledGetter
);
172 private static List
<Real
> getForOne(final VirtualFile root
, final SvnVcs vcs
, final boolean goIntoNested
,
173 final VcsRootIterator rootIterator
, final Getter
<Boolean
> cancelledGetter
) {
174 final UrlConstructor constructor
= new UrlConstructor(vcs
);
175 final LinkedList
<Node
> queue
= new LinkedList
<Node
>();
176 final LinkedList
<Real
> result
= new LinkedList
<Real
>();
178 queue
.add(constructor
.createReplaceable(root
));
179 while (! queue
.isEmpty()) {
180 final Node node
= queue
.removeFirst();
183 final Real real
= constructor
.createReal(node
.getFile(), root
);
185 if (constructor
.replaceWithReal(real
, node
)) {
187 if (! goIntoNested
) continue;
192 final VirtualFile file
= node
.getFile();
193 if (file
.isDirectory() && (! SvnUtil
.isAdminDirectory(file
))) {
194 for (VirtualFile child
: file
.getChildren()) {
195 if (Boolean
.TRUE
.equals(cancelledGetter
.get())) throw new ProcessCanceledException();
196 if (rootIterator
.acceptFolderUnderVcs(root
, child
)) {
198 queue
.add(constructor
.createReplaceable(child
));
200 queue
.add(constructor
.createSupposed(real
, child
));