blob: e90127124105f0326e1e7998203d3e65bfa3a299 [file] [log] [blame]
/*
* Copyright 2000-2013 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.roots;
import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.EmptyModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.impl.ModuleRootManagerImpl;
import com.intellij.openapi.roots.impl.RootModelImpl;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vcs.VcsRootChecker;
import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs;
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import static com.intellij.openapi.vcs.Executor.cd;
import static com.intellij.openapi.vcs.Executor.mkdir;
public abstract class VcsRootPlatformTest extends UsefulTestCase {
public static final String DOT_MOCK = ".mock";
private VcsRootChecker myExtension;
@NotNull protected ProjectLevelVcsManagerImpl myVcsManager;
@NotNull protected MockAbstractVcs myVcs;
@NotNull protected String myVcsName;
protected Project myProject;
protected VirtualFile myProjectRoot;
protected VirtualFile myRepository;
public static final String myRepositoryFolderName = "repository";
private RootModelImpl myRootModel;
protected static final Collection<File> myFilesToDelete = new HashSet<File>();
protected IdeaProjectTestFixture myProjectFixture;
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
protected VcsRootPlatformTest() {
PlatformTestCase.initPlatformLangPrefix();
}
@Override
protected void setUp() throws Exception {
super.setUp();
myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture();
myProjectFixture.setUp();
myProject = myProjectFixture.getProject();
myProjectRoot = myProject.getBaseDir();
cd(myProjectRoot);
Module module = doCreateRealModuleIn("foo", myProject, EmptyModuleType
.getInstance());
myRootModel = ((ModuleRootManagerImpl)ModuleRootManager.getInstance(module)).getRootModel();
mkdir(myRepositoryFolderName);
myRepository = myProjectRoot.findChild(myRepositoryFolderName);
myVcs = new MockAbstractVcs(myProject);
myVcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject);
ExtensionPoint<VcsRootChecker> point = getExtensionPoint();
myExtension = new VcsRootChecker() {
@Override
public VcsKey getSupportedVcs() {
return myVcs.getKeyInstanceMethod();
}
@Override
public boolean isRoot(@NotNull String path) {
return new File(path, DOT_MOCK).exists();
}
@Override
public boolean isVcsDir(@Nullable String path) {
return path != null && path.toLowerCase().endsWith(DOT_MOCK);
}
};
point.registerExtension(myExtension);
myVcsManager.registerVcs(myVcs);
myVcsName = myVcs.getName();
}
private static ExtensionPoint<VcsRootChecker> getExtensionPoint() {
return Extensions.getRootArea().getExtensionPoint(VcsRootChecker.EXTENSION_POINT_NAME);
}
@Override
protected void tearDown() throws Exception {
getExtensionPoint().unregisterExtension(myExtension);
myVcsManager.unregisterVcs(myVcs);
for (File file : myFilesToDelete) {
delete(file);
}
myProjectFixture.tearDown();
super.tearDown();
}
private static void delete(File file) {
boolean b = FileUtil.delete(file);
if (!b && file.exists()) {
fail("Can't delete " + file.getAbsolutePath());
}
}
/**
* Creates the necessary temporary directories in the filesystem with empty ".mock" directories for given roots.
* And creates an instance of the project.
*
* @param mockRoots path to actual .mock roots, relative to the project dir.
*/
public void initProject(@NotNull VcsRootConfiguration vcsRootConfiguration)
throws IOException {
createDirs(vcsRootConfiguration.getMockRoots());
Collection<String> contentRoots = vcsRootConfiguration.getContentRoots();
createProjectStructure(myProject, contentRoots);
if (!contentRoots.isEmpty()) {
for (String root : contentRoots) {
VirtualFile f = myProjectRoot.findFileByRelativePath(root);
if (f != null) {
myRootModel.addContentEntry(f);
}
}
}
}
static void createProjectStructure(@NotNull Project project, @NotNull Collection<String> paths) {
for (String path : paths) {
cd(project.getBaseDir().getPath());
File f = new File(project.getBaseDir().getPath(), path);
f.mkdirs();
}
}
@NotNull
public static Module doCreateRealModuleIn(@NotNull String moduleName,
@NotNull final Project project,
@NotNull final ModuleType moduleType) {
final VirtualFile baseDir = project.getBaseDir();
assertNotNull(baseDir);
final File moduleFile = new File(baseDir.getPath().replace('/', File.separatorChar),
moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION);
FileUtil.createIfDoesntExist(moduleFile);
myFilesToDelete.add(moduleFile);
return new WriteAction<Module>() {
@Override
protected void run(Result<Module> result) throws Throwable {
final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleFile);
assert virtualFile != null;
Module module = ModuleManager.getInstance(project).newModule(virtualFile.getPath(), moduleType.getId());
module.getModuleFile();
result.setResult(module);
}
}.execute().getResultObject();
}
/**
* @return path to the project
*/
private void createDirs(@NotNull Collection<String> mockRoots) throws IOException {
File baseDir;
if (mockRoots.isEmpty()) {
return;
}
baseDir = VfsUtilCore.virtualToIoFile(myProject.getBaseDir());
int maxDepth = findMaxDepthAboveProject(mockRoots);
File projectDir = createChild(baseDir, maxDepth - 1);
cd(projectDir.getPath());
for (String path : mockRoots) {
File file = new File(projectDir, path);
file.mkdirs();
File mockDir = new File(file, DOT_MOCK);
mockDir.mkdirs();
myFilesToDelete.add(mockDir);
mockDir.deleteOnExit();
}
}
@NotNull
private static File createChild(@NotNull File base, int depth) throws IOException {
File dir = base;
if (depth < 0) {
return dir;
}
for (int i = 0; i < depth; ++i) {
dir = FileUtil.createTempDirectory(dir, "grdt", null);
}
return dir;
}
// Assuming that there are no ".." inside the path - only in the beginning
static int findMaxDepthAboveProject(@NotNull Collection<String> paths) {
int max = 0;
for (String path : paths) {
String[] splits = path.split("/");
int count = 0;
for (String split : splits) {
if (split.equals("..")) {
count++;
}
}
if (count > max) {
max = count;
}
}
return max;
}
}