From 4c259c6c2cdb47100eef76717858c116cb02b468 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Sat, 16 Aug 2014 23:14:20 +0400 Subject: [PATCH] svn: Fixed revision detection for files changed during update (UpdatedFiles class) - correctly handle case that files updated in externals could have different revisions from files just under update command root (and also from files in other externals) --- .../openapi/vcs/update/FileGroup.java | 3 ++ .../openapi/vcs/update/UpdatedFiles.java | 4 +++ .../idea/svn/update/SvnUpdateEnvironment.java | 2 -- .../idea/svn/update/UpdateEventHandler.java | 29 +++++++++++++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java index a5fa2c121ed2..d9684018484a 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java @@ -254,6 +254,9 @@ public class FileGroup implements JDOMExternalizable { return null; } + /** + * @deprecated: remove after IDEA 14 + */ public void setRevisions(final String path, final AbstractVcs vcs, final VcsRevisionNumber revision) { for (UpdatedFile file : myFiles) { if (file.getPath().startsWith(path)) { diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java b/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java index d8d6d53371d8..fdd3237af1cd 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java @@ -106,6 +106,10 @@ public class UpdatedFiles implements JDOMExternalizable { return result; } + /** + * @deprecated: remove after IDEA 14 + */ + @SuppressWarnings("UnusedDeclaration") public void setRevisions(final String path, final AbstractVcs vcs, final VcsRevisionNumber revision) { for(FileGroup group: myGroups) { group.setRevisions(path, vcs, revision); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java index 554b2c29bc48..41bfd61fded1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java @@ -89,8 +89,6 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false); } - myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev))); - return rev; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java index b5dbe6730ede..aff94e123a31 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java @@ -16,10 +16,13 @@ package org.jetbrains.idea.svn.update; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.wm.StatusBar; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnFileUrlMapping; @@ -32,11 +35,12 @@ import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.util.SVNLogType; import java.io.File; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -49,6 +53,10 @@ public class UpdateEventHandler implements ProgressTracker { private final SvnVcs myVCS; @Nullable private final SvnUpdateContext mySequentialUpdatesContext; private final Map myUrlToCheckForSwitch; + // pair.first - group id, pair.second - file path + // Stack is used to correctly handle cases when updates of externals occur during ordinary update, because these inner updates could have + // its own revisions. + private final Stack>> myFilesWaitingForRevision; protected String myText; protected String myText2; @@ -60,6 +68,11 @@ public class UpdateEventHandler implements ProgressTracker { mySequentialUpdatesContext = sequentialUpdatesContext; myExternalsCount = 1; myUrlToCheckForSwitch = new HashMap(); + myFilesWaitingForRevision = ContainerUtil.newStack(); + // It is more suitable to make this push while handling UPDATE_NONE event - for command line like "svn update " this event will + // be fired when update of is started. But it's not clear if this event won't be fired in other cases by SVNKit. So currently + // first push is made here. If further we want to support commands like "svn update " this logic should be revised. + myFilesWaitingForRevision.push(ContainerUtil.>newArrayList()); } public void addToSwitch(final File file, final SVNURL url) { @@ -153,6 +166,7 @@ public class UpdateEventHandler implements ProgressTracker { if (mySequentialUpdatesContext != null) { mySequentialUpdatesContext.registerExternalRootBeingUpdated(event.getFile()); } + myFilesWaitingForRevision.push(ContainerUtil.>newArrayList()); myExternalsCount++; myText = SvnBundle.message("progress.text.updating.external.location", event.getFile().getAbsolutePath()); } @@ -162,6 +176,7 @@ public class UpdateEventHandler implements ProgressTracker { } else if (event.getAction() == EventAction.UPDATE_COMPLETED && event.getRevision() >= 0) { possiblySwitched(event); + setRevisionForWaitingFiles(event.getRevision()); myExternalsCount--; myText2 = SvnBundle.message("progres.text2.updated.to.revision", event.getRevision()); if (myExternalsCount == 0) { @@ -212,12 +227,22 @@ public class UpdateEventHandler implements ProgressTracker { protected void addFileToGroup(final String id, final ProgressEvent event) { final FileGroup fileGroup = myUpdatedFiles.getGroupById(id); final String path = event.getFile().getAbsolutePath(); - fileGroup.add(path, SvnVcs.getKey(), new SvnRevisionNumber(SVNRevision.create(event.getRevision()))); + myFilesWaitingForRevision.peek().add(Pair.create(id, path)); if (event.getErrorMessage() != null) { fileGroup.addError(path, event.getErrorMessage().getMessage()); } } + private void setRevisionForWaitingFiles(long revisionNumber) { + SvnRevisionNumber revision = new SvnRevisionNumber(SVNRevision.create(revisionNumber)); + + for (Pair pair : myFilesWaitingForRevision.pop()) { + FileGroup fileGroup = myUpdatedFiles.getGroupById(pair.getFirst()); + + fileGroup.add(pair.getSecond(), SvnVcs.getKey(), revision); + } + } + public void checkCancelled() throws SVNCancelException { if (myProgressIndicator != null) { myProgressIndicator.checkCanceled();