mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-138072 'Save' operation does nothing if there are unread 'could not save project' messages in Event Log
This commit is contained in:
-1
@@ -185,7 +185,6 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
errors = executeSave(session, readonlyFiles, errors);
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
+51
-31
@@ -18,6 +18,7 @@ package com.intellij.openapi.components.impl.stores;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.highlighter.ProjectFileType;
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.notification.NotificationsManager;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.components.*;
|
||||
@@ -30,6 +31,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.project.impl.ProjectImpl;
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl;
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl.UnableToSaveProjectNotification;
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -446,51 +448,69 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
|
||||
@Override
|
||||
protected final List<Throwable> doSave(@Nullable List<SaveSession> saveSessions, @NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles, @Nullable List<Throwable> errors) {
|
||||
ProjectImpl.UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, myProject);
|
||||
if (notifications.length > 0) {
|
||||
throw new SaveCancelledException();
|
||||
}
|
||||
|
||||
beforeSave(readonlyFiles);
|
||||
|
||||
super.doSave(saveSessions, readonlyFiles, errors);
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
ReadonlyStatusHandler.OperationStatus status;
|
||||
AccessToken token = ReadAction.start();
|
||||
try {
|
||||
status = ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(getFilesList(readonlyFiles));
|
||||
UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, myProject);
|
||||
if (readonlyFiles.isEmpty()) {
|
||||
if (notifications.length > 0) {
|
||||
for (UnableToSaveProjectNotification notification : notifications) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (notifications.length > 0) {
|
||||
throw new SaveCancelledException();
|
||||
}
|
||||
|
||||
ReadonlyStatusHandler.OperationStatus status;
|
||||
AccessToken token = ReadAction.start();
|
||||
try {
|
||||
status = ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(getFilesList(readonlyFiles));
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
|
||||
if (status.hasReadonlyFiles()) {
|
||||
dropUnableToSaveProjectNotification(myProject, status.getReadonlyFiles());
|
||||
throw new SaveCancelledException();
|
||||
}
|
||||
else {
|
||||
List<Pair<SaveSession, VirtualFile>> oldList = new ArrayList<Pair<SaveSession, VirtualFile>>(readonlyFiles);
|
||||
readonlyFiles.clear();
|
||||
for (Pair<SaveSession, VirtualFile> entry : oldList) {
|
||||
errors = executeSave(entry.first, readonlyFiles, errors);
|
||||
}
|
||||
|
||||
if (status.hasReadonlyFiles()) {
|
||||
ProjectImpl.dropUnableToSaveProjectNotification(myProject, status.getReadonlyFiles());
|
||||
if (errors != null) {
|
||||
CompoundRuntimeException.doThrow(errors);
|
||||
}
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
dropUnableToSaveProjectNotification(myProject, getFilesList(readonlyFiles));
|
||||
throw new SaveCancelledException();
|
||||
}
|
||||
else {
|
||||
List<Pair<SaveSession, VirtualFile>> oldList = new ArrayList<Pair<SaveSession, VirtualFile>>(readonlyFiles);
|
||||
readonlyFiles.clear();
|
||||
for (Pair<SaveSession, VirtualFile> entry : oldList) {
|
||||
errors = executeSave(entry.first, readonlyFiles, errors);
|
||||
}
|
||||
|
||||
if (errors != null) {
|
||||
CompoundRuntimeException.doThrow(errors);
|
||||
}
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
ProjectImpl.dropUnableToSaveProjectNotification(myProject, getFilesList(readonlyFiles));
|
||||
throw new SaveCancelledException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
private static void dropUnableToSaveProjectNotification(@NotNull Project project, @NotNull VirtualFile[] readOnlyFiles) {
|
||||
UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
|
||||
if (notifications.length == 0) {
|
||||
Notifications.Bus.notify(new UnableToSaveProjectNotification(project, readOnlyFiles), project);
|
||||
}
|
||||
else {
|
||||
notifications[0].myFiles = readOnlyFiles;
|
||||
}
|
||||
}
|
||||
|
||||
protected void beforeSave(@NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles) {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -19,7 +19,7 @@ import com.intellij.ide.RecentProjectsManager;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.ide.startup.StartupManagerEx;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.notification.NotificationsManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathMacros;
|
||||
import com.intellij.openapi.application.ex.ApplicationEx;
|
||||
@@ -54,9 +54,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.FrameTitleBuilder;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.TimedReference;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.pico.ConstructorInjectionComponentAdapter;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -65,7 +63,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.picocontainer.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -520,59 +517,4 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
|
||||
protected boolean logSlowComponents() {
|
||||
return super.logSlowComponents() || ApplicationInfoImpl.getShadowInstance().isEAP();
|
||||
}
|
||||
|
||||
public static void dropUnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
|
||||
final UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
|
||||
if (notifications.length == 0) {
|
||||
Notifications.Bus.notify(new UnableToSaveProjectNotification(project, readOnlyFiles), project);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnableToSaveProjectNotification extends Notification {
|
||||
private Project myProject;
|
||||
private final String[] myFileNames;
|
||||
|
||||
private UnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
|
||||
super("Project Settings", "Could not save project!", buildMessage(), NotificationType.ERROR, new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
final UnableToSaveProjectNotification unableToSaveProjectNotification = (UnableToSaveProjectNotification)notification;
|
||||
final Project _project = unableToSaveProjectNotification.getProject();
|
||||
notification.expire();
|
||||
|
||||
if (_project != null && !_project.isDisposed()) {
|
||||
_project.save();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myProject = project;
|
||||
myFileNames = ContainerUtil.map(readOnlyFiles, new Function<VirtualFile, String>() {
|
||||
@Override
|
||||
public String fun(VirtualFile file) {
|
||||
return file.getPresentableUrl();
|
||||
}
|
||||
}, new String[readOnlyFiles.length]);
|
||||
}
|
||||
|
||||
public String[] getFileNames() {
|
||||
return myFileNames;
|
||||
}
|
||||
|
||||
private static String buildMessage() {
|
||||
return "<p>Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
|
||||
" <a href=\"\">Try to save project again</a>.</p>";
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expire() {
|
||||
myProject = null;
|
||||
super.expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
-10
@@ -23,6 +23,9 @@ import com.intellij.ide.RecentProjectsManager;
|
||||
import com.intellij.ide.impl.ProjectUtil;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.NotificationsManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.*;
|
||||
@@ -42,7 +45,6 @@ import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
@@ -67,6 +69,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -976,17 +979,30 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean ensureCouldCloseIfUnableToSave(@NotNull final Project project) {
|
||||
final ProjectImpl.UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, project);
|
||||
if (notifications.length == 0) return true;
|
||||
private static boolean ensureCouldCloseIfUnableToSave(@NotNull Project project) {
|
||||
UnableToSaveProjectNotification[] notifications =
|
||||
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
|
||||
if (notifications.length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String fileNames = StringUtil.join(notifications[0].getFileNames(), "\n");
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(String.format("%s was unable to save some project files,\nare you sure you want to close this project anyway?",
|
||||
ApplicationNamesInfo.getInstance().getProductName()));
|
||||
|
||||
final String msg = String.format("%s was unable to save some project files,\nare you sure you want to close this project anyway?",
|
||||
ApplicationNamesInfo.getInstance().getProductName());
|
||||
return Messages.showDialog(project, msg, "Unsaved Project", "Read-only files:\n\n" + fileNames, new String[]{"Yes", "No"}, 0, 1,
|
||||
Messages.getWarningIcon()) == 0;
|
||||
message.append("\n\nRead-only files:\n");
|
||||
int count = 0;
|
||||
VirtualFile[] files = notifications[0].myFiles;
|
||||
for (VirtualFile file : files) {
|
||||
if (count == 10) {
|
||||
message.append('\n').append("and ").append(files.length - count).append(" more").append('\n');
|
||||
}
|
||||
else {
|
||||
message.append(file.getPath()).append('\n');
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return Messages.showYesNoDialog(project, message.toString(), "Unsaved Project", Messages.getWarningIcon()) == Messages.YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -1039,4 +1055,34 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
|
||||
public String getPresentableName() {
|
||||
return ProjectBundle.message("project.default.settings");
|
||||
}
|
||||
|
||||
public static class UnableToSaveProjectNotification extends Notification {
|
||||
private Project myProject;
|
||||
public VirtualFile[] myFiles;
|
||||
|
||||
public UnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
|
||||
super("Project Settings", "Could not save project", "Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
|
||||
" <a href=\"\">Try to save project again</a>.", NotificationType.ERROR, new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
final UnableToSaveProjectNotification unableToSaveProjectNotification = (UnableToSaveProjectNotification)notification;
|
||||
final Project _project = unableToSaveProjectNotification.myProject;
|
||||
notification.expire();
|
||||
|
||||
if (_project != null && !_project.isDisposed()) {
|
||||
_project.save();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myProject = project;
|
||||
myFiles = readOnlyFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expire() {
|
||||
myProject = null;
|
||||
super.expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user