org.jetbrains.idea.SvnTestCase.java Source code

Java tutorial

Introduction

Here is the source code for org.jetbrains.idea.SvnTestCase.java

Source

/*
 * 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 org.jetbrains.idea;

import com.intellij.execution.process.ProcessOutput;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TestDialog;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
import com.intellij.openapi.vcs.update.CommonUpdateProjectAction;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import com.intellij.testFramework.vcs.AbstractJunitVcsTestCase;
import com.intellij.testFramework.vcs.MockChangeListManagerGate;
import com.intellij.testFramework.vcs.MockChangelistBuilder;
import com.intellij.testFramework.vcs.TestClientRunner;
import com.intellij.util.Processor;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnApplicationSettings;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnFileUrlMappingImpl;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.actions.CreateExternalAction;
import org.junit.After;
import org.junit.Before;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static org.junit.Assert.*;

/**
 * @author yole
 */
public abstract class SvnTestCase extends AbstractJunitVcsTestCase {

    public static String ourGlobalTestDataDir;
    public static Boolean ourGlobalUseNativeAcceleration;

    protected TempDirTestFixture myTempDirFixture;
    protected String myRepoUrl;
    protected TestClientRunner myRunner;
    protected String myWcRootName;
    // TODO: Change this to explicitly run either with native acceleration or not.
    // properties set through run configurations or different runners (like Suite) could be used
    private boolean myUseNativeAcceleration = new GregorianCalendar().get(Calendar.HOUR_OF_DAY) % 2 == 0;

    private String myTestDataDir;
    private File myRepoRoot;
    private File myWcRoot;
    private ChangeListManagerGate myGate;
    protected String myAnotherRepoUrl;
    protected File myPluginRoot;

    protected SvnTestCase(@NotNull String testDataDir) {
        PlatformTestCase.initPlatformLangPrefix();
        myTestDataDir = testDataDir;
        myWcRootName = "wcroot";
    }

    public static void imitateEvent(VirtualFile dir) {
        final VirtualFile child = dir.findChild(".svn");
        assertNotNull(child);
        final VirtualFile wcdb = child.findChild("wc.db");
        assertNotNull(wcdb);

        final BulkFileListener listener = ApplicationManager.getApplication().getMessageBus()
                .syncPublisher(VirtualFileManager.VFS_CHANGES);
        final VFileContentChangeEvent event = new VFileContentChangeEvent(null, wcdb,
                wcdb.getModificationStamp() - 1, wcdb.getModificationStamp(), true);
        final List<VFileContentChangeEvent> events = Collections.singletonList(event);
        listener.before(events);
        listener.after(events);
    }

    @Override
    protected String getPluginName() {
        return "Subversion";
    }

    @Before
    public void setUp() throws Exception {
        System.out.println("Native client for status: " + isUseNativeAcceleration());

        String property = System.getProperty("svn.test.data.directory");
        if (!StringUtil.isEmpty(property)) {
            myTestDataDir = property;
        }

        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
            @Override
            public void run() {
                try {
                    final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
                    myTempDirFixture = fixtureFactory.createTempDirTestFixture();
                    myTempDirFixture.setUp();

                    myRepoRoot = new File(myTempDirFixture.getTempDirPath(), "svnroot");
                    assert myRepoRoot.mkdir() || myRepoRoot.isDirectory() : myRepoRoot;

                    myPluginRoot = new File(PluginPathManager.getPluginHomePath("svn4idea"));
                    if (!myPluginRoot.isDirectory()) {
                        // try standalone mode
                        Class aClass = SvnTestCase.class;
                        String rootPath = PathManager.getResourceRoot(aClass,
                                "/" + aClass.getName().replace('.', '/') + ".class");
                        myPluginRoot = new File(rootPath).getParentFile().getParentFile().getParentFile();
                    }

                    File svnBinDir = new File(myPluginRoot, getTestDataDir() + "/svn/bin");
                    File svnExecutable = null;
                    if (SystemInfo.isWindows) {
                        svnExecutable = new File(svnBinDir, "windows/svn.exe");
                    } else if (SystemInfo.isLinux) {
                        svnExecutable = new File(svnBinDir, "linux/svn");
                    } else if (SystemInfo.isMac) {
                        svnExecutable = new File(svnBinDir, "mac/svn");
                    }
                    assertTrue("No Subversion executable was found: " + svnExecutable + ", " + SystemInfo.OS_NAME,
                            svnExecutable != null && svnExecutable.canExecute());
                    myClientBinaryPath = svnExecutable.getParentFile();
                    myRunner = SystemInfo.isMac
                            ? createClientRunner(
                                    Collections.singletonMap("DYLD_LIBRARY_PATH", myClientBinaryPath.getPath()))
                            : createClientRunner();

                    ZipUtil.extract(new File(myPluginRoot, getTestDataDir() + "/svn/newrepo.zip"), myRepoRoot,
                            null);

                    myWcRoot = new File(myTempDirFixture.getTempDirPath(), myWcRootName);
                    assert myWcRoot.mkdir() || myWcRoot.isDirectory() : myWcRoot;

                    myRepoUrl = (SystemInfo.isWindows ? "file:///" : "file://")
                            + FileUtil.toSystemIndependentName(myRepoRoot.getPath());

                    verify(runSvn("co", myRepoUrl, myWcRoot.getPath()));

                    initProject(myWcRoot, SvnTestCase.this.getTestName());
                    activateVCS(SvnVcs.VCS_NAME);

                    myGate = new MockChangeListManagerGate(ChangeListManager.getInstance(myProject));

                    ((StartupManagerImpl) StartupManager.getInstance(myProject)).runPostStartupActivities();
                    refreshSvnMappingsSynchronously();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });

        // there should be kind-a waiting for after change list manager finds all changes and runs inner refresh of copies in the above method
        if (myInitChangeListManager) {
            ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
            VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
            changeListManager.ensureUpToDate(false);
        }
    }

