SVN: for tests and not only - make commands inside SvnFileSystemListener to be repeated up to 3 times in case of BUSY exception

This commit is contained in:
irengrig
2012-06-29 16:25:00 +04:00
parent 425307a03d
commit 8b67e5bf7f
2 changed files with 148 additions and 23 deletions
@@ -0,0 +1,60 @@
/*
* Copyright 2000-2012 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.svn;
import org.tmatesoft.svn.core.SVNException;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 6/29/12
* Time: 3:45 PM
*/
public abstract class RepeatSvnActionThroughBusy {
public static final int REPEAT = 3;
protected int myCnt = REPEAT;
protected long myTimeout = 50;
protected abstract void executeImpl() throws SVNException;
protected Object myT;
public <T> T compute() throws SVNException {
execute();
return (T) myT;
}
public void execute() throws SVNException {
while (true) {
try {
executeImpl();
break;
} catch (SVNException e) {
if (SvnVcs.ourBusyExceptionProcessor.process(e)) {
if (myCnt > 0) {
try {
Thread.sleep(myTimeout * (REPEAT - myCnt + 1));
}
catch (InterruptedException e1) {
//
}
-- myCnt;
continue;
}
}
throw e;
}
}
}
}
@@ -168,7 +168,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
@Nullable
public String getRepositoryUUID(final Project project, final VirtualFile dir) {
try {
final SVNInfo info1 = myWcClient.doInfo(new File(dir.getPath()), SVNRevision.UNDEFINED);
final SVNInfo info1 = new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
myT = myWcClient.doInfo(new File(dir.getPath()), SVNRevision.UNDEFINED);
}
}.compute();
if (info1 == null || info1.getRepositoryUUID() == null) {
// go deeper if current parent was added (if parent was added, it theoretically could NOT know its repo UUID)
final VirtualFile parent = dir.getParent();
@@ -252,18 +257,33 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
return true;
}
private boolean for17move(SvnVcs vcs, File src, File dst, boolean undo) throws SVNException {
private boolean for17move(SvnVcs vcs, final File src, final File dst, boolean undo) throws SVNException {
if (undo) {
final SVNWCClient wcClient = vcs.createWCClient();
myUndoingMove = true;
wcClient.doRevert(dst, true);
wcClient.doRevert(src, true);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doRevert(dst, true);
}
}.execute();
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doRevert(src, true);
}
}.execute();
restoreFromUndoStorage(dst);
} else {
if (doUsualMove(vcs, src)) return true;
final SVNCopyClient copyClient = vcs.createCopyClient();
final SVNCopySource svnCopySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.WORKING, src);
copyClient.doCopy(new SVNCopySource[]{svnCopySource}, dst, true, false, true);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
copyClient.doCopy(new SVNCopySource[]{svnCopySource}, dst, true, false, true);
}
}.execute();
}
return false;
}
@@ -280,17 +300,27 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
return false;
}
private boolean for16move(SvnVcs vcs, File src, File dst, boolean undo) throws SVNException {
SVNMoveClient mover = vcs.createMoveClient();
private boolean for16move(SvnVcs vcs, final File src, final File dst, boolean undo) throws SVNException {
final SVNMoveClient mover = vcs.createMoveClient();
if (undo) {
myUndoingMove = true;
restoreFromUndoStorage(dst);
mover.undoMove(src, dst);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
mover.undoMove(src, dst);
}
}.execute();
}
else {
// if src is not under version control, do usual move.
if (doUsualMove(vcs, src)) return true;
mover.doMove(src, dst);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
mover.doMove(src, dst);
}
}.execute();
}
return false;
}
@@ -349,7 +379,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
return true;
}
if (vcs == null) return false;
File ioFile = getIOFile(file);
final File ioFile = getIOFile(file);
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
return false;
}
@@ -385,7 +415,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
try {
final SVNWCClient wcClient = vcs.createWCClient();
wcClient.doRevert(ioFile, false);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doRevert(ioFile, false);
}
}.execute();
}
catch (SVNException e) {
// ignore
@@ -452,8 +487,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) {
return false;
}
SVNWCClient wcClient = vcs.createWCClient();
File targetFile = new File(ioDir, name);
final SVNWCClient wcClient = vcs.createWCClient();
final File targetFile = new File(ioDir, name);
SVNStatus status = getFileStatus(vcs, targetFile);
if (status == null || status.getContentsStatus() == SVNStatusType.STATUS_NONE ||
@@ -472,7 +507,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
}
try {
if (isUndo(vcs)) {
wcClient.doRevert(targetFile, false);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doRevert(targetFile, false);
}
}.execute();
return true;
}
myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
@@ -625,7 +665,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
return new Runnable() {
@Override
public void run() {
SVNWCClient wcClient = vcs.createWCClient();
final SVNWCClient wcClient = vcs.createWCClient();
final SVNCopyClient copyClient = vcs.createCopyClient();
for(VirtualFile file: filesToProcess) {
final File ioFile = new File(file.getPath());
@@ -638,7 +678,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
try {
// not recursive
final SVNCopySource[] copySource = {new SVNCopySource(SVNRevision.WORKING, SVNRevision.WORKING, copyFrom)};
copyClient.doCopy(copySource, ioFile, false, true, true);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
copyClient.doCopy(copySource, ioFile, false, true, true);
}
}.execute();
}
catch (SVNException e) {
throw new VcsException(e);
@@ -651,7 +696,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
}
}
else {
wcClient.doAdd(ioFile, true, false, false, true);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doAdd(ioFile, true, false, false, true);
}
}.execute();
}
VcsDirtyScopeManager.getInstance(project).fileDirty(file);
}
@@ -760,12 +810,17 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
final List<VcsException> exceptions) {
return new Runnable() {
public void run() {
SVNWCClient wcClient = vcs.createWCClient();
final SVNWCClient wcClient = vcs.createWCClient();
for(FilePath file: filesToProcess) {
VirtualFile vFile = file.getVirtualFile(); // for deleted directories
File ioFile = new File(file.getPath());
final File ioFile = new File(file.getPath());
try {
wcClient.doDelete(ioFile, true, false);
new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
wcClient.doDelete(ioFile, true, false);
}
}.execute();
if (vFile != null && vFile.isValid() && vFile.isDirectory()) {
vFile.refresh(true, true);
VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(vFile);
@@ -811,10 +866,15 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
final SvnVcs vcs = SvnVcs.getInstance(project);
final SVNStatusClient sc = vcs.createStatusClient();
final Collection<File> files = myDeletedFiles.remove(project);
for (File file : files) {
for (final File file : files) {
boolean isAdded = false;
try {
final SVNStatus status = sc.doStatus(file, false);
final SVNStatus status = new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
myT = sc.doStatus(file, false);
}
}.compute();
isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
}
catch (SVNException e) {
@@ -884,7 +944,12 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
@Nullable
private static SVNStatus getFileStatus(final File file, final SVNStatusClient stClient) {
try {
return stClient.doStatus(file, false);
return new RepeatSvnActionThroughBusy() {
@Override
protected void executeImpl() throws SVNException {
myT = stClient.doStatus(file, false);
}
}.compute();
}
catch (SVNException e) {
return null;