From 8b67e5bf7fea5ba960f34de57011cb85490f356f Mon Sep 17 00:00:00 2001 From: irengrig Date: Fri, 29 Jun 2012 16:25:00 +0400 Subject: [PATCH] SVN: for tests and not only - make commands inside SvnFileSystemListener to be repeated up to 3 times in case of BUSY exception --- .../idea/svn/RepeatSvnActionThroughBusy.java | 60 ++++++++++ .../idea/svn/SvnFileSystemListener.java | 111 ++++++++++++++---- 2 files changed, 148 insertions(+), 23 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java new file mode 100644 index 000000000000..2d2a1b8fd962 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java @@ -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 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; + } + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java index 7e0745b50962..7737a88585e7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java @@ -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 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 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;