    protected void refreshSvnMappingsSynchronously() {
        final SvnVcs vcs = SvnVcs.getInstance(myProject);
        if (!myInitChangeListManager) {
            return;
        }
        final Semaphore semaphore = new Semaphore();
        semaphore.down();
        ((SvnFileUrlMappingImpl) vcs.getSvnFileUrlMapping()).realRefresh(new Runnable() {
            @Override
            public void run() {
                semaphore.up();
            }
        });
        semaphore.waitFor();
    }

    @Override
    protected void projectCreated() {
        if (isUseNativeAcceleration()) {
            SvnConfiguration.getInstance(myProject)
                    .setUseAcceleration(SvnConfiguration.UseAcceleration.commandLine);
            SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
        }
    }

    @After
    public void tearDown() throws Exception {
        ((ChangeListManagerImpl) ChangeListManager.getInstance(myProject)).stopEveryThingIfInTestMode();
        sleep(100);
        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
            @Override
            public void run() {
                try {
                    tearDownProject();

                    if (myWcRoot != null && myWcRoot.exists()) {
                        FileUtil.delete(myWcRoot);
                    }
                    if (myRepoRoot != null && myRepoRoot.exists()) {
                        FileUtil.delete(myRepoRoot);
                    }

                    if (myTempDirFixture != null) {
                        myTempDirFixture.tearDown();
                        myTempDirFixture = null;
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

    protected ProcessOutput runSvn(String... commandLine) throws IOException {
        return myRunner.runClient("svn", null, myWcRoot, commandLine);
    }

    protected void enableSilentOperation(final VcsConfiguration.StandardConfirmation op) {
        setStandardConfirmation(SvnVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY);
    }

    protected void disableSilentOperation(final VcsConfiguration.StandardConfirmation op) {
        setStandardConfirmation(SvnVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY);
    }

    protected void checkin() throws IOException {
        runInAndVerifyIgnoreOutput("ci", "-m", "test");
    }

    protected void update() throws IOException {
        runInAndVerifyIgnoreOutput("up");
    }

    protected List<Change> getChangesInScope(final VcsDirtyScope dirtyScope) throws VcsException {
        ChangeProvider changeProvider = SvnVcs.getInstance(myProject).getChangeProvider();
        MockChangelistBuilder builder = new MockChangelistBuilder();
        changeProvider.getChanges(dirtyScope, builder, new EmptyProgressIndicator(), myGate);
        return builder.getChanges();
    }

    protected void undo() {
        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
            @Override
            public void run() {
                final TestDialog oldTestDialog = Messages.setTestDialog(TestDialog.OK);
                try {
                    UndoManager.getInstance(myProject).undo(null);
                } finally {
                    Messages.setTestDialog(oldTestDialog);
                }
            }
        });
    }

    protected void prepareInnerCopy(final boolean anotherRepository) throws Exception {
        final String mainUrl = myRepoUrl + "/root/source";
        final String externalURL;
        if (anotherRepository) {
            createAnotherRepo();
            externalURL = myAnotherRepoUrl + "/root/target";
        } else {
            externalURL = myRepoUrl + "/root/target";
        }

        final ChangeListManagerImpl clManager = (ChangeListManagerImpl) ChangeListManager.getInstance(myProject);
        final SubTree subTree = new SubTree(myWorkingCopyDir);
        checkin();
        clManager.stopEveryThingIfInTestMode();
        sleep(100);
        final File rootFile = new File(subTree.myRootDir.getPath());
        FileUtil.delete(rootFile);
        FileUtil.delete(new File(myWorkingCopyDir.getPath() + File.separator + ".svn"));
        assertTrue(!rootFile.exists());
        sleep(200);
        myWorkingCopyDir.refresh(false, true);

        runInAndVerifyIgnoreOutput("co", mainUrl);
        final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
        final File innerDir = new File(sourceDir, "inner1/inner2/inner");
        runInAndVerifyIgnoreOutput("co", externalURL, innerDir.getPath());
        sleep(100);
        myWorkingCopyDir.refresh(false, true);
        // above is preparation

        // start change list manager again
        clManager.forceGoInTestMode();
        refreshSvnMappingsSynchronously();
        //clManager.ensureUpToDate(false);
        //clManager.ensureUpToDate(false);
    }

    public String getTestDataDir() {
        return StringUtil.isEmpty(ourGlobalTestDataDir) ? myTestDataDir : ourGlobalTestDataDir;
    }

    public void setTestDataDir(String testDataDir) {
        myTestDataDir = testDataDir;
    }

    public boolean isUseNativeAcceleration() {
        return ourGlobalUseNativeAcceleration != null ? ourGlobalUseNativeAcceleration : myUseNativeAcceleration;
    }

    public void setUseNativeAcceleration(boolean useNativeAcceleration) {
        myUseNativeAcceleration = useNativeAcceleration;
    }

    protected class SubTree {
        public VirtualFile myRootDir;
        public VirtualFile mySourceDir;
        public VirtualFile myTargetDir;

        public VirtualFile myS1File;
        public VirtualFile myS2File;

        public final List<VirtualFile> myTargetFiles;
        public static final String ourS1Contents = "123";
        public static final String ourS2Contents = "abc";

        private VirtualFile findOrCreateChild(final VirtualFile parent, final String name, final String content) {
            final VirtualFile result = parent.findChild(name);
            if (result != null)
                return result;
            if (content == null) {
                return createDirInCommand(parent, name);
            } else {
                return createFileInCommand(parent, name, content);
            }
        }

        public SubTree(final VirtualFile base) throws Exception {
            myRootDir = findOrCreateChild(base, "root", null);
            mySourceDir = findOrCreateChild(myRootDir, "source", null);
            myS1File = findOrCreateChild(mySourceDir, "s1.txt", ourS1Contents);
            myS2File = findOrCreateChild(mySourceDir, "s2.txt", ourS2Contents);

            myTargetDir = findOrCreateChild(myRootDir, "target", null);
            myTargetFiles = new ArrayList<VirtualFile>();
            for (int i = 0; i < 10; i++) {
                myTargetFiles.add(findOrCreateChild(myTargetDir, "t" + (i + 10) + ".txt", ourS1Contents));
            }
        }
    }

    protected static void sleep(final int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ignore) {
        }
    }

    public String prepareBranchesStructure() throws Exception {
        final SvnVcs vcs = SvnVcs.getInstance(myProject);
        final String mainUrl = myRepoUrl + "/trunk";
        runInAndVerifyIgnoreOutput("mkdir", "-m", "mkdir", mainUrl);
        runInAndVerifyIgnoreOutput("mkdir", "-m", "mkdir", myRepoUrl + "/branches");
        runInAndVerifyIgnoreOutput("mkdir", "-m", "mkdir", myRepoUrl + "/tags");

        final ChangeListManagerImpl clManager = (ChangeListManagerImpl) ChangeListManager.getInstance(myProject);
        clManager.stopEveryThingIfInTestMode();
        sleep(100);
        boolean deleted = false;
        for (int i = 0; i < 5; i++) {
            deleted = FileUtil.delete(new File(myWorkingCopyDir.getPath() + File.separator + ".svn"));
            if (deleted)
                break;
            sleep(200);
        }
        assertTrue(deleted);
        sleep(200);
        myWorkingCopyDir.refresh(false, true);

        runInAndVerifyIgnoreOutput("co", mainUrl, myWorkingCopyDir.getPath());
        enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
        final SubTree tree = new SubTree(myWorkingCopyDir);
        checkin();
        final String branchUrl = myRepoUrl + "/branches/b1";
        runInAndVerifyIgnoreOutput("copy", "-q", "-m", "coppy", mainUrl, branchUrl);

        clManager.forceGoInTestMode();
        refreshSvnMappingsSynchronously();
        //clManager.ensureUpToDate(false);
        //clManager.ensureUpToDate(false);

        return branchUrl;
    }

    public void prepareExternal() throws Exception {
        prepareExternal(true, true, false);
    }

    public void prepareExternal(final boolean commitExternalDefinition, final boolean updateExternal,
            final boolean anotherRepository) throws Exception {
        final ChangeListManagerImpl clManager = (ChangeListManagerImpl) ChangeListManager.getInstance(myProject);
        final SvnVcs vcs = SvnVcs.getInstance(myProject);
        final String mainUrl = myRepoUrl + "/root/source";
        final String externalURL;
        if (anotherRepository) {
            createAnotherRepo();
            externalURL = myAnotherRepoUrl + "/root/target";
        } else {
            externalURL = myRepoUrl + "/root/target";
        }

        final SubTree subTree = new SubTree(myWorkingCopyDir);
        checkin();
        clManager.stopEveryThingIfInTestMode();
        sleep(100);
        final File rootFile = new File(subTree.myRootDir.getPath());
        FileUtil.delete(rootFile);
        FileUtil.delete(new File(myWorkingCopyDir.getPath() + File.separator + ".svn"));
        assertTrue(!rootFile.exists());
        sleep(200);
        myWorkingCopyDir.refresh(false, true);

        final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
        runInAndVerifyIgnoreOutput("co", mainUrl, sourceDir.getPath());
        CreateExternalAction.addToExternalProperty(vcs, sourceDir, "external", externalURL);
        sleep(100);

        if (updateExternal) {
            runInAndVerifyIgnoreOutput("up", sourceDir.getPath());
        }
        if (commitExternalDefinition) {
            runInAndVerifyIgnoreOutput("ci", "-m", "test", sourceDir.getPath());
        }
        sleep(100);

        if (updateExternal) {
            myWorkingCopyDir.refresh(false, true);
            assertTrue(new File(sourceDir, "external").exists());
        }
        // above is preparation

        // start change list manager again
        clManager.forceGoInTestMode();
        refreshSvnMappingsSynchronously();
        //clManager.ensureUpToDate(false);
        //clManager.ensureUpToDate(false);
    }

    protected void createAnotherRepo() throws Exception {
        final File repo = FileUtil.createTempDirectory("anotherRepo", "");
        FileUtil.delete(repo);
        FileUtil.copyDir(myRepoRoot, repo);
        myAnotherRepoUrl = (SystemInfo.isWindows ? "file:///" : "file://")
                + FileUtil.toSystemIndependentName(repo.getPath());
        final File tmpWc = FileUtil.createTempDirectory("hhh", "");
        runInAndVerifyIgnoreOutput("co", myAnotherRepoUrl, tmpWc.getPath());
        final VirtualFile tmpWcVf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tmpWc);
        assertNotNull(tmpWcVf);
        final SubTree tree = new SubTree(tmpWcVf);
        runInAndVerifyIgnoreOutput(tmpWc, "add", "root");
        runInAndVerifyIgnoreOutput(tmpWc, "ci", "-m", "fff");
        FileUtil.delete(tmpWc);
    }

