diff --git a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java index 8cd863e7c545..847ca99e18f6 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java @@ -268,7 +268,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { contents.add(myContentFactory.createFromBytes(project, output, bytes)); } - return new BinaryMergeRequestImpl(outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); + return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); } catch (IOException e) { throw new InvalidDiffRequestException("Can't read from file", e); @@ -358,7 +358,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { byteContents.add(file.contentsToByteArray()); // TODO: we can read contents from file when needed } - return new BinaryMergeRequestImpl(outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); + return new BinaryMergeRequestImpl(project, outputContent, originalContent, contents, byteContents, title, contentTitles, applyCallback); } catch (IOException e) { throw new InvalidDiffRequestException("Can't read from file", e); diff --git a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java index dab137d1df73..3e0716f47750 100644 --- a/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java @@ -20,11 +20,13 @@ import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.FileContent; import com.intellij.diff.merge.BinaryMergeRequest; import com.intellij.diff.merge.MergeResult; +import com.intellij.diff.util.DiffUtil; import com.intellij.diff.util.ThreeSide; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +37,7 @@ import java.util.List; public class BinaryMergeRequestImpl extends BinaryMergeRequest { private static final Logger LOG = Logger.getInstance(BinaryMergeRequestImpl.class); + @Nullable private final Project myProject; @NotNull private final FileContent myFile; @NotNull private final List myContents; @@ -46,7 +49,8 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { @Nullable private final Consumer myApplyCallback; - public BinaryMergeRequestImpl(@NotNull FileContent file, + public BinaryMergeRequestImpl(@Nullable Project project, + @NotNull FileContent file, @NotNull byte[] originalContent, @NotNull List contents, @NotNull List byteContents, @@ -57,6 +61,7 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { assert contents.size() == 3; assert contentTitles.size() == 3; + myProject = project; myFile = file; myOriginalContent = originalContent; @@ -123,11 +128,13 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest { @Override protected void run() throws Throwable { try { - myFile.getFile().setBinaryContent(applyContent); + VirtualFile file = myFile.getFile(); + if (!DiffUtil.makeWritable(myProject, file)) throw new IOException("File is read-only: " + file.getPresentableName()); + file.setBinaryContent(applyContent); } catch (IOException e) { LOG.error(e); - Messages.showErrorDialog((Project)null, "Can't apply result", CommonBundle.getErrorTitle()); + Messages.showErrorDialog(myProject, "Can't apply result", CommonBundle.getErrorTitle()); } } }.execute(); diff --git a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java index 08a3a16d6516..0a3b245a3f7d 100644 --- a/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java @@ -18,8 +18,8 @@ package com.intellij.diff.requests; import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.merge.MergeResult; import com.intellij.diff.merge.TextMergeRequest; +import com.intellij.diff.util.DiffUtil; import com.intellij.diff.util.ThreeSide; -import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Consumer; @@ -108,12 +108,12 @@ public class TextMergeRequestImpl extends TextMergeRequest { } if (applyContent != null) { - new WriteCommandAction.Simple(myProject) { + DiffUtil.executeWriteCommand(myOutput.getDocument(), myProject, null, new Runnable() { @Override - protected void run() throws Throwable { + public void run() { myOutput.getDocument().setText(applyContent); } - }.execute(); + }); } if (myApplyCallback != null) myApplyCallback.consume(result); diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index 6e8f8ae5365f..7eba1ed668b7 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -744,7 +744,11 @@ public class DiffUtil { @CalledInAwt public final void run() { - if (!makeWritable(myProject, myDocument)) return; + if (!makeWritable(myProject, myDocument)) { + VirtualFile file = FileDocumentManager.getInstance().getFile(myDocument); + LOG.warn("Document is read-only" + (file != null ? ": " + file.getPresentableName() : "")); + return; + } ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { @@ -797,6 +801,13 @@ public class DiffUtil { return ReadonlyStatusHandler.ensureDocumentWritable(project, document); } + @CalledInAwt + public static boolean makeWritable(@Nullable Project project, @NotNull VirtualFile file) { + if (file.isWritable()) return true; + if (project == null) return false; + return ReadonlyStatusHandler.ensureFilesWritable(project, file); + } + // // Windows // diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java index cd251e5c09ba..a73108224977 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java @@ -22,7 +22,7 @@ import com.intellij.diff.DiffRequestFactory; import com.intellij.diff.InvalidDiffRequestException; import com.intellij.diff.merge.MergeRequest; import com.intellij.diff.merge.MergeResult; -import com.intellij.diff.merge.MergeWindow; +import com.intellij.diff.util.DiffUtil; import com.intellij.ide.presentation.VirtualFilePresentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -61,6 +61,7 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellRenderer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.IOException; import java.util.*; /** @@ -236,6 +237,9 @@ public class MultipleFileMergeDialog extends DialogWrapper { public void run() { try { if (!(myProvider instanceof MergeProvider2) || myMergeSession.canMerge(file)) { + if (!DiffUtil.makeWritable(myProject, file)) { + throw new IOException("File is read-only: " + file.getPresentableName()); + } MergeData data = myProvider.loadRevisions(file); if (isCurrent) { file.setBinaryContent(data.CURRENT);