merge: make file writable on applyLeft/applyRight
authorAleksey Pivovarov <aleksey.pivovarov@jetbrains.com>
Wed, 26 Aug 2015 12:09:31 +0000 (15:09 +0300)
committerAleksey Pivovarov <AMPivovarov@gmail.com>
Thu, 27 Aug 2015 10:41:42 +0000 (13:41 +0300)
platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java
platform/diff-impl/src/com/intellij/diff/requests/BinaryMergeRequestImpl.java
platform/diff-impl/src/com/intellij/diff/requests/TextMergeRequestImpl.java
platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java

index 8cd863e7c545c47e004e78b6663825e1832d0897..847ca99e18f64ac74a251bbbc9594fa1dce59a14 100644 (file)
@@ -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);
index dab137d1df731a93ed3b2a3341abe71accd87b08..3e0716f47750fd8907ca48ac43c1ccac5db6c130 100644 (file)
@@ -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<DiffContent> myContents;
 
@@ -46,7 +49,8 @@ public class BinaryMergeRequestImpl extends BinaryMergeRequest {
 
   @Nullable private final Consumer<MergeResult> myApplyCallback;
 
-  public BinaryMergeRequestImpl(@NotNull FileContent file,
+  public BinaryMergeRequestImpl(@Nullable Project project,
+                                @NotNull FileContent file,
                                 @NotNull byte[] originalContent,
                                 @NotNull List<DiffContent> contents,
                                 @NotNull List<byte[]> 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();
index 08a3a16d65168631c015c5aeff9935df7c91ecd3..0a3b245a3f7d969b0f1a1f67641a34b2e5dc897f 100644 (file)
@@ -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);
index 6e8f8ae5365fdeb44380c5ce6410fd084a52bbce..7eba1ed668b7f56411c2a983f01ddcc67229e662 100644 (file)
@@ -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
   //
index cd251e5c09ba2b173c647008b694e00d6fa24b41..a731082249771a104c2840b56b86b55443877de7 100644 (file)
@@ -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);