    protected static void imitUpdate(final Project project) {
        ProjectLevelVcsManagerEx.getInstanceEx(project).getOptions(VcsConfiguration.StandardOption.UPDATE)
                .setValue(false);
        final CommonUpdateProjectAction action = new CommonUpdateProjectAction();
        action.getTemplatePresentation().setText("1");
        action.actionPerformed(new AnActionEvent(null, new DataContext() {
            @Nullable
            @Override
            public Object getData(@NonNls String dataId) {
                if (CommonDataKeys.PROJECT.is(dataId)) {
                    return project;
                }
                return null;
            }
        }, "test", new Presentation(), null, 0));

        final ChangeListManager clManager = ChangeListManager.getInstance(project);
        clManager.ensureUpToDate(false);
        clManager.ensureUpToDate(false); // wait for after-events like annotations recalculation
        sleep(100); // zipper updater
    }

    protected void runAndVerifyStatusSorted(final String... stdoutLines) throws IOException {
        runStatusAcrossLocks(myWcRoot, true, stdoutLines);
    }

    protected void runAndVerifyStatus(final String... stdoutLines) throws IOException {
        runStatusAcrossLocks(myWcRoot, false, stdoutLines);
    }

    private void runStatusAcrossLocks(@Nullable File workingDir, final boolean sorted, final String... stdoutLines)
            throws IOException {
        final Processor<ProcessOutput> primitiveVerifier = new Processor<ProcessOutput>() {
            @Override
            public boolean process(ProcessOutput output) {
                if (sorted) {
                    verifySorted(output, stdoutLines); // will assert if err not empty
                } else {
                    verify(output, stdoutLines); // will assert if err not empty
                }
                return false;
            }
        };
        runAndVerifyAcrossLocks(workingDir, new String[] { "status" }, new Processor<ProcessOutput>() {
            @Override
            public boolean process(ProcessOutput output) {
                final List<String> lines = output.getStdoutLines();
                for (String line : lines) {
                    if (line.trim().startsWith("L")) {
                        return true; // i.e. continue tries
                    }
                }
                primitiveVerifier.process(output);
                return false;
            }
        }, primitiveVerifier);
    }

