mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
656 lines
25 KiB
Java
656 lines
25 KiB
Java
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
|
package org.jetbrains.idea.svn;
|
|
|
|
import com.intellij.openapi.Disposable;
|
|
import com.intellij.openapi.diagnostic.Logger;
|
|
import com.intellij.openapi.util.Condition;
|
|
import com.intellij.openapi.util.Disposer;
|
|
import com.intellij.openapi.vcs.FilePath;
|
|
import com.intellij.openapi.vcs.FileStatus;
|
|
import com.intellij.openapi.vcs.VcsConfiguration;
|
|
import com.intellij.openapi.vcs.VcsException;
|
|
import com.intellij.openapi.vcs.changes.Change;
|
|
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
|
import com.intellij.openapi.vcs.changes.LocallyDeletedChange;
|
|
import com.intellij.openapi.vcs.changes.SimpleContentRevision;
|
|
import com.intellij.openapi.vcs.rollback.RollbackProgressListener;
|
|
import com.intellij.openapi.vfs.LocalFileSystem;
|
|
import com.intellij.openapi.vfs.VirtualFile;
|
|
import com.intellij.openapi.vfs.newvfs.RefreshSession;
|
|
import com.intellij.testFramework.RunAll;
|
|
import com.intellij.testFramework.TestLoggerFactory;
|
|
import com.intellij.util.containers.ContainerUtil;
|
|
import org.jetbrains.idea.svn.api.Depth;
|
|
import org.jetbrains.idea.svn.api.Target;
|
|
import org.jetbrains.idea.svn.commandLine.SvnBindException;
|
|
import org.jetbrains.idea.svn.ignore.FileGroupInfo;
|
|
import org.jetbrains.idea.svn.ignore.SvnPropertyService;
|
|
import org.jetbrains.idea.svn.properties.PropertyValue;
|
|
import org.junit.Assume;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import static com.intellij.openapi.util.io.FileUtil.filesEqual;
|
|
import static com.intellij.openapi.vfs.VfsUtilCore.virtualToIoFile;
|
|
import static com.intellij.testFramework.UsefulTestCase.assertDoesntExist;
|
|
import static com.intellij.testFramework.UsefulTestCase.assertExists;
|
|
import static com.intellij.util.containers.ContainerUtil.isEmpty;
|
|
import static com.intellij.util.lang.CompoundRuntimeException.throwIfNotEmpty;
|
|
import static com.intellij.vcsUtil.VcsUtil.getFilePath;
|
|
import static java.util.Arrays.asList;
|
|
import static java.util.Collections.emptyList;
|
|
import static java.util.Collections.singletonList;
|
|
import static org.jetbrains.idea.svn.api.Revision.WORKING;
|
|
import static org.junit.Assert.*;
|
|
|
|
public class SvnRollbackTest extends SvnTestCase {
|
|
private Disposable testRootDisposable = null;
|
|
|
|
@Override
|
|
@Before
|
|
public void before() throws Exception {
|
|
super.before();
|
|
|
|
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
|
|
|
testRootDisposable = Disposer.newDisposable("SvnRollbackTest");
|
|
TestLoggerFactory.enableDebugLogging(testRootDisposable, RefreshSession.class);
|
|
}
|
|
|
|
@Override
|
|
public void after() throws Exception {
|
|
RunAll.runAll(
|
|
() -> {
|
|
Disposer.dispose(testRootDisposable);
|
|
testRootDisposable = null;
|
|
},
|
|
() -> super.after()
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testSimpleRollback() throws Exception {
|
|
final VirtualFile a = createFileInCommand("a.txt", "test");
|
|
checkin();
|
|
|
|
editFileInCommand(a, "tset");
|
|
refreshChanges();
|
|
|
|
final Change change = changeListManager.getChange(a);
|
|
assertNotNull(change);
|
|
|
|
assertRollback(singletonList(change), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackMoveDir() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
moveFileInCommand(tree.mySourceDir, tree.myTargetDir);
|
|
refreshChanges();
|
|
|
|
final Change change = assertMove(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
|
|
assertRollback(singletonList(change), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackMOveDirVariant() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
final VirtualFile unv = createFileInCommand(tree.mySourceDir, "unv.txt", "***");
|
|
final File wasUnversioned = virtualToIoFile(unv);
|
|
moveFileInCommand(tree.mySourceDir, tree.myTargetDir);
|
|
refreshChanges();
|
|
|
|
final Change change = assertMove(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
final Change s2Change = assertMove(tree.myS2File);
|
|
assertTrue(unv.isValid());
|
|
assertTrue(!filesEqual(virtualToIoFile(unv), wasUnversioned));
|
|
assertDoesntExist(wasUnversioned);
|
|
|
|
assertRollback(asList(change, s2Change), emptyList());
|
|
|
|
assertExists(wasUnversioned);
|
|
}
|
|
|
|
//IDEA-39943
|
|
@Test
|
|
public void testRollbackWithDeepUnversioned() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final VirtualFile inner = createDirInCommand(tree.mySourceDir, "inner");
|
|
final VirtualFile innerFile = createFileInCommand(inner, "inInner.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
final VirtualFile deepUnverioned = createFileInCommand(inner, "deepUnverioned.txt", "deepUnverioned");
|
|
final File was = virtualToIoFile(deepUnverioned);
|
|
|
|
checkin();
|
|
runAndVerifyStatus("? root/source/inner/" + deepUnverioned.getName());
|
|
update();
|
|
|
|
renameFileInCommand(tree.mySourceDir, "newName");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change change = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertMove(inner);
|
|
assertMove(innerFile);
|
|
|
|
assertTrue(!filesEqual(virtualToIoFile(deepUnverioned), was));
|
|
assertDoesntExist(was);
|
|
|
|
assertRollback(singletonList(change), emptyList());
|
|
|
|
assertExists(was);
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackDeepEdit() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final VirtualFile inner = createDirInCommand(tree.mySourceDir, "inner");
|
|
final VirtualFile innerFile = createFileInCommand(inner, "inInner.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
checkin();
|
|
runAndVerifyStatus();
|
|
update();
|
|
|
|
editFileInCommand(innerFile, "some content");
|
|
renameFileInCommand(tree.mySourceDir, "newName");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change change = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertMove(inner);
|
|
final Change innerChange = assertMove(innerFile);
|
|
|
|
assertRollback(singletonList(change),
|
|
singletonList(new Change(innerChange.getBeforeRevision(), innerChange.getBeforeRevision(), FileStatus.MODIFIED)));
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackDirRenameWithDeepRenamesAndUnverioned() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final VirtualFile inner = createDirInCommand(tree.mySourceDir, "inner");
|
|
final VirtualFile inner1 = createDirInCommand(inner, "inner1");
|
|
final VirtualFile inner2 = createDirInCommand(inner1, "inner2");
|
|
createFileInCommand(inner1, "inInner38432.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
final VirtualFile inner3 = createDirInCommand(inner2, "inner3");
|
|
final VirtualFile innerFile = createFileInCommand(inner3, "inInner.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
final VirtualFile innerFile1 = createFileInCommand(inner3, "inInner1.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
final VirtualFile deepUNversioned = createFileInCommand(inner3, "deep.txt", "deep");
|
|
final File wasU = virtualToIoFile(deepUNversioned);
|
|
final File wasLowestDir = virtualToIoFile(inner3);
|
|
final File wasInnerFile1 = virtualToIoFile(innerFile1);
|
|
final File wasInnerFile = virtualToIoFile(innerFile);
|
|
checkin();
|
|
runAndVerifyStatus("? root/source/inner/inner1/inner2/inner3/deep.txt");
|
|
update();
|
|
|
|
editFileInCommand(innerFile, "some content");
|
|
final File inner2Before = virtualToIoFile(inner2);
|
|
renameFileInCommand(inner2, "newName2");
|
|
final File wasU2 = virtualToIoFile(deepUNversioned);
|
|
final File inner2After = virtualToIoFile(inner2);
|
|
final File wasInnerFileAfter = virtualToIoFile(innerFile);
|
|
final File wasInnerFile1After = virtualToIoFile(innerFile1);
|
|
final File wasLowestDirAfter = virtualToIoFile(inner3);
|
|
|
|
renameFileInCommand(tree.mySourceDir, "newNameSource");
|
|
assertDoesntExist(wasU);
|
|
assertDoesntExist(wasU2);
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", inner2.isValid());
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change change = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertMove(inner2);
|
|
assertMove(inner);
|
|
assertMove(innerFile);
|
|
|
|
final Change fantomDelete1 = new Change(new SimpleContentRevision("1", getFilePath(wasLowestDir, true), "2"),
|
|
new SimpleContentRevision("1", getFilePath(wasLowestDirAfter, true), "2"));
|
|
final Change fantomDelete2 = new Change(new SimpleContentRevision("1", getFilePath(wasInnerFile1, false), "2"),
|
|
new SimpleContentRevision("1", getFilePath(wasInnerFile1After, false), WORKING.toString()));
|
|
|
|
assertRollback(
|
|
singletonList(change),
|
|
asList(new Change(new SimpleContentRevision("1", getFilePath(wasInnerFile, false), "2"),
|
|
new SimpleContentRevision("1", getFilePath(wasInnerFileAfter, false), WORKING.toString())),
|
|
new Change(new SimpleContentRevision("1", getFilePath(inner2Before, true), "2"),
|
|
new SimpleContentRevision("1", getFilePath(inner2After, true), WORKING.toString())), fantomDelete1, fantomDelete2)
|
|
);
|
|
|
|
assertExists(wasU2);
|
|
}
|
|
|
|
@Test
|
|
public void testKeepDeepProperty() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final VirtualFile inner = createDirInCommand(tree.mySourceDir, "inner");
|
|
final VirtualFile innerFile = createFileInCommand(inner, "inInner.txt", "kdfjsdisdjiuewjfew wefn w");
|
|
checkin();
|
|
runAndVerifyStatus();
|
|
update();
|
|
|
|
final File fileBefore = virtualToIoFile(innerFile);
|
|
setProperty(fileBefore, "abc", "cde");
|
|
assertEquals("cde", getProperty(virtualToIoFile(innerFile), "abc"));
|
|
final File innerBefore = virtualToIoFile(inner);
|
|
renameFileInCommand(inner, "innerNew");
|
|
final File innerAfter = virtualToIoFile(inner);
|
|
final File fileAfter = virtualToIoFile(innerFile);
|
|
renameFileInCommand(tree.mySourceDir, "newName");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", inner.isValid());
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change change = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertMove(inner);
|
|
assertMove(innerFile);
|
|
assertEquals("cde", getProperty(virtualToIoFile(innerFile), "abc"));
|
|
|
|
assertRollback(
|
|
singletonList(change),
|
|
asList(new Change(new SimpleContentRevision("1", getFilePath(innerBefore, true), "2"),
|
|
new SimpleContentRevision("1", getFilePath(innerAfter, true), WORKING.toString())),
|
|
new Change(new SimpleContentRevision("1", getFilePath(fileBefore, false), "2"),
|
|
new SimpleContentRevision("1", getFilePath(fileAfter, false), WORKING.toString())))
|
|
);
|
|
|
|
assertEquals("cde", getProperty(fileAfter, "abc"));
|
|
}
|
|
|
|
private String getProperty(File file, String name) throws SvnBindException {
|
|
PropertyValue value = vcs.getFactory(file).createPropertyClient().getProperty(Target.on(file), name, false, WORKING);
|
|
|
|
return PropertyValue.toString(value);
|
|
}
|
|
|
|
private void setProperty(final File file, final String name, final String value) throws SvnBindException {
|
|
vcs.getFactory(file).createPropertyClient().setProperty(file, name, PropertyValue.create(value), Depth.EMPTY, true);
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackDelete() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final FilePath fpSource = getFilePath(virtualToIoFile(tree.mySourceDir), true);
|
|
final FilePath fpT11 = getFilePath(virtualToIoFile(tree.myTargetFiles.get(0)), false);
|
|
deleteFileInCommand(tree.mySourceDir);
|
|
deleteFileInCommand(tree.myTargetFiles.get(0));
|
|
refreshChanges();
|
|
|
|
final Change change = assertDelete(fpSource);
|
|
final Change t11Change = assertDelete(fpT11);
|
|
|
|
assertRollback(asList(change, t11Change), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackAdd() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final VirtualFile newDir = createDirInCommand(tree.mySourceDir, "newDir");
|
|
final VirtualFile inNewDir = createFileInCommand(newDir, "f.txt", "12345");
|
|
final VirtualFile inSource = createFileInCommand(tree.myTargetDir, "newF.txt", "54321");
|
|
assertTrue(newDir != null && inNewDir != null && inSource != null);
|
|
refreshChanges();
|
|
|
|
final Change change = assertAdd(newDir);
|
|
assertAdd(inNewDir);
|
|
final Change inSourceChange = assertAdd(inSource);
|
|
|
|
assertRollback(asList(change, inSourceChange), emptyList());
|
|
}
|
|
|
|
// move directory with unversioned dir + check edit
|
|
@Test
|
|
public void testRollbackRenameDirWithUnversionedDir() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final String editedText = "s1 edited";
|
|
editFileInCommand(tree.myS1File, editedText);
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
final VirtualFile unverionedDir = createDirInCommand(tree.mySourceDir, "unverionedDir");
|
|
final String unvText = "unv content";
|
|
final VirtualFile unvFile = createFileInCommand(unverionedDir, "childFile", unvText);
|
|
final File wasUnvDir = virtualToIoFile(unverionedDir);
|
|
final File wasUnvFile = virtualToIoFile(unvFile);
|
|
renameFileInCommand(tree.mySourceDir, "renamed");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change dirChange = assertRename(tree.mySourceDir);
|
|
final Change s1Change = assertMove(tree.myS1File);
|
|
assertEquals(FileStatus.UNKNOWN, changeListManager.getStatus(unverionedDir));
|
|
assertDoesntExist(wasUnvDir);
|
|
assertEquals(FileStatus.UNKNOWN, changeListManager.getStatus(unvFile));
|
|
assertDoesntExist(wasUnvFile);
|
|
|
|
assertRollback(singletonList(dirChange),
|
|
singletonList(new Change(s1Change.getBeforeRevision(), s1Change.getBeforeRevision(), FileStatus.MODIFIED)));
|
|
|
|
assertExists(wasUnvDir);
|
|
assertExists(wasUnvFile);
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackDirWithIgnored() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
VirtualFile ignored = createFileInCommand(tree.mySourceDir, "ign.txt", "ignored");
|
|
final File wasIgnored = virtualToIoFile(ignored);
|
|
final FileGroupInfo groupInfo = new FileGroupInfo();
|
|
groupInfo.onFileEnabled(ignored);
|
|
SvnPropertyService.doAddToIgnoreProperty(vcs, false, new VirtualFile[]{ignored}, groupInfo);
|
|
refreshChanges();
|
|
|
|
assertEquals(FileStatus.IGNORED, changeListManager.getStatus(ignored));
|
|
|
|
renameFileInCommand(tree.mySourceDir, "renamed");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change dirChange = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertDoesntExist(wasIgnored);
|
|
assertEquals(FileStatus.IGNORED, changeListManager.getStatus(ignored));
|
|
|
|
assertRollback(singletonList(dirChange), emptyList());
|
|
|
|
ignored = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wasIgnored);
|
|
// ignored property was not committed
|
|
assertEquals(FileStatus.UNKNOWN, changeListManager.getStatus(ignored));
|
|
assertExists(wasIgnored);
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackDirWithCommittedIgnored() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
|
|
|
VirtualFile ignored = createFileInCommand(tree.mySourceDir, "ign.txt", "ignored");
|
|
final File wasIgnored = virtualToIoFile(ignored);
|
|
final FileGroupInfo groupInfo = new FileGroupInfo();
|
|
groupInfo.onFileEnabled(ignored);
|
|
SvnPropertyService.doAddToIgnoreProperty(vcs, false, new VirtualFile[]{ignored}, groupInfo);
|
|
checkin();
|
|
refreshChanges();
|
|
update();
|
|
|
|
assertEquals(FileStatus.IGNORED, changeListManager.getStatus(ignored));
|
|
|
|
renameFileInCommand(tree.mySourceDir, "renamed");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change dirChange = assertRename(tree.mySourceDir);
|
|
assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
assertDoesntExist(wasIgnored);
|
|
assertEquals(FileStatus.IGNORED, changeListManager.getStatus(ignored));
|
|
|
|
assertRollback(singletonList(dirChange), emptyList());
|
|
|
|
ignored = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wasIgnored);
|
|
// ignored property was committed
|
|
assertEquals(FileStatus.IGNORED, changeListManager.getStatus(ignored));
|
|
assertExists(wasIgnored);
|
|
}
|
|
|
|
@Test
|
|
public void testListAllChangesForRevert() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final String editedText = "s1 edited";
|
|
editFileInCommand(tree.myS1File, editedText);
|
|
renameFileInCommand(tree.mySourceDir, "renamed");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change dirChange = assertRename(tree.mySourceDir);
|
|
final Change s1Change = assertMove(tree.myS1File);
|
|
final Change s2Change = assertMove(tree.myS2File);
|
|
|
|
assertRollback(asList(dirChange, s1Change, s2Change), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testKeepOneUnderRenamed() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final File was2 = virtualToIoFile(tree.myS2File);
|
|
editFileInCommand(tree.myS1File, "s1 edited");
|
|
editFileInCommand(tree.myS2File, "s2 edited");
|
|
renameFileInCommand(tree.mySourceDir, "renamed");
|
|
refreshChanges();
|
|
Assume.assumeTrue("Suspecting blinking IDEA-182560. Test aborted.", tree.mySourceDir.isValid());
|
|
|
|
final Change dirChange = assertRename(tree.mySourceDir);
|
|
final Change s1Change = assertMove(tree.myS1File);
|
|
assertMove(tree.myS2File);
|
|
|
|
final FilePath fp = getFilePath(was2, false);
|
|
assertRollback(asList(dirChange, s1Change), singletonList(
|
|
new Change(new SimpleContentRevision("1", fp, "1"), new SimpleContentRevision("1", fp, WORKING.toString()))));
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackLocallyDeletedSimple() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
|
|
|
final File wasFile = virtualToIoFile(tree.myS1File);
|
|
deleteFileInCommand(tree.myS1File);
|
|
refreshChanges();
|
|
|
|
final List<LocallyDeletedChange> deletedFiles = changeListManager.getDeletedFiles();
|
|
assertNotNull(deletedFiles);
|
|
assertEquals(1, deletedFiles.size());
|
|
assertEquals(wasFile, deletedFiles.get(0).getPath().getIOFile());
|
|
|
|
assertRollbackLocallyDeleted(singletonList(deletedFiles.get(0).getPath()), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackLocallyDeletedSimpleDir() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
|
|
|
final File wasFile = virtualToIoFile(tree.mySourceDir);
|
|
final File wasFileS1 = virtualToIoFile(tree.myS1File);
|
|
final File wasFileS2 = virtualToIoFile(tree.myS2File);
|
|
deleteFileInCommand(tree.mySourceDir);
|
|
refreshChanges();
|
|
|
|
final List<LocallyDeletedChange> deletedFiles = changeListManager.getDeletedFiles();
|
|
assertNotNull(deletedFiles);
|
|
assertEquals(3, deletedFiles.size());
|
|
|
|
final Set<File> files = ContainerUtil.newHashSet(wasFile, wasFileS1, wasFileS2);
|
|
for (LocallyDeletedChange file : deletedFiles) {
|
|
files.remove(file.getPath().getIOFile());
|
|
}
|
|
assertTrue(files.isEmpty());
|
|
|
|
assertRollbackLocallyDeleted(singletonList(getFilePath(wasFile, true)), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackAddedLocallyDeleted() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
VirtualFile f1 = createFileInCommand(tree.mySourceDir, "f1", "4");
|
|
VirtualFile dir = createDirInCommand(tree.mySourceDir, "dirrr");
|
|
VirtualFile f2 = createFileInCommand(dir, "f2", "411");
|
|
refreshChanges();
|
|
|
|
assertAdd(f1);
|
|
assertAdd(dir);
|
|
assertAdd(f2);
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
|
|
|
final File wasFile1 = virtualToIoFile(f1);
|
|
final File wasFile2 = virtualToIoFile(dir);
|
|
final File wasFile3 = virtualToIoFile(f2);
|
|
deleteFileInCommand(f1);
|
|
deleteFileInCommand(dir);
|
|
refreshChanges();
|
|
|
|
final List<LocallyDeletedChange> deletedFiles = changeListManager.getDeletedFiles();
|
|
assertNotNull(deletedFiles);
|
|
assertEquals(3, deletedFiles.size());
|
|
final Set<File> files = ContainerUtil.newHashSet(wasFile1, wasFile2, wasFile3);
|
|
assertTrue(files.contains(deletedFiles.get(0).getPath().getIOFile()));
|
|
assertTrue(files.contains(deletedFiles.get(1).getPath().getIOFile()));
|
|
assertTrue(files.contains(deletedFiles.get(2).getPath().getIOFile()));
|
|
|
|
assertRollbackLocallyDeleted(asList(getFilePath(wasFile2, true), getFilePath(wasFile1, false)), emptyList());
|
|
}
|
|
|
|
@Test
|
|
public void testRollbackMovedDirectoryLocallyDeleted() throws Exception {
|
|
final SubTree tree = new SubTree(myWorkingCopyDir);
|
|
checkin();
|
|
|
|
final File wasInitially = virtualToIoFile(tree.mySourceDir);
|
|
assertExists(wasInitially);
|
|
moveFileInCommand(tree.mySourceDir, tree.myTargetDir);
|
|
assertDoesntExist(wasInitially);
|
|
refreshChanges();
|
|
|
|
assertMove(tree.mySourceDir);
|
|
final File was = virtualToIoFile(tree.mySourceDir);
|
|
assertNotSame(wasInitially, was);
|
|
|
|
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
|
|
|
deleteFileInCommand(tree.mySourceDir);
|
|
runAndVerifyStatus(
|
|
"D root/source",
|
|
"> moved to root/target/source",
|
|
"D root/source/s1.txt",
|
|
"D root/source/s2.txt",
|
|
"! root/target/source",
|
|
"! root/target/source/s1.txt",
|
|
"! root/target/source/s2.txt"
|
|
);
|
|
|
|
assertRollbackLocallyDeleted(singletonList(getFilePath(was, true)), emptyList());
|
|
|
|
runAndVerifyStatusSorted("D root/source", "D root/source/s1.txt", "D root/source/s2.txt");
|
|
}
|
|
|
|
private void assertRollback(List<Change> changes, final List<Change> allowedAfter) throws VcsException {
|
|
rollback(changes);
|
|
refreshChanges();
|
|
|
|
List<LocalChangeList> lists = changeListManager.getChangeLists();
|
|
final HashSet<Change> afterCopy = new HashSet<>(allowedAfter);
|
|
for (LocalChangeList list : lists) {
|
|
for (Change change : list.getChanges()) {
|
|
assertTrue(afterCopy.remove(change));
|
|
}
|
|
}
|
|
assertTrue(afterCopy.isEmpty());
|
|
}
|
|
|
|
private void assertRollbackLocallyDeleted(final List<FilePath> locally, final List<FilePath> allowed) throws VcsException {
|
|
final List<VcsException> exceptions = new ArrayList<>();
|
|
vcs.createRollbackEnvironment().rollbackMissingFileDeletion(locally, exceptions, RollbackProgressListener.EMPTY);
|
|
throwIfNotEmpty(exceptions);
|
|
refreshChanges();
|
|
|
|
final List<LocallyDeletedChange> deletedFiles = changeListManager.getDeletedFiles();
|
|
if (allowed == null || allowed.isEmpty()) {
|
|
assertTrue(isEmpty(deletedFiles));
|
|
}
|
|
final ArrayList<FilePath> copy = new ArrayList<>(allowed);
|
|
for (LocallyDeletedChange file : deletedFiles) {
|
|
copy.remove(file.getPath());
|
|
}
|
|
assertTrue(copy.isEmpty());
|
|
}
|
|
|
|
private Change assertAdd(VirtualFile file) {
|
|
return assertChangeFor(file, change -> change.getBeforeRevision() == null);
|
|
}
|
|
|
|
private Change assertDelete(FilePath fpSource) {
|
|
return assertChangeFor(fpSource, change -> change.getAfterRevision() == null);
|
|
}
|
|
|
|
private Change assertMove(VirtualFile file) {
|
|
return assertChangeFor(file, change -> change.isMoved());
|
|
}
|
|
|
|
private Change assertRename(VirtualFile file) {
|
|
return assertChangeFor(file, change -> change.isRenamed());
|
|
}
|
|
|
|
private Change assertChangeFor(VirtualFile file, Condition<Change> check) {
|
|
if (!file.isValid()) Logger.getInstance(SvnRollbackTest.class).warn("File is invalid: " + file);
|
|
return assertChangeFor(getFilePath(file), check);
|
|
}
|
|
|
|
private Change assertChangeFor(final FilePath file, Condition<Change> check) {
|
|
Change change = changeListManager.getChange(file);
|
|
assertTrue(String.format("Wrong change: %s\nAll changes: %s", change, changeListManager.getAllChanges()),
|
|
change != null && check.value(change));
|
|
return change;
|
|
}
|
|
}
|