IDEA-137442 Problems on exit from Idea when a project in Perforce

This commit is contained in:
Vladimir Krivosheev
2015-03-13 16:40:29 +01:00
parent df51a4ae9a
commit 6bd484862a
5 changed files with 99 additions and 59 deletions
@@ -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) {
@@ -287,12 +287,17 @@ public class DirectoryBasedStorage extends StateStorageBase<DirectoryStorageData
}
}
private void deleteFiles(@NotNull VirtualFile dir) {
private void deleteFiles(@NotNull VirtualFile dir) throws IOException {
AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(DocumentRunnable.IgnoreDocumentRunnable.class);
try {
for (VirtualFile file : dir.getChildren()) {
if (removedFileNames.contains(file.getName())) {
deleteFile(file, this);
try {
file.delete(this);
}
catch (FileNotFoundException e) {
throw new ReadOnlyModificationException(file, e, null);
}
}
}
}
@@ -301,16 +306,4 @@ public class DirectoryBasedStorage extends StateStorageBase<DirectoryStorageData
}
}
}
public static void deleteFile(@NotNull VirtualFile file, @NotNull Object requestor) {
try {
file.delete(requestor);
}
catch (FileNotFoundException e) {
throw new ReadOnlyModificationException(file, e);
}
catch (IOException e) {
throw new StateStorageException(e);
}
}
}
@@ -22,6 +22,7 @@ import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.StateStorage;
import com.intellij.openapi.components.StoragePathMacros;
@@ -121,46 +122,66 @@ public class StorageUtil {
}
@NotNull
public static VirtualFile writeFile(@Nullable final File file,
@NotNull final Object requestor,
@Nullable final VirtualFile virtualFile,
@NotNull final BufferExposingByteArrayOutputStream content,
@Nullable final LineSeparator lineSeparatorIfPrependXmlProlog) throws IOException {
public static VirtualFile writeFile(@Nullable File file,
@NotNull Object requestor,
@Nullable VirtualFile virtualFile,
@NotNull BufferExposingByteArrayOutputStream content,
@Nullable LineSeparator lineSeparatorIfPrependXmlProlog) throws IOException {
final VirtualFile result;
if (file != null && (virtualFile == null || !virtualFile.isValid())) {
result = getOrCreateVirtualFile(requestor, file);
}
else {
result = virtualFile;
assert result != null;
}
assert result != null;
boolean equals = isEqualContent(result, lineSeparatorIfPrependXmlProlog, content);
if (equals) return result;
return ApplicationManager.getApplication().runWriteAction(new ThrowableComputable<VirtualFile, IOException>() {
@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();
}
@@ -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;
}
}
@@ -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<T extends Scheme, E extends ExternalizableScheme
}
}
List<Throwable> errors = null;
VirtualFile dir = getVirtualDir();
if (!hasSchemes) {
myFilesToDelete.clear();
@@ -510,14 +510,14 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
try {
StorageUtil.deleteFile(this, dir);
}
catch (IOException e) {
throw new StateStorageException(e);
catch (Throwable e) {
errors = new SmartList<Throwable>();
errors.add(e);
}
}
return;
}
List<Throwable> errors = null;
for (E scheme : schemesToSave) {
try {
saveScheme(scheme, nameGenerator);
@@ -530,7 +530,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
deleteFiles(dir);
errors = deleteFiles(dir, errors);
CompoundRuntimeException.doThrow(errors);
}
@@ -620,9 +620,10 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return !scheme.getName().equals(scheme.getExternalInfo().getPreviouslySavedName());
}
private void deleteFiles(@Nullable VirtualFile dir) {
@Nullable
private List<Throwable> deleteFiles(@Nullable VirtualFile dir, List<Throwable> errors) {
if (myFilesToDelete.isEmpty()) {
return;
return errors;
}
if (myProvider != null && myProvider.isEnabled()) {
@@ -639,7 +640,15 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
try {
for (VirtualFile file : dir.getChildren()) {
if (myFilesToDelete.contains(file.getNameWithoutExtension())) {
DirectoryBasedStorage.deleteFile(file, this);
try {
file.delete(this);
}
catch (IOException e) {
if (errors == null) {
errors = new SmartList<Throwable>();
}
errors.add(e);
}
}
}
myFilesToDelete.clear();
@@ -648,6 +657,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
token.finish();
}
}
return errors;
}
@Nullable