    protected void runInAndVerifyIgnoreOutput(final String... inLines) throws IOException {
        final Processor<ProcessOutput> verifier = createPrimitiveExitCodeVerifier();
        runAndVerifyAcrossLocks(myWcRoot, myRunner, inLines, verifier, verifier);
    }

    private static Processor<ProcessOutput> createPrimitiveExitCodeVerifier() {
        return new Processor<ProcessOutput>() {
            @Override
            public boolean process(ProcessOutput output) {
                assertEquals(output.getStderr(), 0, output.getExitCode());
                return false;
            }
        };
    }

    public static void runInAndVerifyIgnoreOutput(File workingDir, final TestClientRunner runner,
            final String[] input, final String... stdoutLines) throws IOException {
        final Processor<ProcessOutput> verifier = createPrimitiveExitCodeVerifier();
        runAndVerifyAcrossLocks(workingDir, runner, input, verifier, verifier);
    }

    protected void runInAndVerifyIgnoreOutput(final File root, final String... inLines) throws IOException {
        final Processor<ProcessOutput> verifier = createPrimitiveExitCodeVerifier();
        runAndVerifyAcrossLocks(root, myRunner, inLines, verifier, verifier);
    }

    private void runAndVerifyAcrossLocks(@Nullable File workingDir, final String[] input,
            final Processor<ProcessOutput> verifier, final Processor<ProcessOutput> primitiveVerifier)
            throws IOException {
        workingDir = workingDir == null ? myWcRoot : workingDir;
        runAndVerifyAcrossLocks(workingDir, myRunner, input, verifier, primitiveVerifier);
    }

