package org.tmatesoft.svn.test;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.admin.SVNAdminClient;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Sandbox {
public static Sandbox createWithoutCleanup(String testName, TestOptions testOptions) throws SVNException {
return create(testName, testOptions, false);
}
public static Sandbox createWithCleanup(String testName, TestOptions testOptions) throws SVNException {
return create(testName, testOptions, true);
}
private final String testName;
private final TestOptions testOptions;
private final List<WorkingCopy> workingCopies;
private File testDirectory;
private final List<ApacheProcess> apacheProcesses;
private final List<SvnserveProcess> svnserveProcesses;
private final Map<SVNURL, File> urlToRepositoryRoot;
private Sandbox(String testName, TestOptions testOptions) {
this.testName = testName;
this.testOptions = testOptions;
this.workingCopies = new ArrayList<WorkingCopy>();
this.apacheProcesses = new ArrayList<ApacheProcess>();
this.svnserveProcesses = new ArrayList<SvnserveProcess>();
this.urlToRepositoryRoot = new HashMap<SVNURL, File>();
}
public void dispose() {
for (WorkingCopy workingCopy : workingCopies) {
workingCopy.dispose();
}
for (ApacheProcess apacheProcess : apacheProcesses) {
ApacheProcess.shutdown(apacheProcess);
}
for (SvnserveProcess svnserveProcess : svnserveProcesses) {
SvnserveProcess.shutdown(svnserveProcess);
}
}
public WorkingCopy checkoutWorkingCopy() throws SVNException {
return checkoutWorkingCopyOrUpdateTo(SVNRepository.INVALID_REVISION);
}
public WorkingCopy checkoutWorkingCopyOrUpdateTo(long revision) throws SVNException {
if (getWorkingCopyDirectory().exists()) {
final WorkingCopy workingCopy = openExistingWorkingCopy();
workingCopy.updateToRevision(revision);
return workingCopy;
} else {
return checkoutOrUpdateExistingWorkingCopy(getRepositoryUrl(), revision);
}
}
private WorkingCopy openExistingWorkingCopy() {
final WorkingCopy workingCopy = new WorkingCopy(getTestOptions(), getWorkingCopyDirectory());
workingCopy.setRepositoryUrl(getRepositoryUrl());
workingCopies.add(workingCopy);
return workingCopy;
}
public WorkingCopy checkoutOrUpdateExistingWorkingCopy(SVNURL repositoryUrl, long revision) throws SVNException {
return checkoutOrUpdateExistingWorkingCopy(repositoryUrl, revision, SvnWcGeneration.V17);
}
public WorkingCopy checkoutOrUpdateExistingWorkingCopy(SVNURL repositoryUrl, long revision, SvnWcGeneration wcGeneration) throws SVNException {
final WorkingCopy workingCopy = new WorkingCopy(getTestOptions(), getWorkingCopyDirectory());
workingCopy.setWcGeneration(wcGeneration);
workingCopy.checkoutRevision(repositoryUrl, revision);
workingCopies.add(workingCopy);
return workingCopy;
}
public WorkingCopy checkoutNewWorkingCopy(SVNURL url) throws SVNException {
return checkoutNewWorkingCopy(url, SVNRevision.HEAD.getNumber());
}
public WorkingCopy checkoutNewWorkingCopy(SVNURL repositoryUrl, long revision) throws SVNException {
return checkoutNewWorkingCopy(repositoryUrl, revision, true, TestUtil.getDefaultWcGeneration());
}
public WorkingCopy checkoutNewWorkingCopy(SVNURL repositoryUrl, long revision, boolean ignoreExternals, SvnWcGeneration wcGeneration) throws SVNException {
return checkoutNewWorkingCopy(repositoryUrl, revision, ignoreExternals, wcGeneration, createWorkingCopyDirectory());
}
public WorkingCopy checkoutNewWorkingCopy(SVNURL repositoryUrl, long revision, boolean ignoreExternals, SvnWcGeneration wcGeneration, File wcDirectory) throws SVNException {
final WorkingCopy workingCopy = new WorkingCopy(getTestOptions(), wcDirectory);
workingCopy.setWcGeneration(wcGeneration);
workingCopy.checkoutRevision(repositoryUrl, revision, ignoreExternals);
workingCopies.add(workingCopy);
return workingCopy;
}
public SVNURL getFSFSAccessUrl(SVNURL url) {
if ("file".equals(url.getProtocol())) {
return url;
}
final File repositoryRoot = urlToRepositoryRoot.get(url);
try {
return SVNURL.fromFile(repositoryRoot);
} catch (SVNException e) {
return null;
}
}
private SVNURL getRepositoryUrl() {
final SVNURL repositoryUrl = getTestOptions().getRepositoryUrl();
if (repositoryUrl == null) {
throw new RuntimeException("Unable to start the test: repository URL is not specified.");
}
return repositoryUrl;
}
private String getTestName() {
return testName;
}
private File getTestDirectory() {
if (testDirectory == null) {
testDirectory = createTestDirectory();
}
return testDirectory;
}
public SVNURL createSvnRepository() throws SVNException {
final File repositoryDirectory = createDirectory("svn.repo");
createSvnRepository(repositoryDirectory);
SVNURL url = SVNURL.fromFile(repositoryDirectory);
urlToRepositoryRoot.put(url, repositoryDirectory);
return url;
}
public SVNURL createSvnRepositoryWithDavAccess() throws SVNException {
return createSvnRepositoryWithDavAccess(null);
}
public SVNURL createSvnRepositoryWithSvnAccess() throws SVNException {
return createSvnRepositoryWithSvnAccess(null);
}
public SVNURL createSvnRepositoryWithDavAccess(Map<String, String> loginToPassword) throws SVNException {
final File repositoryDirectory = createDirectory("svn.repo");
createSvnRepository(repositoryDirectory);
final ApacheProcess apacheProcess = runApacheForSvnRepository(repositoryDirectory, loginToPassword);
SVNURL url = apacheProcess.getUrl();
urlToRepositoryRoot.put(url, repositoryDirectory);
return url;
}
public SVNURL createSvnRepositoryWithSvnAccess(Map<String, String> loginToPassword) throws SVNException {
final File repositoryDirectory = createDirectory("svn.repo");
createSvnRepository(repositoryDirectory);
final SvnserveProcess svnserveProcess = runSvnserveForSvnRepository(repositoryDirectory, loginToPassword);
SVNURL url = svnserveProcess.getUrl();
urlToRepositoryRoot.put(url, repositoryDirectory);
return url;
}
public File createFailingHook(SVNURL url, String hookName) throws SVNException {
final String failingHookContents = TestUtil.getFailingHookContents();
return createHook(url, hookName, failingHookContents);
}
public File createHook(SVNURL url, String hookName, String failingHookContents) throws SVNException {
final File repositoryRoot = urlToRepositoryRoot.get(url);
final File hookFile = TestUtil.getHookFile(repositoryRoot, hookName);
TestUtil.writeFileContentsString(hookFile, failingHookContents);
SVNFileUtil.setExecutable(hookFile, true);
return hookFile;
}
public File writeActiveAuthzContents(SVNURL url, String contents) throws SVNException {
//maybe url is served by apache?
final ApacheProcess apacheProcess = findApacheProcess(url);
if (apacheProcess != null) {
final File activeAuthzFile = apacheProcess.getAuthzFile();
if (activeAuthzFile == null) {
return null;
}
TestUtil.writeFileContentsString(activeAuthzFile, contents);
apacheProcess.reload(); //reload apache configuration
return activeAuthzFile;
}
//maybe url is served by svnserve?
final SvnserveProcess svnserveProcess = findSvnserveProcess(url);
if (svnserveProcess != null) {
final File activeAuthzFile = svnserveProcess.getAuthzFile();
if (activeAuthzFile == null) {
return null;
}
TestUtil.writeFileContentsString(activeAuthzFile, contents);
svnserveProcess.reload();
return activeAuthzFile;
}
//authz for FSFS is useless
return null;
}
public File writeHookContents(SVNURL url, String hookName, String hookContents) throws SVNException {
final File repositoryRoot = urlToRepositoryRoot.get(url);
final File hookFile = TestUtil.getHookFile(repositoryRoot, hookName);
TestUtil.writeFileContentsString(hookFile, hookContents);
SVNFileUtil.setExecutable(hookFile, true);
return hookFile;
}
private ApacheProcess findApacheProcess(SVNURL url) {
for (ApacheProcess apacheProcess : apacheProcesses) {
if (apacheProcess.getUrl().equals(url)) {
return apacheProcess;
}
}
return null;
}
private SvnserveProcess findSvnserveProcess(SVNURL url) {
for (SvnserveProcess svnserveProcess : svnserveProcesses) {
if (svnserveProcess.getUrl().equals(url)) {
return svnserveProcess;
}
}
return null;
}
private File getWorkingCopyDirectory() {
return new File(getTestDirectory(), "wc");
}
private File createWorkingCopyDirectory() {
return createDirectory("wc");
}
public File createDirectory(String suggestedName) {
return TestUtil.createDirectory(getTestDirectory(), suggestedName).getAbsoluteFile();
}
private File createTestDirectory() {
final File testDirectory = new File(getTempDirectory(), getTestName());
testDirectory.mkdirs();
return testDirectory;
}
private TestOptions getTestOptions() {
return testOptions;
}
private File getTempDirectory() {
return getTestOptions().getTempDirectory();
}
private void cleanup() throws SVNException {
SVNFileUtil.deleteAll(getTestDirectory(), null);
}
private static Sandbox create(String testName, TestOptions testOptions, boolean cleanup) throws SVNException {
final Sandbox sandbox = new Sandbox(testName, testOptions);
if (cleanup) {
sandbox.cleanup();
}
return sandbox;
}
private ApacheProcess runApacheForSvnRepository(File repositoryDirectory, Map<String, String> loginToPassword) throws SVNException {
final ApacheProcess apacheProcess = ApacheProcess.run(getTestOptions(), repositoryDirectory, loginToPassword);
apacheProcesses.add(apacheProcess);
return apacheProcess;
}
private SvnserveProcess runSvnserveForSvnRepository(File repositoryDirectory, Map<String, String> loginToPassword) throws SVNException {
final SvnserveProcess svnserveProcess = SvnserveProcess.run(getTestOptions(), repositoryDirectory, loginToPassword);
svnserveProcesses.add(svnserveProcess);
return svnserveProcess;
}
private void createSvnRepository(File repositoryDirectory) throws SVNException {
final SVNClientManager clientManager = SVNClientManager.newInstance();
try {
SVNAdminClient adminClient = clientManager.getAdminClient();
adminClient.doCreateRepository(repositoryDirectory, null, true, false);
} finally {
clientManager.dispose();
}
}
}