From 6bd484862a8cadea2182a746007dbf2e8767111a Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 13 Mar 2015 16:39:22 +0100 Subject: [PATCH] IDEA-137442 Problems on exit from Idea when a project in Perforce --- .../impl/stores/ComponentStoreImpl.java | 2 +- .../impl/stores/DirectoryBasedStorage.java | 21 ++-- .../components/impl/stores/StorageUtil.java | 98 ++++++++++++------- .../store/ReadOnlyModificationException.java | 11 ++- .../openapi/options/SchemesManagerImpl.java | 26 +++-- 5 files changed, 99 insertions(+), 59 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 9b8f767c9240..5d0dcf7d2e11 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -196,7 +196,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } catch (ReadOnlyModificationException e) { LOG.warn(e); - readonlyFiles.add(Pair.create(session, e.getFile())); + readonlyFiles.add(Pair.create(e.getSession() == null ? session : e.getSession(), e.getFile())); } catch (Exception e) { if (errors == null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java index ed22efe6259b..a51630cdc1b7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java @@ -287,12 +287,17 @@ public class DirectoryBasedStorage extends StateStorageBase() { - @Override - public VirtualFile compute() throws IOException { - try { - OutputStream out = result.getOutputStream(requestor); - try { - if (lineSeparatorIfPrependXmlProlog != null) { - out.write(XML_PROLOG); - out.write(lineSeparatorIfPrependXmlProlog.getSeparatorBytes()); - } - content.writeTo(out); - } - finally { - out.close(); - } - return result; - } - catch (FileNotFoundException e) { - if (virtualFile == null) { - throw e; - } - throw new ReadOnlyModificationException(virtualFile, e); + if (equals) { + LOG.warn("Content equals, but it must be handled not on this level"); + return result; + } + else { + doWrite(requestor, result, virtualFile, content, lineSeparatorIfPrependXmlProlog); + return result; + } + } + + private static void doWrite(@NotNull final Object requestor, + @NotNull final VirtualFile file, + @Nullable final VirtualFile proposedFile, + @NotNull final BufferExposingByteArrayOutputStream content, + @Nullable final LineSeparator lineSeparatorIfPrependXmlProlog) throws IOException { + AccessToken token = WriteAction.start(); + try { + OutputStream out = file.getOutputStream(requestor); + try { + if (lineSeparatorIfPrependXmlProlog != null) { + out.write(XML_PROLOG); + out.write(lineSeparatorIfPrependXmlProlog.getSeparatorBytes()); } + content.writeTo(out); } - }); + finally { + out.close(); + } + } + catch (FileNotFoundException e) { + if (proposedFile == null) { + throw e; + } + else { + throw new ReadOnlyModificationException(proposedFile, e, new StateStorage.SaveSession() { + @Override + public void save() throws IOException { + doWrite(requestor, file, proposedFile, content, lineSeparatorIfPrependXmlProlog); + } + }); + } + } + finally { + token.finish(); + } } private static boolean isEqualContent(VirtualFile result, @@ -187,7 +208,7 @@ public class StorageUtil { return equals; } - public static void deleteFile(@NotNull File file, @NotNull Object requestor, @Nullable VirtualFile virtualFile) throws IOException { + public static void deleteFile(@NotNull File file, @NotNull final Object requestor, @Nullable final VirtualFile virtualFile) throws IOException { if (virtualFile == null) { LOG.warn("Cannot find virtual file " + file.getAbsolutePath()); } @@ -198,7 +219,17 @@ public class StorageUtil { } } else if (virtualFile.exists()) { - deleteFile(requestor, virtualFile); + try { + deleteFile(requestor, virtualFile); + } + catch (FileNotFoundException e) { + throw new ReadOnlyModificationException(virtualFile, e, new StateStorage.SaveSession() { + @Override + public void save() throws IOException { + deleteFile(requestor, virtualFile); + } + }); + } } } @@ -207,9 +238,6 @@ public class StorageUtil { try { virtualFile.delete(requestor); } - catch (FileNotFoundException e) { - throw new ReadOnlyModificationException(virtualFile, e); - } finally { token.finish(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java b/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java index 8550341fc763..e7361b166abb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java @@ -15,20 +15,29 @@ */ package com.intellij.openapi.components.store; +import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public final class ReadOnlyModificationException extends RuntimeException { private final VirtualFile myFile; + private final StateStorage.SaveSession mySession; - public ReadOnlyModificationException(@NotNull VirtualFile file, @NotNull Throwable cause) { + public ReadOnlyModificationException(@NotNull VirtualFile file, @Nullable Throwable cause, StateStorage.SaveSession session) { super(cause); myFile = file; + mySession = session; } @NotNull public VirtualFile getFile() { return myFile; } + + @Nullable + public StateStorage.SaveSession getSession() { + return mySession; + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java index eab56840f234..e885101942d7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.components.impl.stores.DirectoryBasedStorage; import com.intellij.openapi.components.impl.stores.DirectoryStorageData; import com.intellij.openapi.components.impl.stores.StorageUtil; @@ -503,6 +502,7 @@ public class SchemesManagerImpl errors = null; VirtualFile dir = getVirtualDir(); if (!hasSchemes) { myFilesToDelete.clear(); @@ -510,14 +510,14 @@ public class SchemesManagerImpl(); + errors.add(e); } } return; } - List errors = null; for (E scheme : schemesToSave) { try { saveScheme(scheme, nameGenerator); @@ -530,7 +530,7 @@ public class SchemesManagerImpl deleteFiles(@Nullable VirtualFile dir, List errors) { if (myFilesToDelete.isEmpty()) { - return; + return errors; } if (myProvider != null && myProvider.isEnabled()) { @@ -639,7 +640,15 @@ public class SchemesManagerImpl(); + } + errors.add(e); + } } } myFilesToDelete.clear(); @@ -648,6 +657,7 @@ public class SchemesManagerImpl