    /**
     * @param verifier - if returns true, try again
     */
    public static void runAndVerifyAcrossLocks(File workingDir, final TestClientRunner runner, final String[] input,
            final Processor<ProcessOutput> verifier, final Processor<ProcessOutput> primitiveVerifier)
            throws IOException {
        for (int i = 0; i < 5; i++) {
            final ProcessOutput output = runner.runClient("svn", null, workingDir, input);
            if (output.getExitCode() == 0) {
                if (verifier.process(output)) {
                    continue;
                }
                return;
            }

            if (!StringUtil.isEmptyOrSpaces(output.getStderr())) {
                final String stderr = output.getStderr();
                /*svn: E155004: Working copy '' locked.
                svn: E155004: '' is already locked.
                svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)*/
                if (stderr.contains("E155004") && stderr.contains("is already locked")) {
                    continue;
                }
            }
            // will throw assertion
            if (verifier.process(output)) {
                continue;
            }
            return;
        }
        final ProcessOutput output = runner.runClient("svn", null, workingDir, input);
        primitiveVerifier.process(output);
    }

    protected void setNativeAcceleration(final boolean value) {
        System.out.println("Set native acceleration to " + value);
        SvnConfiguration.getInstance(myProject).setUseAcceleration(
                value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing);
        SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
    }
}