blob: 3d06a956477644b4c31f777c5aab6f2caf39b152 [file] [log] [blame]
/*
* Copyright 2000-2009 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 com.intellij.openapi.vcs.changes.committed;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.NotNullFunction;
import com.intellij.util.PairProcessor;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class CachesHolder {
@NonNls private static final String VCS_CACHE_PATH = "vcsCache";
private final Project myProject;
private final Map<String, ChangesCacheFile> myCacheFiles;
private final RepositoryLocationCache myLocationCache;
private final ProjectLevelVcsManager myPlManager;
public CachesHolder(final Project project, final RepositoryLocationCache locationCache) {
myProject = project;
myLocationCache = locationCache;
myPlManager = ProjectLevelVcsManager.getInstance(myProject);
myCacheFiles = new ConcurrentHashMap<String, ChangesCacheFile>();
}
public CachesHolder(final Project project, final RepositoryLocationCache locationCache, final ProjectLevelVcsManager manager) {
myProject = project;
myPlManager = manager;
myLocationCache = locationCache;
myCacheFiles = new ConcurrentHashMap<String, ChangesCacheFile>();
}
/**
* Returns all paths that will be used to collect committed changes about. ideally, for one checkout there should be one file
*/
public Map<VirtualFile, RepositoryLocation> getAllRootsUnderVcs(final AbstractVcs vcs) {
final RootsCalculator calculator = new RootsCalculator(myProject, vcs, myLocationCache);
return calculator.getRoots();
}
public void iterateAllRepositoryLocations(final PairProcessor<RepositoryLocation, AbstractVcs> locationProcessor) {
final AbstractVcs[] vcses = myPlManager.getAllActiveVcss();
for (AbstractVcs vcs : vcses) {
final CommittedChangesProvider provider = vcs.getCommittedChangesProvider();
if (provider instanceof CachingCommittedChangesProvider) {
final Map<VirtualFile, RepositoryLocation> map = getAllRootsUnderVcs(vcs);
for (VirtualFile root : map.keySet()) {
final RepositoryLocation location = map.get(root);
if (! Boolean.TRUE.equals(locationProcessor.process(location, vcs))) {
return;
}
}
}
}
}
public void iterateAllCaches(final NotNullFunction<ChangesCacheFile, Boolean> consumer) {
final AbstractVcs[] vcses = myPlManager.getAllActiveVcss();
for (AbstractVcs vcs : vcses) {
final CommittedChangesProvider provider = vcs.getCommittedChangesProvider();
if (provider instanceof CachingCommittedChangesProvider) {
final Map<VirtualFile, RepositoryLocation> map = getAllRootsUnderVcs(vcs);
for (VirtualFile root : map.keySet()) {
final RepositoryLocation location = map.get(root);
final ChangesCacheFile cacheFile = getCacheFile(vcs, root, location);
if (Boolean.TRUE.equals(consumer.fun(cacheFile))) {
return;
}
}
}
}
}
public void clearAllCaches() {
for (Map.Entry<String, ChangesCacheFile> entry : myCacheFiles.entrySet()) {
entry.getValue().delete();
}
myCacheFiles.clear();
}
public List<ChangesCacheFile> getAllCaches() {
final List<ChangesCacheFile> result = new ArrayList<ChangesCacheFile>();
iterateAllCaches(new NotNullFunction<ChangesCacheFile, Boolean>() {
@NotNull
public Boolean fun(final ChangesCacheFile changesCacheFile) {
result.add(changesCacheFile);
return false;
}
});
return result;
}
public ChangesCacheFile getCacheFile(AbstractVcs vcs, VirtualFile root, RepositoryLocation location) {
final String key = location.getKey();
ChangesCacheFile cacheFile = myCacheFiles.get(key);
if (cacheFile == null) {
cacheFile = new ChangesCacheFile(myProject, getCachePath(location), vcs, root, location);
myCacheFiles.put(key, cacheFile);
}
return cacheFile;
}
public File getCacheBasePath() {
File file = new File(PathManager.getSystemPath(), VCS_CACHE_PATH);
file = new File(file, myProject.getLocationHash());
return file;
}
@SuppressWarnings({"HardCodedStringLiteral"})
private File getCachePath(final RepositoryLocation location) {
File file = getCacheBasePath();
file.mkdirs();
String s = location.getKey();
try {
final byte[] bytes = MessageDigest.getInstance("MD5").digest(CharsetToolkit.getUtf8Bytes(s));
StringBuilder result = new StringBuilder();
for (byte aByte : bytes) {
result.append(String.format("%02x", aByte));
}
return new File(file, result.toString());
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public ChangesCacheFile haveCache(RepositoryLocation location) {
String key = location.getKey();
if (myCacheFiles.containsKey(key)) return myCacheFiles.get(key);
key = key.endsWith("/") ? key : (key + "/");
for (String s : myCacheFiles.keySet()) {
if (key.startsWith(s) || s.startsWith(key)) return myCacheFiles.get(s);
}
return null;
}
}