VCS: patch creation separated from patch application
authorirengrig <Irina.Chernushina@jetbrains.com>
Mon, 15 Mar 2010 15:45:51 +0000 (18:45 +0300)
committerirengrig <Irina.Chernushina@jetbrains.com>
Mon, 15 Mar 2010 15:45:51 +0000 (18:45 +0300)
25 files changed:
platform/lvcs-impl/testSrc/com/intellij/historyIntegrTests/PatchingTestCase.java
platform/util/src/com/intellij/openapi/diff/impl/patch/PatchLine.java [moved from platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/PatchLine.java with 100% similarity]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/BinaryFilePatch.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/FilePatch.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/PatchHunk.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/TextFilePatch.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryFilePatch.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryShelvedFilePatch.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatch.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchBase.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchFactory.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyTextFilePatch.java [new file with mode: 0644]
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/CustomBinaryPatchApplier.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PatchApplier.java
platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RevertCommittedStuffAbstractAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.form [deleted file]
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.java [deleted file]
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchForBaseRevisionTexts.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/LazyPatchContentRevision.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChange.java

index 6d89eb3df8856e83f3398de1d7affd37e263c83e..4b7be8efdcfd90f324fb0dc1f9a4c65db3407220 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.intellij.historyIntegrTests;
 
+import com.intellij.openapi.diff.impl.patch.BinaryFilePatch;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
 import com.intellij.openapi.diff.impl.patch.PatchReader;
 import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
@@ -52,6 +53,6 @@ public abstract class PatchingTestCase extends IntegrationTestCase {
       patches.add(p);
     }
 
-    new PatchApplier(myProject, root, patches, null, null).execute();
+    new PatchApplier<BinaryFilePatch>(myProject, root, patches, null, null).execute();
   }
 }
index 31ee275760f84495dd53d6db1bbe569075aa526e..6fe7ff86f336191b1d4579d8c765e0d776bcbc52 100644 (file)
  */
 package com.intellij.openapi.diff.impl.patch;
 
-import com.intellij.openapi.vfs.VirtualFile;
-
-import java.io.IOException;
-
 /**
  * @author yole
  */
@@ -31,15 +27,6 @@ public class BinaryFilePatch extends FilePatch {
     myAfterContent = afterContent;
   }
 
-  protected void applyCreate(final VirtualFile newFile) throws IOException, ApplyPatchException {
-    newFile.setBinaryContent(myAfterContent);
-  }
-
-  protected ApplyPatchStatus applyChange(final VirtualFile fileToPatch) throws IOException, ApplyPatchException {
-    fileToPatch.setBinaryContent(myAfterContent);
-    return ApplyPatchStatus.SUCCESS;
-  }
-
   public boolean isNewFile() {
     return myBeforeContent == null;
   }
@@ -47,4 +34,8 @@ public class BinaryFilePatch extends FilePatch {
   public boolean isDeletedFile() {
     return myAfterContent == null;
   }
+
+  public byte[] getAfterContent() {
+    return myAfterContent;
+  }
 }
index d33a87f8c2923dcf20ed5b294b77b357a6466662..b1f8fb3dd621ddcb440765079a6019cc2e337a62 100644 (file)
  */
 package com.intellij.openapi.diff.impl.patch;
 
