2 * Copyright 2000-2007 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.
17 package com
.intellij
.openapi
.vcs
.changes
;
19 import com
.intellij
.openapi
.application
.ApplicationManager
;
20 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
21 import com
.intellij
.openapi
.project
.Project
;
22 import com
.intellij
.openapi
.util
.Computable
;
23 import com
.intellij
.openapi
.util
.io
.FileUtil
;
24 import com
.intellij
.openapi
.vcs
.AbstractVcs
;
25 import com
.intellij
.openapi
.vcs
.FilePath
;
26 import com
.intellij
.openapi
.vcs
.ProjectLevelVcsManager
;
27 import com
.intellij
.openapi
.vcs
.actions
.VcsContextFactory
;
28 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.pom
.Navigatable
;
31 import org
.jetbrains
.annotations
.NotNull
;
32 import org
.jetbrains
.annotations
.Nullable
;
40 public class ChangesUtil
{
41 private ChangesUtil() {}
44 public static FilePath
getFilePath(@NotNull final Change change
) {
45 ContentRevision revision
= change
.getAfterRevision();
46 if (revision
== null) {
47 revision
= change
.getBeforeRevision();
48 assert revision
!= null;
51 return revision
.getFile();
55 public static FilePath
getBeforePath(@NotNull final Change change
) {
56 ContentRevision revision
= change
.getBeforeRevision();
57 return revision
== null ?
null : revision
.getFile();
61 public static FilePath
getAfterPath(@NotNull final Change change
) {
62 ContentRevision revision
= change
.getAfterRevision();
63 return revision
== null ?
null : revision
.getFile();
66 public static AbstractVcs
getVcsForChange(Change change
, final Project project
) {
67 return ProjectLevelVcsManager
.getInstance(project
).getVcsFor(getFilePath(change
));
70 public static AbstractVcs
getVcsForFile(VirtualFile file
, Project project
) {
71 return ProjectLevelVcsManager
.getInstance(project
).getVcsFor(file
);
74 public static AbstractVcs
getVcsForFile(File file
, Project project
) {
75 return ProjectLevelVcsManager
.getInstance(project
).getVcsFor(VcsContextFactory
.SERVICE
.getInstance().createFilePathOn(file
));
78 public static Collection
<FilePath
> getPaths(final List
<Change
> changes
) {
79 Set
<FilePath
> paths
= new HashSet
<FilePath
>();
80 for (Change change
: changes
) {
81 ContentRevision beforeRevision
= change
.getBeforeRevision();
82 if (beforeRevision
!= null) {
83 paths
.add(beforeRevision
.getFile());
85 ContentRevision afterRevision
= change
.getAfterRevision();
86 if (afterRevision
!= null) {
87 paths
.add(afterRevision
.getFile());
93 public static VirtualFile
[] getFilesFromChanges(final Collection
<Change
> changes
) {
94 ArrayList
<VirtualFile
> files
= new ArrayList
<VirtualFile
>();
95 for (Change change
: changes
) {
96 final ContentRevision afterRevision
= change
.getAfterRevision();
97 if (afterRevision
!= null) {
98 final VirtualFile file
= afterRevision
.getFile().getVirtualFile();
99 if (file
!= null && file
.isValid()) {
104 return files
.toArray(new VirtualFile
[files
.size()]);
107 public static Navigatable
[] getNavigatableArray(final Project project
, final VirtualFile
[] selectedFiles
) {
108 List
<Navigatable
> result
= new ArrayList
<Navigatable
>();
109 for (VirtualFile selectedFile
: selectedFiles
) {
110 if (!selectedFile
.isDirectory()) {
111 result
.add(new OpenFileDescriptor(project
, selectedFile
));
114 return result
.toArray(new Navigatable
[result
.size()]);
118 public static ChangeList
getChangeListIfOnlyOne(@NotNull final Project project
, @Nullable Change
[] changes
) {
119 if (changes
== null || changes
.length
== 0) {
123 ChangeList selectedList
= null;
124 for (Change change
: changes
) {
125 final ChangeList list
= ChangeListManager
.getInstance(project
).getChangeList(change
);
126 if (selectedList
== null) {
129 else if (selectedList
!= list
) {
136 public static FilePath
getCommittedPath(final Project project
, FilePath filePath
) {
137 // check if the file has just been renamed (IDEADEV-15494)
138 Change change
= ChangeListManager
.getInstance(project
).getChange(filePath
);
139 if (change
!= null) {
140 final ContentRevision beforeRevision
= change
.getBeforeRevision();
141 final ContentRevision afterRevision
= change
.getAfterRevision();
142 if (beforeRevision
!= null && afterRevision
!= null && !beforeRevision
.getFile().equals(afterRevision
.getFile()) &&
143 afterRevision
.getFile().equals(filePath
)) {
144 filePath
= beforeRevision
.getFile();
150 public static FilePath
getLocalPath(final Project project
, final FilePath filePath
) {
151 // check if the file has just been renamed (IDEADEV-15494)
152 Change change
= ApplicationManager
.getApplication().runReadAction(new Computable
<Change
>() {
154 public Change
compute() {
155 if (project
.isDisposed()) return null;
156 return ChangeListManager
.getInstance(project
).getChange(filePath
);
159 if (change
!= null) {
160 final ContentRevision beforeRevision
= change
.getBeforeRevision();
161 final ContentRevision afterRevision
= change
.getAfterRevision();
162 if (beforeRevision
!= null && afterRevision
!= null && !beforeRevision
.getFile().equals(afterRevision
.getFile()) &&
163 beforeRevision
.getFile().equals(filePath
)) {
164 return afterRevision
.getFile();
171 public static VirtualFile
findValidParent(FilePath file
) {
172 ApplicationManager
.getApplication().assertReadAccessAllowed();
173 VirtualFile parent
= file
.getVirtualFile();
174 if (parent
== null) {
175 parent
= file
.getVirtualFileParent();
177 if (parent
== null) {
178 File ioFile
= file
.getIOFile();
180 parent
= LocalFileSystem
.getInstance().findFileByIoFile(ioFile
);
181 if (parent
!= null) break;
182 ioFile
= ioFile
.getParentFile();
183 if (ioFile
== null) return null;
191 public static String
getProjectRelativePath(final Project project
, @Nullable final File fileName
) {
192 if (fileName
== null) return null;
193 VirtualFile baseDir
= project
.getBaseDir();
194 if (baseDir
== null) return fileName
.toString();
195 String relativePath
= FileUtil
.getRelativePath(new File(baseDir
.getPath()), fileName
);
196 if (relativePath
!= null) return relativePath
;
197 return fileName
.toString();
200 public static boolean isBinaryContentRevision(final ContentRevision revision
) {
201 return revision
!= null && !revision
.getFile().isDirectory() && revision
instanceof BinaryContentRevision
;
204 public static boolean isBinaryChange(final Change change
) {
205 return isBinaryContentRevision(change
.getBeforeRevision()) || isBinaryContentRevision(change
.getAfterRevision());
208 public interface PerVcsProcessor
<T
> {
209 void process(AbstractVcs vcs
, List
<T
> items
);
212 public interface VcsSeparator
<T
> {
213 AbstractVcs
getVcsFor(T item
);
216 public static <T
> void processItemsByVcs(final Collection
<T
> items
, final VcsSeparator
<T
> separator
, PerVcsProcessor
<T
> processor
) {
217 final Map
<AbstractVcs
, List
<T
>> changesByVcs
= new HashMap
<AbstractVcs
, List
<T
>>();
219 ApplicationManager
.getApplication().runReadAction(new Runnable() {
221 for (T item
: items
) {
222 final AbstractVcs vcs
= separator
.getVcsFor(item
);
224 List
<T
> vcsChanges
= changesByVcs
.get(vcs
);
225 if (vcsChanges
== null) {
226 vcsChanges
= new ArrayList
<T
>();
227 changesByVcs
.put(vcs
, vcsChanges
);
229 vcsChanges
.add(item
);
235 for (Map
.Entry
<AbstractVcs
, List
<T
>> entry
: changesByVcs
.entrySet()) {
236 processor
.process(entry
.getKey(), entry
.getValue());
240 public static void processChangesByVcs(final Project project
, Collection
<Change
> changes
, PerVcsProcessor
<Change
> processor
) {
241 processItemsByVcs(changes
, new VcsSeparator
<Change
>() {
242 public AbstractVcs
getVcsFor(final Change item
) {
243 return getVcsForChange(item
, project
);
248 public static void processVirtualFilesByVcs(final Project project
, Collection
<VirtualFile
> files
, PerVcsProcessor
<VirtualFile
> processor
) {
249 processItemsByVcs(files
, new VcsSeparator
<VirtualFile
>() {
250 public AbstractVcs
getVcsFor(final VirtualFile item
) {
251 return getVcsForFile(item
, project
);
256 public static void processFilePathsByVcs(final Project project
, Collection
<FilePath
> files
, PerVcsProcessor
<FilePath
> processor
) {
257 processItemsByVcs(files
, new VcsSeparator
<FilePath
>() {
258 public AbstractVcs
getVcsFor(final FilePath item
) {
259 return getVcsForFile(item
.getIOFile(), project
);
264 public static List
<File
> filePathsToFiles(Collection
<FilePath
> filePaths
) {
265 List
<File
> ioFiles
= new ArrayList
<File
>();
266 for(FilePath filePath
: filePaths
) {
267 ioFiles
.add(filePath
.getIOFile());
272 public static boolean hasFileChanges(final Collection
<Change
> changes
) {
273 for(Change change
: changes
) {
274 FilePath path
= ChangesUtil
.getFilePath(change
);
275 if (!path
.isDirectory()) {