blob: df204a34f5a2f96e384e6bc97139abb659889084 [file] [log] [blame]
/*
* Copyright 2000-2011 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package git4idea.status;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.VcsDirtyScope;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.*;
/**
* Common
* Serves as a container of common utility functions to collect dirty paths for both {@link GitNewChangesCollector} and
* {@link GitOldChangesCollector}.
*
* @author Kirill Likhodedov
*/
abstract class GitChangesCollector {
@NotNull protected final Project myProject;
@NotNull protected final VirtualFile myVcsRoot;
@NotNull private final VcsDirtyScope myDirtyScope;
@NotNull private final ChangeListManager myChangeListManager;
@NotNull private final ProjectLevelVcsManager myVcsManager;
@NotNull private AbstractVcs myVcs;
GitChangesCollector(@NotNull Project project, @NotNull ChangeListManager changeListManager, @NotNull ProjectLevelVcsManager vcsManager,
@NotNull AbstractVcs vcs, @NotNull VcsDirtyScope dirtyScope, @NotNull VirtualFile vcsRoot) {
myProject = project;
myChangeListManager = changeListManager;
myVcsManager = vcsManager;
myVcs = vcs;
myDirtyScope = dirtyScope;
myVcsRoot = vcsRoot;
}
/**
* @return the set of unversioned files (from the specified dirty scope).
*/
abstract @NotNull Collection<VirtualFile> getUnversionedFiles();
/**
* @return the set of changes (changed files) from the specified dirty scope.
*/
abstract @NotNull Collection<Change> getChanges();
/**
* Collect dirty file paths
*
* @param includeChanges if true, previous changes are included in collection
* @return the set of dirty paths to check, the paths are automatically collapsed if the summary length more than limit
*/
protected Collection<FilePath> dirtyPaths(boolean includeChanges) {
final List<String> allPaths = new ArrayList<String>();
for (FilePath p : myDirtyScope.getRecursivelyDirtyDirectories()) {
addToPaths(p, allPaths);
}
for (FilePath p : myDirtyScope.getDirtyFilesNoExpand()) {
addToPaths(p, allPaths);
}
if (includeChanges) {
for (Change c : myChangeListManager.getChangesIn(myVcsRoot)) {
switch (c.getType()) {
case NEW:
case DELETED:
case MOVED:
ContentRevision afterRevision = c.getAfterRevision();
if (afterRevision != null) {
addToPaths(afterRevision.getFile(), allPaths);
}
ContentRevision beforeRevision = c.getBeforeRevision();
if (beforeRevision != null) {
addToPaths(beforeRevision.getFile(), allPaths);
}
case MODIFICATION:
default:
// do nothing
}
}
}
removeCommonParents(allPaths);
final List<FilePath> paths = new ArrayList<FilePath>(allPaths.size());
for (String p : allPaths) {
final File file = new File(p);
paths.add(new FilePathImpl(file, file.isDirectory()));
}
return paths;
}
protected void addToPaths(FilePath pathToAdd, List<String> paths) {
VcsRoot fileRoot = myVcsManager.getVcsRootObjectFor(pathToAdd);
if (fileRoot != null && fileRoot.getVcs() != null && myVcs.equals(fileRoot.getVcs()) && myVcsRoot.equals(fileRoot.getPath())) {
paths.add(pathToAdd.getPath());
}
}
protected static void removeCommonParents(List<String> allPaths) {
Collections.sort(allPaths);
String prevPath = null;
Iterator<String> it = allPaths.iterator();
while (it.hasNext()) {
String path = it.next();
if (prevPath != null && FileUtil.startsWith(path, prevPath)) { // the file is under previous file, so enough to check the parent
it.remove();
}
else {
prevPath = path;
}
}
}
}