-import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FilePathImpl;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.IOException;
 
 public abstract class FilePatch {
   private String myBeforeName;
@@ -86,137 +77,6 @@ public abstract class FilePatch {
     return StringUtil.join(components, skipDirs, components.length, "/");
   }
 
-  public FilePath getTarget(final VirtualFile file) {
-    if (isNewFile()) {
-      return new FilePathImpl(file, getBeforeFileName(), false);
-    }
-    return new FilePathImpl(file);
-  }
-
-  public ApplyPatchStatus apply(final VirtualFile fileToPatch, final ApplyPatchContext context, final Project project) throws IOException, ApplyPatchException {
-    context.addAffectedFile(getTarget(fileToPatch));
-    return applyImpl(fileToPatch, project);
-  }
-
-  public ApplyPatchStatus applyImpl(final VirtualFile fileToPatch, final Project project) throws IOException, ApplyPatchException {
-    if (isNewFile()) {
-      applyCreate(fileToPatch);
-    }
-    else if (isDeletedFile()) {
-      FileEditorManagerImpl.getInstance(project).closeFile(fileToPatch);
-      fileToPatch.delete(this);
-    }
-    else {
-      return applyChange(fileToPatch);
-    }
-    return ApplyPatchStatus.SUCCESS;
-  }
-
-  protected abstract void applyCreate(VirtualFile newFile) throws IOException, ApplyPatchException;
-  protected abstract ApplyPatchStatus applyChange(VirtualFile fileToPatch) throws IOException, ApplyPatchException;
-
-  @Nullable
-  public VirtualFile findFileToPatch(@NotNull ApplyPatchContext context) throws IOException {
-    return findPatchTarget(context, myBeforeName, myAfterName, isNewFile());
-  }
-
-  @Nullable
-  public static VirtualFile findPatchTarget(final ApplyPatchContext context, final String beforeName, final String afterName,
-                                            final boolean isNewFile) throws IOException {
-    VirtualFile file = null;
-    if (beforeName != null) {
-      file = findFileToPatchByName(context, beforeName, isNewFile);
-    }
-    if (file == null) {
-      file = findFileToPatchByName(context, afterName, isNewFile);
-    }
-    else if (context.isAllowRename() && afterName != null && !beforeName.equals(afterName)) {
-      String[] beforeNameComponents = beforeName.split("/");
-      String[] afterNameComponents = afterName.split("/");
-      if (!beforeNameComponents [beforeNameComponents.length-1].equals(afterNameComponents [afterNameComponents.length-1])) {
-        context.registerBeforeRename(file);
-        file.rename(FilePatch.class, afterNameComponents [afterNameComponents.length-1]);
-        context.addAffectedFile(file);
-      }
-      boolean needMove = (beforeNameComponents.length != afterNameComponents.length);
-      if (!needMove) {
-        needMove = checkPackageRename(context, beforeNameComponents, afterNameComponents);
-      }
-      if (needMove) {
-        VirtualFile moveTarget = findFileToPatchByComponents(context, afterNameComponents, afterNameComponents.length-1);
-        if (moveTarget == null) {
-          return null;
-        }
-        context.registerBeforeRename(file);
-        file.move(FilePatch.class, moveTarget);
-        context.addAffectedFile(file);
-      }
-    }
-    return file;
-  }
-
-  private static boolean checkPackageRename(final ApplyPatchContext context,
-                                            final String[] beforeNameComponents,
-                                            final String[] afterNameComponents) {
-    int changedIndex = -1;
-    for(int i=context.getSkipTopDirs(); i<afterNameComponents.length-1; i++) {
-      if (!beforeNameComponents [i].equals(afterNameComponents [i])) {
-        if (changedIndex != -1) {
-          return true;
-        }
-        changedIndex = i;
-      }
-    }
-    if (changedIndex == -1) return false;
-    VirtualFile oldDir = findFileToPatchByComponents(context, beforeNameComponents, changedIndex+1);
-    VirtualFile newDir = findFileToPatchByComponents(context.getPrepareContext(), afterNameComponents, changedIndex+1);
-    if (oldDir != null && newDir == null) {
-      context.addPendingRename(oldDir, afterNameComponents [changedIndex]);
-      return false;
-    }
-    return true;
-  }
-
-  @Nullable
-  private static VirtualFile findFileToPatchByName(@NotNull ApplyPatchContext context, final String fileName,
-                                                   boolean isNewFile) {
-    String[] pathNameComponents = fileName.split("/");
-    int lastComponentToFind = isNewFile ? pathNameComponents.length-1 : pathNameComponents.length;
-    return findFileToPatchByComponents(context, pathNameComponents, lastComponentToFind);
-  }
-
-  @Nullable
-  private static VirtualFile findFileToPatchByComponents(ApplyPatchContext context,
-                                                         final String[] pathNameComponents,
-                                                         final int lastComponentToFind) {
-    VirtualFile patchedDir = context.getBaseDir();
-    for(int i=context.getSkipTopDirs(); i<lastComponentToFind; i++) {
-      VirtualFile nextChild;
-      if (pathNameComponents [i].equals("..")) {
-        nextChild = patchedDir.getParent();
-      }
-      else {
-        nextChild = patchedDir.findChild(pathNameComponents [i]);
-      }
-      if (nextChild == null) {
-        if (context.isCreateDirectories()) {
-          try {
-            nextChild = patchedDir.createChildDirectory(null, pathNameComponents [i]);
-          }
-          catch (IOException e) {
-            return null;
-          }
-        }
-        else {
-          context.registerMissingDirectory(patchedDir, pathNameComponents, i);
-          return null;
-        }
-      }
-      patchedDir = nextChild;
-    }
-    return patchedDir;
-  }
-
   public abstract boolean isNewFile();
 
   public abstract boolean isDeletedFile();
index 056bfc069b12596b5c7ea07474481966342ba026..a899bee960bd062120ee2f5c7ab8585791e3986b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2010 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.
index 502bac91a5540b7eabecea00d5dddb1df98c4d4e..e92baf5dd8d23c3c7cd38993dd40ae6dc725971b 100644 (file)
  */
 package com.intellij.openapi.diff.impl.patch;
 
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.text.LineTokenizer;
-
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.io.IOException;
+import java.util.List;
 
 /**
  * @author yole
@@ -56,50 +49,6 @@ public class TextFilePatch extends FilePatch {
     return new TextFilePatch(this);
   }
 
-  protected ApplyPatchStatus applyChange(final VirtualFile fileToPatch) throws IOException, ApplyPatchException {
-    byte[] fileContents = fileToPatch.contentsToByteArray();
-    CharSequence text = LoadTextUtil.getTextByBinaryPresentation(fileContents, fileToPatch);
-    StringBuilder newText = new StringBuilder();
-    ApplyPatchStatus status = applyModifications(text, newText);
-    if (status != ApplyPatchStatus.ALREADY_APPLIED) {
-      final Document document = FileDocumentManager.getInstance().getDocument(fileToPatch);
-      if (document == null) {
-        throw new ApplyPatchException("Failed to set contents for updated file " + fileToPatch.getPath());
-      }
-      document.setText(newText.toString());
-      FileDocumentManager.getInstance().saveDocument(document);
-    }
-    return status;
-  }
-
-  public ApplyPatchStatus applyModifications(final CharSequence text, final StringBuilder newText) throws ApplyPatchException {
-    if (myHunks.size() == 0) {
-      return ApplyPatchStatus.SUCCESS;
-    }
-    List<String> lines = new ArrayList<String>();
-    Collections.addAll(lines, LineTokenizer.tokenize(text, false));
-    ApplyPatchStatus result = null;
-    for(PatchHunk hunk: myHunks) {
-      result = ApplyPatchStatus.and(result, hunk.apply(lines));
-    }
-    for(int i=0; i<lines.size(); i++) {
-      newText.append(lines.get(i));
-      if (i < lines.size()-1 || !myHunks.get(myHunks.size()-1).isNoNewLineAtEnd()) {
-        newText.append("\n");
-      }
-    }
-    return result;
-  }
-
-  protected void applyCreate(final VirtualFile newFile) throws IOException, ApplyPatchException {
-    final Document document = FileDocumentManager.getInstance().getDocument(newFile);
-    if (document == null) {
-      throw new ApplyPatchException("Failed to set contents for new file " + newFile.getPath());
-    }
-    document.setText(getNewFileText());
-    FileDocumentManager.getInstance().saveDocument(document);
-  }
-
   public boolean isNewFile() {
     return myHunks.size() == 1 && myHunks.get(0).isNewContent();
   }
index 42c364104b0106eb87be7a98a03298c4426363ce..27be1b147901c42dfcefe5d0ccd70101570ed451 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2010 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.
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryFilePatch.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryFilePatch.java
new file mode 100644 (file)
index 0000000..a1121fc
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
+import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
+import com.intellij.openapi.diff.impl.patch.BinaryFilePatch;
+import com.intellij.openapi.vfs.VirtualFile;
+
+import java.io.IOException;
+
+public class ApplyBinaryFilePatch extends ApplyFilePatchBase<BinaryFilePatch> {
+  public ApplyBinaryFilePatch(BinaryFilePatch patch) {
+    super(patch);
+  }
+
+  protected void applyCreate(final VirtualFile newFile) throws IOException, ApplyPatchException {
+    newFile.setBinaryContent(myPatch.getAfterContent());
+  }
+
+  protected ApplyPatchStatus applyChange(final VirtualFile fileToPatch) throws IOException, ApplyPatchException {
+    fileToPatch.setBinaryContent(myPatch.getAfterContent());
+    return ApplyPatchStatus.SUCCESS;
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryShelvedFilePatch.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyBinaryShelvedFilePatch.java
new file mode 100644 (file)
index 0000000..076cf64
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
+import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
+import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
+import com.intellij.openapi.vfs.VirtualFile;
+
+import java.io.IOException;
+
+public class ApplyBinaryShelvedFilePatch extends ApplyFilePatchBase<ShelveChangesManager.ShelvedBinaryFilePatch> {
+  public ApplyBinaryShelvedFilePatch(ShelveChangesManager.ShelvedBinaryFilePatch patch) {
+    super(patch);
+  }
+
+  @Override
+  protected ApplyPatchStatus applyChange(VirtualFile fileToPatch) throws IOException, ApplyPatchException {
+    return null;
+  }
+
+  @Override
+  protected void applyCreate(VirtualFile newFile) throws IOException, ApplyPatchException {
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatch.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatch.java
new file mode 100644 (file)
index 0000000..03e8a56
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.ApplyPatchContext;
+import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
+import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+
+public interface ApplyFilePatch {
+  ApplyPatchStatus apply(VirtualFile fileToPatch, ApplyPatchContext context, Project project) throws IOException, ApplyPatchException;
+
+  ApplyPatchStatus applyImpl(VirtualFile fileToPatch, Project project) throws IOException, ApplyPatchException;
+
+  @Nullable
+  VirtualFile findFileToPatch(@NotNull ApplyPatchContext context) throws IOException;
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchBase.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchBase.java
new file mode 100644 (file)
index 0000000..0b368a9
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.*;
+import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.LineTokenizer;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.FilePathImpl;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class ApplyFilePatchBase<T extends FilePatch> implements ApplyFilePatch {
+  protected final T myPatch;
+
+  public ApplyFilePatchBase(T patch) {
+    myPatch = patch;
+  }
+
+  public T getPatch() {
+    return myPatch;
+  }
+
+  private FilePath getTarget(final VirtualFile file) {
+    if (myPatch.isNewFile()) {
+      return new FilePathImpl(file, myPatch.getBeforeFileName(), false);
+    }
+    return new FilePathImpl(file);
+  }
+
+  public ApplyPatchStatus apply(final VirtualFile fileToPatch, final ApplyPatchContext context, final Project project) throws
+                                                                                                                       IOException, ApplyPatchException {
+    context.addAffectedFile(getTarget(fileToPatch));
+    return applyImpl(fileToPatch, project);
+  }
+
+  public ApplyPatchStatus applyImpl(final VirtualFile fileToPatch, final Project project) throws IOException, ApplyPatchException {
+    if (myPatch.isNewFile()) {
+      applyCreate(fileToPatch);
+    }
+    else if (myPatch.isDeletedFile()) {
+      FileEditorManagerImpl.getInstance(project).closeFile(fileToPatch);
+      fileToPatch.delete(this);
+    }
+    else {
+      return applyChange(fileToPatch);
+    }
+    return ApplyPatchStatus.SUCCESS;
+  }
+
+  protected abstract void applyCreate(VirtualFile newFile) throws IOException, ApplyPatchException;
+  @Nullable
+  protected abstract ApplyPatchStatus applyChange(VirtualFile fileToPatch) throws IOException, ApplyPatchException;
+
+  @Nullable
+  public VirtualFile findFileToPatch(@NotNull ApplyPatchContext context) throws IOException {
+    return findPatchTarget(context, myPatch.getBeforeName(), myPatch.getAfterName(), myPatch.isNewFile());
+  }
+
+  @Nullable
+  public static VirtualFile findPatchTarget(final ApplyPatchContext context, final String beforeName, final String afterName,
+                                            final boolean isNewFile) throws IOException {
+    VirtualFile file = null;
+    if (beforeName != null) {
+      file = findFileToPatchByName(context, beforeName, isNewFile);
+    }
+    if (file == null) {
+      file = findFileToPatchByName(context, afterName, isNewFile);
+    }
+    else if (context.isAllowRename() && afterName != null && !beforeName.equals(afterName)) {
+      String[] beforeNameComponents = beforeName.split("/");
+      String[] afterNameComponents = afterName.split("/");
+      if (!beforeNameComponents [beforeNameComponents.length-1].equals(afterNameComponents [afterNameComponents.length-1])) {
+        context.registerBeforeRename(file);
+        file.rename(FilePatch.class, afterNameComponents [afterNameComponents.length-1]);
+        context.addAffectedFile(file);
+      }
+      boolean needMove = (beforeNameComponents.length != afterNameComponents.length);
+      if (!needMove) {
+        needMove = checkPackageRename(context, beforeNameComponents, afterNameComponents);
+      }
+      if (needMove) {
+        VirtualFile moveTarget = findFileToPatchByComponents(context, afterNameComponents, afterNameComponents.length-1);
+        if (moveTarget == null) {
+          return null;
+        }
+        context.registerBeforeRename(file);
+        file.move(FilePatch.class, moveTarget);
+        context.addAffectedFile(file);
+      }
+    }
+    return file;
+  }
+
+  private static boolean checkPackageRename(final ApplyPatchContext context,
+                                            final String[] beforeNameComponents,
+                                            final String[] afterNameComponents) {
+    int changedIndex = -1;
+    for(int i=context.getSkipTopDirs(); i<afterNameComponents.length-1; i++) {
+      if (!beforeNameComponents [i].equals(afterNameComponents [i])) {
+        if (changedIndex != -1) {
+          return true;
+        }
+        changedIndex = i;
+      }
+    }
+    if (changedIndex == -1) return false;
+    VirtualFile oldDir = findFileToPatchByComponents(context, beforeNameComponents, changedIndex+1);
+    VirtualFile newDir = findFileToPatchByComponents(context.getPrepareContext(), afterNameComponents, changedIndex+1);
+    if (oldDir != null && newDir == null) {
+      context.addPendingRename(oldDir, afterNameComponents [changedIndex]);
+      return false;
+    }
+    return true;
+  }
+
+  @Nullable
+  private static VirtualFile findFileToPatchByName(@NotNull ApplyPatchContext context, final String fileName,
+                                                   boolean isNewFile) {
+    String[] pathNameComponents = fileName.split("/");
+    int lastComponentToFind = isNewFile ? pathNameComponents.length-1 : pathNameComponents.length;
+    return findFileToPatchByComponents(context, pathNameComponents, lastComponentToFind);
+  }
+
+  @Nullable
+  private static VirtualFile findFileToPatchByComponents(ApplyPatchContext context,
+                                                         final String[] pathNameComponents,
+                                                         final int lastComponentToFind) {
+    VirtualFile patchedDir = context.getBaseDir();
+    for(int i=context.getSkipTopDirs(); i<lastComponentToFind; i++) {
+      VirtualFile nextChild;
+      if (pathNameComponents [i].equals("..")) {
+        nextChild = patchedDir.getParent();
+      }
+      else {
+        nextChild = patchedDir.findChild(pathNameComponents [i]);
+      }
+      if (nextChild == null) {
+        if (context.isCreateDirectories()) {
+          try {
+            nextChild = patchedDir.createChildDirectory(null, pathNameComponents [i]);
+          }
+          catch (IOException e) {
+            return null;
+          }
+        }
+        else {
+          context.registerMissingDirectory(patchedDir, pathNameComponents, i);
+          return null;
+        }
+      }
+      patchedDir = nextChild;
+    }
+    return patchedDir;
+  }
+
+  // todo move somewhere?
+  @Nullable
+  public static ApplyPatchStatus applyModifications(final TextFilePatch patch, final CharSequence text, final StringBuilder newText) throws
+                                                                                                                                     ApplyPatchException {
+    final List<PatchHunk> hunks = patch.getHunks();
+    if (hunks.isEmpty()) {
+      return ApplyPatchStatus.SUCCESS;
+    }
+    List<String> lines = new ArrayList<String>();
+    Collections.addAll(lines, LineTokenizer.tokenize(text, false));
+    ApplyPatchStatus result = null;
+    for(PatchHunk hunk: hunks) {
+      result = ApplyPatchStatus.and(result, hunk.apply(lines));
+    }
+    for(int i=0; i<lines.size(); i++) {
+      newText.append(lines.get(i));
+      if (i < lines.size()-1 || !hunks.get(hunks.size()-1).isNoNewLineAtEnd()) {
+        newText.append("\n");
+      }
+    }
+    return result;
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchFactory.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyFilePatchFactory.java
new file mode 100644 (file)
index 0000000..79bd535
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.BinaryFilePatch;
+import com.intellij.openapi.diff.impl.patch.FilePatch;
+import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
+
+public class ApplyFilePatchFactory {
+  private ApplyFilePatchFactory() {
+  }
+
+  public static ApplyTextFilePatch create(final TextFilePatch patch) {
+    return new ApplyTextFilePatch(patch);
+  }
+
+  public static ApplyBinaryFilePatch create(final BinaryFilePatch patch) {
+    return new ApplyBinaryFilePatch(patch);
+  }
+
+  public static ApplyBinaryShelvedFilePatch create(final ShelveChangesManager.ShelvedBinaryFilePatch patch) {
+    return new ApplyBinaryShelvedFilePatch(patch);
+  }
+
+  public static ApplyFilePatchBase createGeneral(final FilePatch patch) {
+    if (patch instanceof TextFilePatch) {
+      return create((TextFilePatch) patch);
+    } else if (patch instanceof BinaryFilePatch) {
+      return create((BinaryFilePatch) patch);
+    } else if (patch instanceof ShelveChangesManager.ShelvedBinaryFilePatch) {
+      return create((ShelveChangesManager.ShelvedBinaryFilePatch) patch);
+    }
+    throw new IllegalStateException();
+  }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyTextFilePatch.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/ApplyTextFilePatch.java
new file mode 100644 (file)
index 0000000..0fb9298
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.patch.apply;
+
+import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
+import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
+import com.intellij.openapi.diff.impl.patch.PatchHunk;
+import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.util.text.LineTokenizer;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ApplyTextFilePatch extends ApplyFilePatchBase<TextFilePatch> {
+  public ApplyTextFilePatch(final TextFilePatch patch) {
+    super(patch);
+  }
+
+  @Nullable
+  protected ApplyPatchStatus applyChange(final VirtualFile fileToPatch) throws IOException, ApplyPatchException {
+    byte[] fileContents = fileToPatch.contentsToByteArray();
+    CharSequence text = LoadTextUtil.getTextByBinaryPresentation(fileContents, fileToPatch);
+    StringBuilder newText = new StringBuilder();
+    ApplyPatchStatus status = applyModifications(text, newText);
+    if (status != ApplyPatchStatus.ALREADY_APPLIED) {
+      final Document document = FileDocumentManager.getInstance().getDocument(fileToPatch);
+      if (document == null) {
+        throw new ApplyPatchException("Failed to set contents for updated file " + fileToPatch.getPath());
+      }
+      document.setText(newText.toString());
+      FileDocumentManager.getInstance().saveDocument(document);
+    }
+    return status;
+  }
+
+  // todo taken to another place also, cheeeeeck
+  @Nullable
+  public ApplyPatchStatus applyModifications(final CharSequence text, final StringBuilder newText) throws ApplyPatchException {
+    final List<PatchHunk> hunks = myPatch.getHunks();
+    if (hunks.size() == 0) {
+      return ApplyPatchStatus.SUCCESS;
+    }
+    List<String> lines = new ArrayList<String>();
+    Collections.addAll(lines, LineTokenizer.tokenize(text, false));
+    ApplyPatchStatus result = null;
+    for(PatchHunk hunk: hunks) {
+      result = ApplyPatchStatus.and(result, hunk.apply(lines));
+    }
+    for(int i=0; i<lines.size(); i++) {
+      newText.append(lines.get(i));
+      if (i < lines.size()-1 || !hunks.get(hunks.size()-1).isNoNewLineAtEnd()) {
+        newText.append("\n");
+      }
+    }
+    return result;
+  }
+
+  protected void applyCreate(final VirtualFile newFile) throws IOException, ApplyPatchException {
+    final Document document = FileDocumentManager.getInstance().getDocument(newFile);
+    if (document == null) {
+      throw new ApplyPatchException("Failed to set contents for new file " + newFile.getPath());
+    }
+    document.setText(myPatch.getNewFileText());
+    FileDocumentManager.getInstance().saveDocument(document);
+  }
+}
index cdbcfe35f13b88bf686df81f29b84431b5ab53ee..fc735ac8924f80b8a9dd0075509de11926dff604 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.openapi.diff.impl.patch.formove;
 
 import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
@@ -24,9 +25,9 @@ import org.jetbrains.annotations.NotNull;
 import java.io.IOException;
 import java.util.List;
 
-public interface CustomBinaryPatchApplier {
+public interface CustomBinaryPatchApplier<T extends FilePatch> {
   @NotNull
-  ApplyPatchStatus apply(List<Pair<VirtualFile, FilePatch>> patches) throws IOException;
+  ApplyPatchStatus apply(List<Pair<VirtualFile, ApplyFilePatchBase<T>>> patches) throws IOException;
   @NotNull
   List<FilePatch> getAppliedPatches();
 }
index eaa713eb261b7eec2f0daa06bc5ec99e9f23b1b7..7ff2c143a0a0c5e45a7a891adedfe2f465511457 100644 (file)
@@ -21,6 +21,8 @@ import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.diff.impl.patch.ApplyPatchContext;
 import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyTextFilePatch;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
@@ -52,25 +54,25 @@ import java.util.List;
 /**
  * for patches. for shelve.
  */
-public class PatchApplier {
+public class PatchApplier<BinaryType extends FilePatch> {
   private final Project myProject;
   private final VirtualFile myBaseDirectory;
   private final List<FilePatch> myPatches;
-  private final CustomBinaryPatchApplier myCustomForBinaries;
+  private final CustomBinaryPatchApplier<BinaryType> myCustomForBinaries;
   private final LocalChangeList myTargetChangeList;
 
   private final List<FilePatch> myRemainingPatches;
-  private final PathsVerifier myVerifier;
+  private final PathsVerifier<BinaryType> myVerifier;
 
   public PatchApplier(final Project project, final VirtualFile baseDirectory, final List<FilePatch> patches,
-                      final LocalChangeList targetChangeList, final CustomBinaryPatchApplier customForBinaries) {
+                      final LocalChangeList targetChangeList, final CustomBinaryPatchApplier<BinaryType> customForBinaries) {
     myProject = project;
     myBaseDirectory = baseDirectory;
     myPatches = patches;
     myTargetChangeList = targetChangeList;
     myCustomForBinaries = customForBinaries;
     myRemainingPatches = new ArrayList<FilePatch>();
-    myVerifier = new PathsVerifier(myProject, myBaseDirectory, myPatches, new PathsVerifier.BaseMapper() {
+    myVerifier = new PathsVerifier<BinaryType>(myProject, myBaseDirectory, myPatches, new PathsVerifier.BaseMapper() {
       @Nullable
       public VirtualFile getFile(FilePatch patch, String path) {
         return PathMerger.getFile(myBaseDirectory, path);
@@ -137,7 +139,7 @@ public class PatchApplier {
               return;
             }
 
-            final List<Pair<VirtualFile, FilePatch>> textPatches = myVerifier.getTextPatches();
+            final List<Pair<VirtualFile, ApplyTextFilePatch>> textPatches = myVerifier.getTextPatches();
             if (! fileTypesAreOk(textPatches)) {
               return;
             }
@@ -184,8 +186,8 @@ public class PatchApplier {
   }
 
   @Nullable
-  private ApplyPatchStatus actualApply(final PathsVerifier verifier) {
-    final List<Pair<VirtualFile, FilePatch>> textPatches = verifier.getTextPatches();
+  private ApplyPatchStatus actualApply(final PathsVerifier<BinaryType> verifier) {
+    final List<Pair<VirtualFile, ApplyTextFilePatch>> textPatches = verifier.getTextPatches();
     final ApplyPatchContext context = new ApplyPatchContext(myBaseDirectory, 0, true, true);
     ApplyPatchStatus status = null;
 
@@ -195,7 +197,7 @@ public class PatchApplier {
       if (myCustomForBinaries == null) {
         status = applyList(verifier.getBinaryPatches(), context, status);
       } else {
-        final List<Pair<VirtualFile, FilePatch>> binaryPatches = verifier.getBinaryPatches();
+        final List<Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>> binaryPatches = verifier.getBinaryPatches();
         ApplyPatchStatus patchStatus = myCustomForBinaries.apply(binaryPatches);
         final List<FilePatch> appliedPatches = myCustomForBinaries.getAppliedPatches();
         moveForCustomBinaries(binaryPatches, appliedPatches);
@@ -211,24 +213,24 @@ public class PatchApplier {
     return status;
   }
 
-  private void moveForCustomBinaries(final List<Pair<VirtualFile, FilePatch>> patches,
+  private void moveForCustomBinaries(final List<Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>> patches,
                                      final List<FilePatch> appliedPatches) throws IOException {
-    for (Pair<VirtualFile, FilePatch> patch : patches) {
-      if (appliedPatches.contains(patch.getSecond())) {
+    for (Pair<VirtualFile, ApplyFilePatchBase<BinaryType>> patch : patches) {
+      if (appliedPatches.contains(patch.getSecond().getPatch())) {
         myVerifier.doMoveIfNeeded(patch.getFirst());
       }
     }
   }
 
-  private ApplyPatchStatus applyList(final List<Pair<VirtualFile, FilePatch>> patches, final ApplyPatchContext context,
+  private <V extends FilePatch, T extends ApplyFilePatchBase<V>> ApplyPatchStatus applyList(final List<Pair<VirtualFile, T>> patches, final ApplyPatchContext context,
                                      ApplyPatchStatus status) throws IOException {
-    for (Pair<VirtualFile, FilePatch> patch : patches) {
+    for (Pair<VirtualFile, T> patch : patches) {
       ApplyPatchStatus patchStatus = ApplyPatchAction.applyOnly(myProject, patch.getSecond(), context, patch.getFirst());
       myVerifier.doMoveIfNeeded(patch.getFirst());
 
       status = ApplyPatchStatus.and(status, patchStatus);
       if (patchStatus != ApplyPatchStatus.FAILURE) {
-        myRemainingPatches.remove(patch.getSecond());
+        myRemainingPatches.remove(patch.getSecond().getPatch());
       } else {
         // interrupt if failure
         return status;
@@ -259,8 +261,8 @@ public class PatchApplier {
     return (! readonlyStatus.hasReadonlyFiles());
   }
 
-  private boolean fileTypesAreOk(final List<Pair<VirtualFile, FilePatch>> textPatches) {
-    for (Pair<VirtualFile, FilePatch> textPatch : textPatches) {
+  private boolean fileTypesAreOk(final List<Pair<VirtualFile, ApplyTextFilePatch>> textPatches) {
+    for (Pair<VirtualFile, ApplyTextFilePatch> textPatch : textPatches) {
       final VirtualFile file = textPatch.getFirst();
       if (! file.isDirectory()) {
         FileType fileType = file.getFileType();
index c5bf4a99724ca39e9e863049173205c9792afbfe..d2d57c6ac303ce4c0397e4dea6f808113b361ce9 100644 (file)
  */
 package com.intellij.openapi.diff.impl.patch.formove;
 
+import com.intellij.openapi.diff.impl.patch.BinaryFilePatch;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
 import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchFactory;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyTextFilePatch;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Pair;
@@ -25,6 +29,7 @@ import com.intellij.openapi.vcs.FilePathImpl;
 import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsBundle;
 import com.intellij.openapi.vcs.changes.patch.RelativePathCalculator;
+import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
 import com.intellij.openapi.vcs.impl.ExcludedFileIndex;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -34,7 +39,7 @@ import org.jetbrains.annotations.Nullable;
 import java.io.IOException;
 import java.util.*;
 
-public class PathsVerifier {
+public class PathsVerifier<BinaryType extends FilePatch> {
   // in
   private final Project myProject;
   private final VirtualFile myBaseDirectory;
@@ -44,8 +49,8 @@ public class PathsVerifier {
   private final List<FilePath> myBeforePaths;
   private final List<VirtualFile> myCreatedDirectories;
   // out
-  private final List<Pair<VirtualFile, FilePatch>> myTextPatches;
-  private final List<Pair<VirtualFile, FilePatch>> myBinaryPatches;
+  private final List<Pair<VirtualFile, ApplyTextFilePatch>> myTextPatches;
+  private final List<Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>> myBinaryPatches;
   private final List<VirtualFile> myWritableFiles;
   private final BaseMapper myBaseMapper;
 
@@ -58,8 +63,8 @@ public class PathsVerifier {
     myMovedFiles = new HashMap<VirtualFile, MovedFileData>();
     myBeforePaths = new ArrayList<FilePath>();
     myCreatedDirectories = new ArrayList<VirtualFile>();
-    myTextPatches = new ArrayList<Pair<VirtualFile,FilePatch>>();
-    myBinaryPatches = new ArrayList<Pair<VirtualFile,FilePatch>>();
+    myTextPatches = new ArrayList<Pair<VirtualFile, ApplyTextFilePatch>>();
+    myBinaryPatches = new ArrayList<Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>>();
     myWritableFiles = new ArrayList<VirtualFile>();
   }
 
@@ -284,11 +289,14 @@ public class PathsVerifier {
   }
 
   private void addPatch(final FilePatch patch, final VirtualFile file) {
-    final Pair<VirtualFile, FilePatch> patchPair = new Pair<VirtualFile, FilePatch>(file, patch);
+    final Pair<VirtualFile, ApplyFilePatchBase> patchPair = new Pair<VirtualFile, ApplyFilePatchBase>(file, ApplyFilePatchFactory.createGeneral(patch));
     if (patch instanceof TextFilePatch) {
-      myTextPatches.add(patchPair);
+      myTextPatches.add(new Pair<VirtualFile, ApplyTextFilePatch>(file, ApplyFilePatchFactory.create((TextFilePatch) patch)));
     } else {
-      myBinaryPatches.add(patchPair);
+      final ApplyFilePatchBase<BinaryType> applyBinaryPatch = (ApplyFilePatchBase<BinaryType>) ((patch instanceof BinaryFilePatch) ? ApplyFilePatchFactory
+        .create((BinaryFilePatch) patch) :
+              ApplyFilePatchFactory.create((ShelveChangesManager.ShelvedBinaryFilePatch) patch));
+      myBinaryPatches.add(new Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>(file, applyBinaryPatch));
     }
     myWritableFiles.add(file);
   }
@@ -410,11 +418,11 @@ public class PathsVerifier {
     return child;
   }
 
-  public List<Pair<VirtualFile, FilePatch>> getTextPatches() {
+  public List<Pair<VirtualFile, ApplyTextFilePatch>> getTextPatches() {
     return myTextPatches;
   }
 
-  public List<Pair<VirtualFile, FilePatch>> getBinaryPatches() {
+  public List<Pair<VirtualFile, ApplyFilePatchBase<BinaryType>>> getBinaryPatches() {
     return myBinaryPatches;
   }
 
index fc17779c474269ae670da5c541638b12c034f1db..d953a1650c710d9c8ab0035bcaf09a9aa453c481 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.actions;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.diff.impl.patch.BinaryFilePatch;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
 import com.intellij.openapi.diff.impl.patch.TextPatchBuilder;
 import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
@@ -76,7 +77,7 @@ abstract class RevertCommittedStuffAbstractAction extends AnAction implements Du
       Messages.showErrorDialog(project, "Failed to revert changes: " + ex.getMessage(), VcsBundle.message("revert.changes.title"));
       return;
     }
-    new PatchApplier(project, baseDir, patches, chooser.getSelectedList(), null).execute();
+    new PatchApplier<BinaryFilePatch>(project, baseDir, patches, chooser.getSelectedList(), null).execute();
   }
 
   public void update(final AnActionEvent e) {
index c96dacad91377f3adf43d5f9a0bd2bc1ceb85d39..353b5223ce4f9362b23c2e23022ffbaf1b53f3e0 100644 (file)
@@ -32,6 +32,7 @@ import com.intellij.openapi.diff.DiffManager;
 import com.intellij.openapi.diff.DiffRequestFactory;
 import com.intellij.openapi.diff.MergeRequest;
 import com.intellij.openapi.diff.impl.patch.*;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
@@ -72,7 +73,7 @@ public class ApplyPatchAction extends AnAction {
         final Collection<PatchApplier> appliers = new LinkedList<PatchApplier>();
         for (VirtualFile base : patchGroups.keySet()) {
           final PatchApplier patchApplier =
-            new PatchApplier(project, base, ObjectsConvertor.convert(patchGroups.get(base), new Convertor<FilePatchInProgress, FilePatch>() {
+            new PatchApplier<BinaryFilePatch>(project, base, ObjectsConvertor.convert(patchGroups.get(base), new Convertor<FilePatchInProgress, FilePatch>() {
               public FilePatch convert(FilePatchInProgress o) {
                 return o.getPatch();
               }
@@ -107,20 +108,21 @@ public class ApplyPatchAction extends AnAction {
     return sb.toString();
   }
 
-  public static ApplyPatchStatus applyOnly(final Project project, final FilePatch patch, final ApplyPatchContext context, final VirtualFile file) {
+  public static<T extends FilePatch> ApplyPatchStatus applyOnly(final Project project, final ApplyFilePatchBase<T> patch, final ApplyPatchContext context, final VirtualFile file) {
+    final T patchBase = patch.getPatch();
     try {
       return patch.apply(file, context, project);
     }
     catch(ApplyPatchException ex) {
-      if (!patch.isNewFile() && !patch.isDeletedFile() && patch instanceof TextFilePatch) {
+      if (!patchBase.isNewFile() && !patchBase.isDeletedFile() && patchBase instanceof TextFilePatch) {
         //final VirtualFile beforeRename = (pathBeforeRename == null) ? file : pathBeforeRename;
-        ApplyPatchStatus mergeStatus = mergeAgainstBaseVersion(project, file, new FilePathImpl(file), (TextFilePatch) patch,
+        ApplyPatchStatus mergeStatus = mergeAgainstBaseVersion(project, file, new FilePathImpl(file), (TextFilePatch) patchBase,
                                                                ApplyPatchMergeRequestFactory.INSTANCE);
         if (mergeStatus != null) {
           return mergeStatus;
         }
       }
-      Messages.showErrorDialog(project, VcsBundle.message("patch.apply.error", patch.getBeforeName(), ex.getMessage()),
+      Messages.showErrorDialog(project, VcsBundle.message("patch.apply.error", patchBase.getBeforeName(), ex.getMessage()),
                                VcsBundle.message("patch.apply.dialog.title"));
     }
     catch (Exception ex) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.form b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.form
deleted file mode 100644 (file)
index fc880ae..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.vcs.changes.patch.ApplyPatchDialog">
-  <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
-    <margin top="0" left="0" bottom="0" right="0"/>
-    <constraints>
-      <xy x="20" y="20" width="571" height="432"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <component id="2b938" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <labelFor value="2ad1e"/>
-          <text resource-bundle="messages/VcsBundle" key="create.patch.file.name.field"/>
-        </properties>
-      </component>
-      <component id="2ad1e" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myFileNameField">
-        <constraints>
-          <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
-            <minimum-size width="300" height="-1"/>
-          </grid>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="2b193" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myBaseDirectoryField">
-        <constraints>
-          <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
-            <minimum-size width="300" height="-1"/>
-          </grid>
-        </constraints>
-        <properties/>
-      </component>
-      <component id="c9d4a" class="javax.swing.JLabel" binding="myStatusLabel">
-        <constraints>
-          <grid row="5" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <text value="  "/>
-        </properties>
-      </component>
-      <component id="bb8e1" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <labelFor value="2b193"/>
-          <text resource-bundle="messages/VcsBundle" key="patch.apply.base.directory.field"/>
-        </properties>
-      </component>
-      <component id="8a145" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties>
-          <labelFor value="bd375"/>
-          <text resource-bundle="messages/VcsBundle" key="patch.apply.strip.leading.directories.field"/>
-        </properties>
-      </component>
-      <component id="bd375" class="javax.swing.JSpinner" binding="myStripLeadingDirectoriesSpinner" default-binding="true">
-        <constraints>
-          <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
-            <preferred-size width="60" height="-1"/>
-          </grid>
-        </constraints>
-        <properties/>
-      </component>
-      <hspacer id="c2196">
-        <constraints>
-          <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-        </constraints>
-      </hspacer>
-      <grid id="d6723" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
-        <margin top="0" left="0" bottom="0" right="4"/>
-        <constraints>
-          <grid row="4" column="0" row-span="1" col-span="3" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties/>
-        <border type="none" title="Target Changelist"/>
-        <children>
-          <nested-form id="e2f7" form-file="com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form" binding="myChangeListChooser" custom-create="true">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-            </constraints>
-          </nested-form>
-        </children>
-      </grid>
-      <grid id="66d26" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
-        <margin top="0" left="0" bottom="0" right="0"/>
-        <constraints>
-          <grid row="3" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
-        </constraints>
-        <properties/>
-        <border type="none" title="Patch Contents"/>
-        <children>
-          <scrollpane id="821b1">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
-                <preferred-size width="-1" height="150"/>
-              </grid>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="11bce" class="javax.swing.JList" binding="myPatchContentsList">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-          <component id="cf3f2" class="javax.swing.JButton" binding="myShowDiffButton">
-            <constraints>
-              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <enabled value="false"/>
-              <text value="Show Diff"/>
-            </properties>
-          </component>
-        </children>
-      </grid>
-    </children>
-  </grid>
-</form>
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDialog.java
deleted file mode 100644 (file)
index 1368929..0000000
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intellij.openapi.vcs.changes.patch;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonShortcuts;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.diff.impl.patch.*;
-import com.intellij.openapi.diff.impl.patch.formove.PathMerger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypeManager;
-import com.intellij.openapi.fileTypes.FileTypes;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.help.HelpManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FilePathImpl;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.VcsBundle;
-import com.intellij.openapi.vcs.changes.*;
-import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
-import com.intellij.openapi.vcs.changes.ui.ChangeListChooserPanel;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.CollectionListModel;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.DocumentAdapter;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.Alarm;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Consumer;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.PropertyKey;
-
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.DocumentEvent;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-import java.util.List;
-
-/**
- * @author yole
- */
-public class ApplyPatchDialog extends DialogWrapper {
-  private final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.patch.ApplyPatchDialog");
-
-  private JPanel myRootPanel;
-  private TextFieldWithBrowseButton myFileNameField;
-  private JLabel myStatusLabel;
-  private TextFieldWithBrowseButton myBaseDirectoryField;
-  private JSpinner myStripLeadingDirectoriesSpinner;
-  private JList myPatchContentsList;
-  private ChangeListChooserPanel myChangeListChooser;
-  private JButton myShowDiffButton;
-  private List<FilePatch> myPatches;
-  private Collection<FilePatch> myPatchesFailedToLoad;
-  private final Alarm myLoadPatchAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
-  private final Alarm myVerifyPatchAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
-  private String myLoadPatchError = null;
-  private String myDetectedBaseDirectory = null;
-  private int myDetectedStripLeadingDirs = -1;
-  private final Project myProject;
-  private boolean myInnerChange;
-  private LocalChangeList mySelectedChangeList;
-
-  private final Map<Pair<String, String>, String> myMoveRenameInfo;
-
-  public ApplyPatchDialog(Project project) {
-    super(project, true);
-    myProject = project;
-    setTitle(VcsBundle.message("patch.apply.dialog.title"));
-    final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
-      @Override
-      public boolean isFileSelectable(VirtualFile file) {
-        return file.getFileType() == StdFileTypes.PATCH || file.getFileType() == FileTypes.PLAIN_TEXT;
-      }
-    };
-    myMoveRenameInfo = new HashMap<Pair<String, String>, String>();
-    myFileNameField.addBrowseFolderListener(VcsBundle.message("patch.apply.select.title"), "", project, descriptor);
-    myFileNameField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
-      protected void textChanged(DocumentEvent e) {
-        updateOKAction();
-        myStatusLabel.setForeground(UIUtil.getLabelForeground());
-        myStatusLabel.setText(VcsBundle.message("patch.load.progress"));
-        myPatches = null;
-        myMoveRenameInfo.clear();
-        myLoadPatchAlarm.cancelAllRequests();
-        myLoadPatchAlarm.addRequest(new Runnable() {
-          public void run() {
-            checkLoadPatches(true);
-          }
-        }, 400);
-      }
-    });
-
-    myBaseDirectoryField.setText(project.getBaseDir().getPresentableUrl());
-    myBaseDirectoryField.addBrowseFolderListener(VcsBundle.message("patch.apply.select.base.directory.title"), "", project,
-                                                 new FileChooserDescriptor(false, true, false, false, false, false));
-    myBaseDirectoryField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
-      protected void textChanged(final DocumentEvent e) {
-        if (!myInnerChange) {
-          queueVerifyPatchPaths();
-        }
-      }
-    });
-
-    myStripLeadingDirectoriesSpinner.setModel(new SpinnerNumberModel(0, 0, 256, 1));
-    myStripLeadingDirectoriesSpinner.addChangeListener(new ChangeListener() {
-      public void stateChanged(final ChangeEvent e) {
-        if (!myInnerChange) {
-          queueVerifyPatchPaths();
-        }
-      }
-    });
-
-    myPatchContentsList.setCellRenderer(new PatchCellRendererPanel());
-
-    ChangeListManager changeListManager = ChangeListManager.getInstance(project);
-    myChangeListChooser.setChangeLists(changeListManager.getChangeListsCopy());
-    myChangeListChooser.setDefaultSelection(changeListManager.getDefaultChangeList());
-    myChangeListChooser.init(project);
-    init();
-    updateOKAction();
-    myShowDiffButton.addActionListener(new ActionListener() {
-      public void actionPerformed(final ActionEvent e) {
-        showDiff();
-      }
-    });
-    myPatchContentsList.addMouseListener(new MouseAdapter() {
-      public void mouseClicked(final MouseEvent e) {
-        if (e.getButton() == 1 && e.getClickCount() == 2) {
-          showDiff();
-        }
-      }
-    });
-
-    new AnAction() {
-      @Override
-      public void actionPerformed(AnActionEvent e) {
-        showDiff();
-      }
-    }.registerCustomShortcutSet(CommonShortcuts.getDiff(), myRootPanel, myDisposable);
-  }
-
-  private void showDiff() {
-    List<Change> changes = new ArrayList<Change>();
-    ApplyPatchContext context = getApplyPatchContext().getPrepareContext();
-    Object[] selection = myPatchContentsList.getSelectedValues();
-    if (selection.length == 0) {
-      if (myPatches == null) return;
-      selection = ArrayUtil.toObjectArray(myPatches);
-    }
-    for(Object o: selection) {
-      final TextFilePatch patch = (TextFilePatch) o;
-      try {
-        if (patch.isNewFile()) {
-          final FilePath newFilePath = FilePathImpl.createNonLocal(patch.getAfterName(), false);
-          final String content = patch.getNewFileText();
-          ContentRevision revision = new SimpleContentRevision(content, newFilePath, patch.getAfterVersionId());
-          changes.add(new Change(null, revision));
-        } else if ((! patch.isDeletedFile()) && (patch.getBeforeName() != null) && (patch.getAfterName() != null) &&
-            (! patch.getBeforeName().equals(patch.getAfterName()))) {
-
-          final VirtualFile baseDirectory = getBaseDirectory();
-          final VirtualFile beforeFile = PathMerger.getFile(baseDirectory, patch.getBeforeName());
-
-          if (beforeFile != null) {
-            final List<String> tail = new ArrayList<String>();
-            final VirtualFile partFile = PathMerger.getFile(baseDirectory, patch.getAfterName(), tail);
-            final StringBuilder sb = new StringBuilder(partFile.getPath());
-            for (String s : tail) {
-              if (sb.charAt(sb.length() - 1) != '/') {
-                sb.append('/');
-              }
-              sb.append(s);
-            }
-
-            final Change change =
-                changeForPath(beforeFile, patch, FilePathImpl.createNonLocal(FileUtil.toSystemIndependentName(sb.toString()), false));
-            if (change != null) {
-              changes.add(change);
-            }
-          } else {
-            Messages.showErrorDialog(myProject, "Cannot show difference: cannot find file " + patch.getBeforeName(),
-                                     VcsBundle.message("patch.apply.dialog.title"));
-          }
-        }
-          else {
-          final VirtualFile fileToPatch = patch.findFileToPatch(context);
-          if (fileToPatch != null) {
-            final FilePathImpl filePath = new FilePathImpl(fileToPatch);
-            final CurrentContentRevision currentRevision = new CurrentContentRevision(filePath);
-            if (patch.isDeletedFile()) {
-              changes.add(new Change(currentRevision, null));
-            }
-            else {
-              final Change change = changeForPath(fileToPatch, patch, null);
-              if (change != null) {
-                changes.add(change);
-              }
-            }
-          }
-        }
-      }
-      catch (Exception e) {
-        Messages.showErrorDialog(myProject, "Error loading changes for " + patch.getAfterFileName() + ": " + e.getMessage(),
-                                 VcsBundle.message("patch.apply.dialog.title"));
-        return;
-      }
-    }
-    ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), 0, myProject,
-                                     ShowDiffAction.DiffExtendUIFactory.NONE, false);
-  }
-
-  @Nullable
-  private Change changeForPath(final VirtualFile fileToPatch, final TextFilePatch patch, final FilePath newFilePath) {
-    try {
-    final FilePathImpl filePath = new FilePathImpl(fileToPatch);
-    final CurrentContentRevision currentRevision = new CurrentContentRevision(filePath);
-    final Document doc = FileDocumentManager.getInstance().getDocument(fileToPatch);
-    String baseContent = doc.getText();
-    StringBuilder newText = new StringBuilder();
-    patch.applyModifications(baseContent, newText);
-    ContentRevision revision = new SimpleContentRevision(newText.toString(), (newFilePath == null) ? filePath : newFilePath, patch.getAfterVersionId());
-    return new Change(currentRevision, revision);
-    } catch (ApplyPatchException e) {
-      ApplyPatchContext context = new ApplyPatchContext(getBaseDirectory(), 0, false, false);
-      // just show diff here. maybe refactor further..
-      ApplyPatchAction.mergeAgainstBaseVersion(myProject, fileToPatch, context, patch, ApplyPatchAction.ApplyPatchMergeRequestFactory.INSTANCE_READ_ONLY);
-      return null;
-    }
-  }
-
-  @Override
-  @NonNls
-  protected String getDimensionServiceKey() {
-    return "vcs.ApplyPatchDialog";
-  }
-
-  private void queueVerifyPatchPaths() {
-    myStatusLabel.setForeground(UIUtil.getLabelForeground());
-    myStatusLabel.setText(VcsBundle.message("apply.patch.progress.verifying"));
-    myVerifyPatchAlarm.cancelAllRequests();
-    myVerifyPatchAlarm.addRequest(new Runnable() {
-      public void run() {
-        try {
-          if (myPatches != null) {
-            verifyPatchPaths();
-          }
-        }
-        catch(Exception ex) {
-          LOG.error(ex);
-        }
-      }
-    }, 400);
-  }
-
-  public void setFileName(String fileName) {
-    myFileNameField.setText(fileName);
-    checkLoadPatches(false);
-  }
-
-  private void checkLoadPatches(final boolean async) {
-    final String fileName = myFileNameField.getText().replace(File.separatorChar, '/');
-    final VirtualFile patchFile = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
-      public VirtualFile compute() {
-        final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileName);
-        if (file != null) {
-          file.refresh(false, false);
-          if (file.isDirectory()) {
-            // we are looking for file not directory
-            return null;
-          }
-        }
-        return file;
-      }
-    });
-    if (patchFile == null) {
-      queueUpdateStatus("Cannot find patch file");
-      return;
-    }
-    myChangeListChooser.setDefaultName(patchFile.getNameWithoutExtension().replace('_', ' ').trim());
-    if (async) {
-      ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
-        public void run() {
-          loadPatchesFromFile(patchFile);
-        }
-      });
-    }
-    else {
-      loadPatchesFromFile(patchFile);
-    }
-  }
-
-  private void loadPatchesFromFile(final VirtualFile patchFile) {
-    myPatches = new ArrayList<FilePatch>();
-    myPatchesFailedToLoad = new HashSet<FilePatch>();
-    ApplicationManager.getApplication().runReadAction(new Runnable() {
-      public void run() {
-        if (!patchFile.isValid()) {
-          queueUpdateStatus("Cannot find patch file");
-          return;
-        }
-        PatchReader reader;
-        try {
-          reader = new PatchReader(patchFile);
-        }
-        catch (IOException e) {
-          queueUpdateStatus(VcsBundle.message("patch.apply.open.error", e.getMessage()));
-          return;
-        }
-        while(true) {
-          FilePatch patch;
-          try {
-            patch = reader.readNextPatch();
-          }
-          catch (PatchSyntaxException e) {
-            if (e.getLine() >= 0) {
-              queueUpdateStatus(VcsBundle.message("patch.apply.load.error.line", e.getMessage(), e.getLine()));
-            }
-            else {
-              queueUpdateStatus(VcsBundle.message("patch.apply.load.error", e.getMessage()));
-            }
-            return;
-          }
-          if (patch == null) {
-            break;
-          }
-
-          final String beforeName = patch.getBeforeName();
-          final String afterName = patch.getAfterName();
-          final String movedMessage = RelativePathCalculator.getMovedString(beforeName, afterName);
-          if (movedMessage != null) {
-            myMoveRenameInfo.put(new Pair<String, String>(beforeName, afterName), movedMessage);
-          }
-          myPatches.add(patch);
-        }
-        if (myPatches.isEmpty()) {
-          queueUpdateStatus(VcsBundle.message("patch.apply.no.patches.found"));
-          return;
-        }
-
-        autoDetectBaseDirectory();
-        queueUpdateStatus(null);
-      }
-    });
-  }
-
-  private void autoDetectBaseDirectory() {
-    boolean autodetectFailed = false;
-    for(FilePatch patch: myPatches) {
-      VirtualFile baseDir = myDetectedBaseDirectory == null
-                            ? getBaseDirectory()
-                            : LocalFileSystem.getInstance().findFileByPath(myDetectedBaseDirectory.replace(File.separatorChar, '/'));
-      int skipTopDirs = myDetectedStripLeadingDirs >= 0 ? myDetectedStripLeadingDirs : 0;
-      VirtualFile fileToPatch;
-      try {
-        fileToPatch = patch.findFileToPatch(new ApplyPatchContext(baseDir, skipTopDirs, false, false));
-      }
-      catch (IOException e) {
-        myPatchesFailedToLoad.add(patch);
-        continue;
-      }
-      if (fileToPatch == null) {
-        boolean success = false;
-        if (!autodetectFailed) {
-          String oldDetectedBaseDirectory = myDetectedBaseDirectory;
-          int oldDetectedStripLeadingDirs = myDetectedStripLeadingDirs;
-          success = detectDirectory(patch);
-          if (success) {
-            if ((oldDetectedBaseDirectory != null && !Comparing.equal(oldDetectedBaseDirectory, myDetectedBaseDirectory)) ||
-                (oldDetectedStripLeadingDirs >= 0 && oldDetectedStripLeadingDirs != myDetectedStripLeadingDirs)) {
-              myDetectedBaseDirectory = null;
-              myDetectedStripLeadingDirs = -1;
-              autodetectFailed = true;
-            }
-          }
-        }
-        if (!success) {
-          myPatchesFailedToLoad.add(patch);
-        }
-      }
-    }
-  }
-
-  private boolean detectDirectory(final FilePatch patch) {
-    if (patch.getBeforeName().equals(patch.getAfterName()) && patch.isNewFile()) {
-      return false;
-    } else {
-      boolean success = detectDirectoryByName(patch.getBeforeName());
-      if (! success) {
-        success = detectDirectoryByName(patch.getAfterName());
-      }
-      return success;
-    }
-  }
-
-  private Collection<String> verifyPatchPaths() {
-    final ApplyPatchContext context = getApplyPatchContext();
-    myPatchesFailedToLoad.clear();
-    for(FilePatch patch: myPatches) {
-      try {
-        if (context.getBaseDir() == null || patch.findFileToPatch(context) == null) {
-          myPatchesFailedToLoad.add(patch);
-        }
-      }
-      catch (IOException e) {
-        myPatchesFailedToLoad.add(patch);
-      }
-    }
-    SwingUtilities.invokeLater(new Runnable() {
-      public void run() {
-        myPatchContentsList.repaint();
-        myStatusLabel.setText("");
-      }
-    });
-    return context.getMissingDirectories();
-  }
-
-  private boolean detectDirectoryByName(final String patchFileName) {
-    PatchBaseDirectoryDetector detector = PatchBaseDirectoryDetector.getInstance(myProject);
-    if (detector == null) return false;
-    final PatchBaseDirectoryDetector.Result result = detector.detectBaseDirectory(patchFileName);
-    if (result == null) return false;
-    myDetectedBaseDirectory = result.baseDir;
-    myDetectedStripLeadingDirs = result.stripDirs;
-    return true;
-  }
-
-  private void queueUpdateStatus(final String s) {
-    if (!SwingUtilities.isEventDispatchThread()) {
-      SwingUtilities.invokeLater(new Runnable() {
-        public void run() {
-          queueUpdateStatus(s);
-        }
-      });
-      return;
-    }
-    updateStatus(s);
-  }
-
-  private void updateStatus(String s) {
-    myInnerChange = true;
-    try {
-      if (myDetectedBaseDirectory != null) {
-        myBaseDirectoryField.setText(myDetectedBaseDirectory);
-        myDetectedBaseDirectory = null;
-      }
-      if (myDetectedStripLeadingDirs != -1) {
-        myStripLeadingDirectoriesSpinner.setValue(myDetectedStripLeadingDirs);
-        myDetectedStripLeadingDirs = -1;
-      }
-    }
-    finally {
-      myInnerChange = false;
-    }
-    myLoadPatchError = s;
-    if (s == null) {
-      myStatusLabel.setForeground(UIUtil.getLabelForeground());
-      myStatusLabel.setText(buildPatchSummary());
-    }
-    else {
-      myStatusLabel.setText(s);
-      myStatusLabel.setForeground(Color.red);
-    }
-    updatePatchTableModel();
-    updateOKAction();
-  }
-
-  private void updatePatchTableModel() {
-    if (myPatches != null) {
-      myPatchContentsList.setModel(new CollectionListModel(myPatches));
-    }
-    else {
-      myPatchContentsList.setModel(new DefaultListModel());
-    }
-    myShowDiffButton.setEnabled(myPatches != null && myPatches.size() > 0);
-  }
-
-  private String buildPatchSummary() {
-    int newFiles = 0;
-    int changedFiles = 0;
-    int deletedFiles = 0;
-    for(FilePatch patch: myPatches) {
-      if (patch.isNewFile()) {
-        newFiles++;
-      }
-      else if (patch.isDeletedFile()) {
-        deletedFiles++;
-      }
-      else {
-        changedFiles++;
-      }
-    }
-    StringBuilder summaryBuilder = new StringBuilder("<html><body><b>").append(VcsBundle.message("apply.patch.summary.title")).append("</b> ");
-    appendSummary(changedFiles, 0, summaryBuilder, "patch.summary.changed.files");
-    appendSummary(newFiles, changedFiles, summaryBuilder, "patch.summary.new.files");
-    appendSummary(deletedFiles, changedFiles + newFiles, summaryBuilder, "patch.summary.deleted.files");
-    summaryBuilder.append("</body></html>");
-    return summaryBuilder.toString();
-  }
-
-  private static void appendSummary(final int count, final int prevCount, final StringBuilder summaryBuilder,
-                                    @PropertyKey(resourceBundle = "messages.VcsBundle") final String key) {
-    if (count > 0) {
-      if (prevCount > 0) {
-        summaryBuilder.append(", ");
-      }
-      summaryBuilder.append(VcsBundle.message(key, count));
-    }
-  }
-
-  @Override
-  protected void dispose() {
-    myLoadPatchAlarm.dispose();
-    myVerifyPatchAlarm.dispose();
-    super.dispose();
-  }
-
-  private void updateOKAction() {
-    setOKActionEnabled(myFileNameField.getText().length() > 0 && myLoadPatchError == null);
-  }
-
-  @Override
-  protected void doOKAction() {
-    if (myPatches == null) {
-      myLoadPatchAlarm.cancelAllRequests();
-      checkLoadPatches(false);
-    }
-    if (myLoadPatchError == null) {
-      mySelectedChangeList = myChangeListChooser.getSelectedList(myProject);
-      if (mySelectedChangeList == null) return;
-      final Collection<String> missingDirs = verifyPatchPaths();
-      if (missingDirs.size() > 0 && !checkCreateMissingDirs(missingDirs)) return;
-      if (getBaseDirectory() == null) {
-        Messages.showErrorDialog(getContentPane(), "Could not find patch base directory " + myBaseDirectoryField.getText());
-        return;
-      }
-      super.doOKAction();
-    }
-  }
-
-  private boolean checkCreateMissingDirs(final Collection<String> missingDirs) {
-    StringBuilder messageBuilder = new StringBuilder(VcsBundle.message("apply.patch.create.dirs.prompt.header"));
-    for(String missingDir: missingDirs) {
-      messageBuilder.append(missingDir).append("\r\n");
-    }
-    messageBuilder.append(VcsBundle.message("apply.patch.create.dirs.prompt.footer"));
-    int rc = Messages.showYesNoCancelDialog(myProject, messageBuilder.toString(), VcsBundle.message("patch.apply.dialog.title"),
-                                            Messages.getQuestionIcon());
-    if (rc == 0) {
-      CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
-        public void run() {
-          for(String dir: missingDirs) {
-            try {
-              VfsUtil.createDirectories(dir);
-            }
-            catch (IOException e) {
-              Messages.showErrorDialog(myProject, "Error creating directories: " + e.getMessage(),
-                                       VcsBundle.message("patch.apply.dialog.title"));
-            }
-          }
-        }
-      }, "Creating directories for new files in patch", null);
-    }
-    else if (rc != 1) {
-      return false;
-    }
-    return true;
-  }
-
-  @Nullable
-  protected JComponent createCenterPanel() {
-    return myRootPanel;
-  }
-
-  public List<FilePatch> getPatches() {
-    return myPatches;
-  }
-
-  private VirtualFile getBaseDirectory() {
-    if (ApplicationManager.getApplication().isDispatchThread()) {
-      return LocalFileSystem.getInstance().refreshAndFindFileByPath(FileUtil.toSystemIndependentName(myBaseDirectoryField.getText())); 
-    }
-    return LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(myBaseDirectoryField.getText()));
-  }
-
-  private int getStripLeadingDirectories() {
-    return ((Integer) myStripLeadingDirectoriesSpinner.getValue()).intValue();
-  }
-
-  public ApplyPatchContext getApplyPatchContext() {
-    return new ApplyPatchContext(getBaseDirectory(), getStripLeadingDirectories(), false, false);
-  }
-
-  public LocalChangeList getSelectedChangeList() {
-    return mySelectedChangeList;
-  }
-
-  private static String getChangeType(final FilePatch filePatch) {
-    if (filePatch.isNewFile()) return VcsBundle.message("change.type.new");
-    if (filePatch.isDeletedFile()) return VcsBundle.message("change.type.deleted");
-    return VcsBundle.message("change.type.modified");
-  }
-
-  protected void doHelpAction() {
-    HelpManager.getInstance().invokeHelp("reference.dialogs.vcs.patch.apply");
-  }
-  
-  protected Action[] createActions() {
-    return new Action[]{ getOKAction(), getCancelAction(), getHelpAction() };
-  }
-
-  private void createUIComponents() {
-    myChangeListChooser = new ChangeListChooserPanel(null, new Consumer<String>() {
-      public void consume(final String errorMessage) {
-        setOKActionEnabled(errorMessage == null);
-        setErrorText(errorMessage);
-      }
-    });
-  }
-
-  private class PatchCellRendererPanel extends JPanel implements ListCellRenderer {
-    private final PatchCellRenderer myRenderer;
-    private final JLabel myFileTypeLabel;
-
-    public PatchCellRendererPanel() {
-      super(new BorderLayout());
-      setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
-      myRenderer = new PatchCellRenderer();
-      add(myRenderer, BorderLayout.CENTER);
-      myFileTypeLabel = new JLabel();
-      myFileTypeLabel.setHorizontalAlignment(JLabel.RIGHT);
-      add(myFileTypeLabel, BorderLayout.EAST);
-    }
-
-    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
-      FilePatch patch = (FilePatch) value;
-      myRenderer.getListCellRendererComponent(list, value, index, isSelected, false);
-      myFileTypeLabel.setText("(" + getChangeType(patch) + ")");
-      if (isSelected) {
-        setBackground(UIUtil.getListSelectionBackground());
-        setForeground(UIUtil.getListSelectionForeground());
-        myFileTypeLabel.setForeground(UIUtil.getListSelectionForeground());
-      }
-      else {
-        setBackground(UIUtil.getListBackground());
-        setForeground(UIUtil.getListForeground());        
-        myFileTypeLabel.setForeground(Color.gray);
-      }
-      return this;
-    }
-  }
-
-  private class PatchCellRenderer extends ColoredListCellRenderer {
-    private final SimpleTextAttributes myNewAttributes = new SimpleTextAttributes(0, FileStatus.ADDED.getColor());
-    private final SimpleTextAttributes myDeletedAttributes = new SimpleTextAttributes(0, FileStatus.DELETED.getColor());
-    private final SimpleTextAttributes myModifiedAttributes = new SimpleTextAttributes(0, FileStatus.MODIFIED.getColor());
-
-    private boolean assumeProblemWillBeFixed(final FilePatch filePatch) {
-      // if some of the files are valid, assume that "red" new files will be fixed by creating directories
-      if (myPatches == null || myPatchesFailedToLoad == null) return false;
-      return (filePatch.isNewFile() && myPatchesFailedToLoad.size() != myPatches.size());
-    }
-
-    protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
-      FilePatch filePatch = (FilePatch) value;
-      String name = filePatch.getAfterNameRelative(getStripLeadingDirectories());
-
-      final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(name);
-      setIcon(fileType.getIcon());
-
-      if (myPatchesFailedToLoad.contains(filePatch) && !assumeProblemWillBeFixed(filePatch)) {
-        append(name, SimpleTextAttributes.ERROR_ATTRIBUTES);
-      }
-      else if (filePatch.isNewFile()) {
-        append(name, myNewAttributes);
-      }
-      else if (filePatch.isDeletedFile()) {
-        append(name, myDeletedAttributes);
-      }
-      else {
-        append(name, myModifiedAttributes);
-      }
-
-      final String afterPath = filePatch.getAfterName();
-      final String beforePath = filePatch.getBeforeName();
-
-      if ((beforePath != null) && (afterPath != null) && (! beforePath.equals(afterPath))) {
-        final String message = myMoveRenameInfo.get(new Pair<String, String>(beforePath, afterPath));
-        if (message != null) {
-          append(message, SimpleTextAttributes.REGULAR_ATTRIBUTES);
-        }
-      }
-    }
-  }
-}
index 9e7722e1135a46a377754fdaf5a6d6068dc2887d..d1c5902efc6d4713d5dd68baf11381df09901d60 100644 (file)
@@ -18,13 +18,13 @@ package com.intellij.openapi.vcs.changes.patch;
 import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
 import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
 import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.Processor;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 public class ApplyPatchForBaseRevisionTexts {
@@ -58,7 +58,7 @@ public class ApplyPatchForBaseRevisionTexts {
           public boolean process(final CharSequence text) {
             newText.setLength(0);
             try {
-              myStatus = patch.applyModifications(text, newText);
+              myStatus = ApplyFilePatchBase.applyModifications(patch, text, newText);
             }
             catch(ApplyPatchException ex) {
               return true;  // continue to older versions
index 4d027bfde718c7bcfa8be7636816018fa550ee99..4c1bbe049c164474fb7b966050dfb1a6dc9f2fd8 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes.patch;
 
 import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
 import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.vcs.FilePath;
@@ -50,7 +51,7 @@ public class LazyPatchContentRevision implements ContentRevision {
         }
         final String baseContent = doc.getText();
         final StringBuilder newText = new StringBuilder();
-        myPatch.applyModifications(baseContent, newText);
+        ApplyFilePatchBase.applyModifications(myPatch, baseContent, newText);
 
         myContent = newText.toString();
       } catch (ApplyPatchException e) {
index 850be87689997a2957ffed920e545c4015924786..cfbb0c06b09da212d788eef486b7eb240fcd74ae 100644 (file)
@@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.diff.DiffRequestFactory;
 import com.intellij.openapi.diff.MergeRequest;
 import com.intellij.openapi.diff.impl.patch.*;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyTextFilePatch;
 import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.MessageType;
@@ -77,7 +78,7 @@ public class DiffShelvedChangesAction extends AnAction implements DumbAware {
       final Change change = shelvedChange.getChange(project);
       final String beforePath = shelvedChange.getBeforePath();
       try {
-        final VirtualFile f = FilePatch.findPatchTarget(context, beforePath, shelvedChange.getAfterPath(), beforePath == null);
+        final VirtualFile f = ApplyTextFilePatch.findPatchTarget(context, beforePath, shelvedChange.getAfterPath(), beforePath == null);
         if ((f == null) || (! f.exists())) {
           if (beforePath != null) {
             missing.add(beforePath);
index d7d0066f6d3f93f970922b84a30d3d8cc109f4a4..d7c2ac6570b3325c13ca3ac37a136d66d74ff28c 100644 (file)
@@ -27,6 +27,7 @@ import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.components.ProjectComponent;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.diff.impl.patch.*;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.diff.impl.patch.formove.CustomBinaryPatchApplier;
 import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
 import com.intellij.openapi.options.StreamProvider;
@@ -269,7 +270,7 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl
     }
 
     final BinaryPatchApplier binaryPatchApplier = new BinaryPatchApplier(binaryFilesToUnshelve.size());
-    final PatchApplier patchApplier = new PatchApplier(myProject, myProject.getBaseDir(), patches, targetChangeList, binaryPatchApplier);
+    final PatchApplier<ShelvedBinaryFilePatch> patchApplier = new PatchApplier<ShelvedBinaryFilePatch>(myProject, myProject.getBaseDir(), patches, targetChangeList, binaryPatchApplier);
     patchApplier.execute();
     remainingPatches.addAll(patchApplier.getRemainingPatches());
 
@@ -299,7 +300,7 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl
     return textFilePatches;
   }
 
-  private class BinaryPatchApplier implements CustomBinaryPatchApplier {
+  private class BinaryPatchApplier implements CustomBinaryPatchApplier<ShelvedBinaryFilePatch> {
     private final List<FilePatch> myAppliedPatches;
 
     private BinaryPatchApplier(final int binaryCount) {
@@ -307,9 +308,9 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl
     }
 
     @NotNull
-    public ApplyPatchStatus apply(final List<Pair<VirtualFile, FilePatch>> patches) throws IOException {
-      for (Pair<VirtualFile, FilePatch> patch : patches) {
-        final ShelvedBinaryFilePatch shelvedPatch = (ShelvedBinaryFilePatch) patch.getSecond();
+    public ApplyPatchStatus apply(final List<Pair<VirtualFile, ApplyFilePatchBase<ShelvedBinaryFilePatch>>> patches) throws IOException {
+      for (Pair<VirtualFile, ApplyFilePatchBase<ShelvedBinaryFilePatch>> patch : patches) {
+        final ShelvedBinaryFilePatch shelvedPatch = patch.getSecond().getPatch();
         unshelveBinaryFile(shelvedPatch.getShelvedBinaryFile(), patch.getFirst());
         myAppliedPatches.add(shelvedPatch);
       }
@@ -522,7 +523,7 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl
     return reader.readAllPatches();
   }
 
-  private static class ShelvedBinaryFilePatch extends FilePatch {
+  public static class ShelvedBinaryFilePatch extends FilePatch {
     private final ShelvedBinaryFile myShelvedBinaryFile;
 
     public ShelvedBinaryFilePatch(final ShelvedBinaryFile shelvedBinaryFile) {
@@ -543,11 +544,6 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl
       return pathNameComponents [pathNameComponents.length-1];    
     }
 
-    protected void applyCreate(final VirtualFile newFile) throws IOException, ApplyPatchException {
-    }
-    protected ApplyPatchStatus applyChange(final VirtualFile fileToPatch) throws IOException, ApplyPatchException {
-      return null;
-    }
     public boolean isNewFile() {
       return myShelvedBinaryFile.BEFORE_PATH == null;
     }
index 62210f3339a3d057db567f359177d402a414fe8e..94b705d598eef09b8f180414d1813a66f160ec78 100644 (file)
@@ -26,6 +26,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
 import com.intellij.openapi.diff.impl.patch.PatchSyntaxException;
 import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
@@ -203,7 +204,7 @@ public class ShelvedChange {
         return null;
       }
       StringBuilder newText = new StringBuilder();
-      patch.applyModifications(getBaseContent(), newText);
+      ApplyFilePatchBase.applyModifications(patch, getBaseContent(), newText);
       return newText.toString();
     }