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;
patches.add(p);
}
- new PatchApplier(myProject, root, patches, null, null).execute();
+ new PatchApplier<BinaryFilePatch>(myProject, root, patches, null, null).execute();
}
}
*/
package com.intellij.openapi.diff.impl.patch;
-import com.intellij.openapi.vfs.VirtualFile;
-
-import java.io.IOException;
-
/**
* @author yole
*/
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;
}
public boolean isDeletedFile() {
return myAfterContent == null;
}
+
+ public byte[] getAfterContent() {
+ return myAfterContent;
+ }
}
*/
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;
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();
/*
- * 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.
*/
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
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();
}
/*
- * 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.
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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 {
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
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;
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();
}
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;
/**
* 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);
return;
}
- final List<Pair<VirtualFile, FilePatch>> textPatches = myVerifier.getTextPatches();
+ final List<Pair<VirtualFile, ApplyTextFilePatch>> textPatches = myVerifier.getTextPatches();
if (! fileTypesAreOk(textPatches)) {
return;
}
}
@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;
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);
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;
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();
*/
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;
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;
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;
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;
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>();
}
}
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);
}
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;
}
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;
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) {
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;
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();
}
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) {
+++ /dev/null
-<?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>
+++ /dev/null
-/*
- * 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);
- }
- }
- }
- }
-}
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 {
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
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;
}
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) {
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;
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);
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;
}
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());
return textFilePatches;
}
- private class BinaryPatchApplier implements CustomBinaryPatchApplier {
+ private class BinaryPatchApplier implements CustomBinaryPatchApplier<ShelvedBinaryFilePatch> {
private final List<FilePatch> myAppliedPatches;
private BinaryPatchApplier(final int binaryCount) {
}
@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);
}
return reader.readAllPatches();
}
- private static class ShelvedBinaryFilePatch extends FilePatch {
+ public static class ShelvedBinaryFilePatch extends FilePatch {
private final ShelvedBinaryFile myShelvedBinaryFile;
public ShelvedBinaryFilePatch(final ShelvedBinaryFile shelvedBinaryFile) {
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;
}
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;
return null;
}
StringBuilder newText = new StringBuilder();
- patch.applyModifications(getBaseContent(), newText);
+ ApplyFilePatchBase.applyModifications(patch, getBaseContent(), newText);
return newText.toString();
}