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 index 5cce4fceb738..f1816b18c07e 100644 --- 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 @@ -29,7 +29,7 @@ public class ApplyBinaryFilePatch extends ApplyFilePatchBase { super(patch); } - protected void applyCreate(final VirtualFile newFile, CommitContext commitContext) throws IOException { + protected void applyCreate(Project project, final VirtualFile newFile, CommitContext commitContext) throws IOException { newFile.setBinaryContent(myPatch.getAfterContent()); } 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 index 94cebfb7e2c9..3391552cb086 100644 --- 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 @@ -15,12 +15,18 @@ */ package com.intellij.openapi.diff.impl.patch.apply; +import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.CommitContext; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.patch.ApplyPatchForBaseRevisionTexts; import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; +import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryContentRevision; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; import java.io.IOException; @@ -29,18 +35,31 @@ public class ApplyBinaryShelvedFilePatch extends ApplyFilePatchBase baseContents) throws IOException { - return null; + protected void applyCreate(Project project, final VirtualFile newFile, CommitContext commitContext) throws IOException { + applyChange(project, newFile, null, null); } - @Override - protected void applyCreate(VirtualFile newFile, CommitContext commitContext) throws IOException { + protected Result applyChange(Project project, final VirtualFile fileToPatch, FilePath pathBeforeRename, Getter baseContents) + throws IOException { + try { + ContentRevision contentRevision = myPatch.getShelvedBinaryFile().createChange(project).getAfterRevision(); + if (contentRevision != null) { + assert (contentRevision instanceof ShelvedBinaryContentRevision); + byte[] binaryContent = ((ShelvedBinaryContentRevision)contentRevision).getBinaryContent(); + //it may be new empty binary file + fileToPatch.setBinaryContent(binaryContent != null ? binaryContent : ArrayUtil.EMPTY_BYTE_ARRAY); + } + } + catch (VcsException e) { + LOG.error("Couldn't apply shelved binary patch", e); + return new Result(ApplyPatchStatus.FAILURE) { + + @Override + public ApplyPatchForBaseRevisionTexts getMergeData() { + return null; + } + }; + } + return SUCCESS; } } 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 index 5e4b866b6ad3..1e219dd8bbda 100644 --- 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 @@ -18,7 +18,7 @@ package com.intellij.openapi.diff.impl.patch.apply; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.patch.ApplyPatchContext; import com.intellij.openapi.diff.impl.patch.FilePatch; -import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; +import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; import com.intellij.openapi.vcs.FilePath; @@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; public abstract class ApplyFilePatchBase implements ApplyFilePatch { - private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase"); + protected final static Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase"); protected final T myPatch; public ApplyFilePatchBase(T patch) { @@ -50,9 +50,9 @@ public abstract class ApplyFilePatchBase implements ApplyFi LOG.debug("apply patch called for : " + fileToPatch.getPath()); } if (myPatch.isNewFile()) { - applyCreate(fileToPatch, commitContext); + applyCreate(project, fileToPatch, commitContext); } else if (myPatch.isDeletedFile()) { - FileEditorManagerImpl.getInstance(project).closeFile(fileToPatch); + FileEditorManager.getInstance(project).closeFile(fileToPatch); fileToPatch.delete(this); } else { @@ -61,7 +61,8 @@ public abstract class ApplyFilePatchBase implements ApplyFi return SUCCESS; } - protected abstract void applyCreate(VirtualFile newFile, CommitContext commitContext) throws IOException; + protected abstract void applyCreate(Project project, VirtualFile newFile, CommitContext commitContext) throws IOException; + protected abstract Result applyChange(Project project, VirtualFile fileToPatch, FilePath pathBeforeRename, Getter baseContents) throws IOException; @Nullable 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 index da75cb5cff3f..b7277ac2ea61 100644 --- 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 @@ -65,7 +65,7 @@ public class ApplyTextFilePatch extends ApplyFilePatchBase { }; } - protected void applyCreate(final VirtualFile newFile, CommitContext commitContext) throws IOException { + protected void applyCreate(Project project, final VirtualFile newFile, CommitContext commitContext) throws IOException { final Document document = FileDocumentManager.getInstance().getDocument(newFile); if (document == null) { throw new IOException("Failed to set contents for new file " + newFile.getPath()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java index cf7c07129542..0b44150a0fc7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java @@ -26,16 +26,19 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.patch.RelativePathCalculator; import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.util.*; @@ -110,7 +113,7 @@ public class PathsVerifier { } return affected; } - + private void addAllFilePath(final Collection files, final Collection paths) { for (VirtualFile file : files) { paths.add(VcsUtil.getFilePath(file)); @@ -337,9 +340,12 @@ public class PathsVerifier { if (patch instanceof TextFilePatch) { myTextPatches.add(Pair.create(file, ApplyFilePatchFactory.create((TextFilePatch)patch))); } else { - final ApplyFilePatchBase applyBinaryPatch = (ApplyFilePatchBase) ((patch instanceof BinaryFilePatch) ? ApplyFilePatchFactory - .create((BinaryFilePatch) patch) : - ApplyFilePatchFactory.create((ShelveChangesManager.ShelvedBinaryFilePatch) patch)); + final ApplyFilePatchBase applyBinaryPatch = (ApplyFilePatchBase)((patch instanceof BinaryFilePatch) + ? ApplyFilePatchFactory + .create((BinaryFilePatch)patch) + : + ApplyFilePatchFactory.create( + (ShelveChangesManager.ShelvedBinaryFilePatch)patch)); myBinaryPatches.add(Pair.create(file, applyBinaryPatch)); } myWritableFiles.add(file); @@ -512,14 +518,39 @@ public class PathsVerifier { public VirtualFile doMove() throws IOException { final VirtualFile oldParent = myCurrent.getParent(); - if (! Comparing.equal(myCurrent.getName(), myNewName)) { + boolean needRename = !Comparing.equal(myCurrent.getName(), myNewName); + boolean needMove = !myNewParent.equals(oldParent); + if (needRename) { + if (needMove) { + File oldParentFile = VfsUtilCore.virtualToIoFile(oldParent); + File targetAfterRenameFile = new File(oldParentFile, myNewName); + if (targetAfterRenameFile.exists() && myCurrent.exists()) { + // if there is a conflict during first rename we have to rename to third name, then move, then rename to final target + performRenameWithConflicts(oldParentFile); + return myCurrent; + } + } myCurrent.rename(PatchApplier.class, myNewName); } - if (! myNewParent.equals(oldParent)) { + if (needMove) { myCurrent.move(PatchApplier.class, myNewParent); } return myCurrent; } + + private void performRenameWithConflicts(@NotNull File oldParent) throws IOException { + File tmpFileWithUniqueName = FileUtil.createTempFile(oldParent, "tempFileToMove", null, false); + File newParentFile = VfsUtilCore.virtualToIoFile(myNewParent); + File destFile = new File(newParentFile, tmpFileWithUniqueName.getName()); + while (destFile.exists()) { + destFile = new File(newParentFile, + FileUtil.createTempFile(oldParent, FileUtil.getNameWithoutExtension(destFile.getName()), null, false) + .getName()); + } + myCurrent.rename(PatchApplier.class, destFile.getName()); + myCurrent.move(PatchApplier.class, myNewParent); + myCurrent.rename(PatchApplier.class, myNewName); + } } public interface BaseMapper { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AbstractFilePatchInProgress.java similarity index 73% rename from platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java rename to platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AbstractFilePatchInProgress.java index c21a5c82f1da..c809196397ad 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/FilePatchInProgress.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AbstractFilePatchInProgress.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,7 @@ */ package com.intellij.openapi.vcs.changes.patch; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.impl.patch.FilePatch; -import com.intellij.openapi.diff.impl.patch.TextFilePatch; import com.intellij.openapi.diff.impl.patch.formove.PathMerger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; @@ -29,11 +27,11 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.CurrentContentRevision; -import com.intellij.openapi.vcs.changes.SimpleContentRevision; import com.intellij.openapi.vcs.changes.actions.ChangeDiffRequestPresentable; import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable; import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentableProxy; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.PathUtil; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,24 +42,22 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -public class FilePatchInProgress implements Strippable { - private final TextFilePatch myPatch; +public abstract class AbstractFilePatchInProgress implements Strippable { + protected final T myPatch; private final PatchStrippable myStrippable; - private final FilePatchStatus myStatus; + protected final FilePatchStatus myStatus; private VirtualFile myBase; - private File myIoCurrentBase; - private VirtualFile myCurrentBase; + protected File myIoCurrentBase; + protected VirtualFile myCurrentBase; private boolean myBaseExists; - private ContentRevision myNewContentRevision; + protected ContentRevision myNewContentRevision; private ContentRevision myCurrentRevision; private final List myAutoBases; - private volatile Boolean myConflicts; + protected volatile Boolean myConflicts; - private File myAfterFile; - - public FilePatchInProgress(final TextFilePatch patch, final Collection autoBases, final VirtualFile baseDir) { - myPatch = patch.pathsOnlyCopy(); + protected AbstractFilePatchInProgress(final T patch, final Collection autoBases, final VirtualFile baseDir) { + myPatch = patch; //should be a copy of FilePatch! because names may be changes during processing variants myStrippable = new PatchStrippable(patch); myAutoBases = new ArrayList(); if (autoBases != null) { @@ -70,7 +66,8 @@ public class FilePatchInProgress implements Strippable { myStatus = getStatus(myPatch); if (myAutoBases.isEmpty()) { setNewBase(baseDir); - } else { + } + else { setNewBase(myAutoBases.get(0)); } } @@ -85,13 +82,14 @@ public class FilePatchInProgress implements Strippable { } } - private static FilePatchStatus getStatus(final TextFilePatch patch) { - final String beforeName = patch.getBeforeName().replace("\\", "/"); - final String afterName = patch.getAfterName().replace("\\", "/"); - + private FilePatchStatus getStatus(final T patch) { + final String beforeName = PathUtil.toSystemIndependentName(patch.getBeforeName()); + final String afterName = PathUtil.toSystemIndependentName(patch.getAfterName()); + if (patch.isNewFile() || (beforeName == null)) { return FilePatchStatus.ADDED; - } else if (patch.isDeletedFile() || (afterName == null)) { + } + else if (patch.isDeletedFile() || (afterName == null)) { return FilePatchStatus.DELETED; } @@ -107,7 +105,6 @@ public class FilePatchInProgress implements Strippable { myBase = base; myNewContentRevision = null; myCurrentRevision = null; - myAfterFile = null; myConflicts = null; final String beforeName = myPatch.getBeforeName(); @@ -115,7 +112,8 @@ public class FilePatchInProgress implements Strippable { myIoCurrentBase = PathMerger.getFile(new File(myBase.getPath()), beforeName); myCurrentBase = myIoCurrentBase == null ? null : VcsUtil.getVirtualFileWithRefresh(myIoCurrentBase); myBaseExists = (myCurrentBase != null) && myCurrentBase.exists(); - } else { + } + else { // creation final String afterName = myPatch.getAfterName(); myBaseExists = true; @@ -144,11 +142,11 @@ public class FilePatchInProgress implements Strippable { return myBase; } - public TextFilePatch getPatch() { + public T getPatch() { return myPatch; } - public boolean isBaseExists() { + private boolean isBaseExists() { return myBaseExists; } @@ -156,49 +154,30 @@ public class FilePatchInProgress implements Strippable { return myBaseExists || FilePatchStatus.ADDED.equals(myStatus); } - public ContentRevision getNewContentRevision() { - if (FilePatchStatus.DELETED.equals(myStatus)) return null; + protected abstract ContentRevision getNewContentRevision(); - if (myNewContentRevision == null) { - myConflicts = null; - if (FilePatchStatus.ADDED.equals(myStatus)) { - final FilePath newFilePath = VcsUtil.getFilePathOnNonLocal(myIoCurrentBase.getAbsolutePath(), false); - final String content = myPatch.getNewFileText(); - myNewContentRevision = new SimpleContentRevision(content, newFilePath, myPatch.getAfterVersionId()); - } else { - final FilePath newFilePath; - if (FilePatchStatus.MOVED_OR_RENAMED.equals(myStatus)) { - newFilePath = VcsUtil.getFilePath(PathMerger.getFile(new File(myBase.getPath()), myPatch.getAfterName()), false); - } else { - newFilePath = (myCurrentBase != null) ? VcsUtil.getFilePath(myCurrentBase) : VcsUtil.getFilePath(myIoCurrentBase, false); - } - myNewContentRevision = new LazyPatchContentRevision(myCurrentBase, newFilePath, myPatch.getAfterVersionId(), myPatch); - if (myCurrentBase != null) { - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - public void run() { - ((LazyPatchContentRevision) myNewContentRevision).getContent(); - } - }); - } - } - } - return myNewContentRevision; + @NotNull + protected FilePath detectNewFilePathForMovedOrModified() { + return FilePatchStatus.MOVED_OR_RENAMED.equals(myStatus) + ? VcsUtil.getFilePath(PathMerger.getFile(new File(myBase.getPath()), myPatch.getAfterName()), false) + : (myCurrentBase != null) ? VcsUtil.getFilePath(myCurrentBase) : VcsUtil.getFilePath(myIoCurrentBase, false); } - public boolean isConflictingChange() { + private boolean isConflictingChange() { if (myConflicts == null) { if ((myCurrentBase != null) && (myNewContentRevision instanceof LazyPatchContentRevision)) { - ((LazyPatchContentRevision) myNewContentRevision).getContent(); - myConflicts = ((LazyPatchContentRevision) myNewContentRevision).isPatchApplyFailed(); - } else { + ((LazyPatchContentRevision)myNewContentRevision).getContent(); + myConflicts = ((LazyPatchContentRevision)myNewContentRevision).isPatchApplyFailed(); + } + else { myConflicts = false; } } return myConflicts; } - public ContentRevision getCurrentRevision() { - if (FilePatchStatus.ADDED.equals(myStatus)) return null; + private ContentRevision getCurrentRevision() { + if (FilePatchStatus.ADDED.equals(myStatus)) return null; if (myCurrentRevision == null) { FilePath filePath = (myCurrentBase != null) ? VcsUtil.getFilePath(myCurrentBase) : VcsUtil.getFilePath(myIoCurrentBase, false); myCurrentRevision = new CurrentContentRevision(filePath); @@ -207,15 +186,17 @@ public class FilePatchInProgress implements Strippable { } public static class PatchChange extends Change { - private final FilePatchInProgress myPatchInProgress; + private final AbstractFilePatchInProgress myPatchInProgress; - public PatchChange(ContentRevision beforeRevision, ContentRevision afterRevision, FilePatchInProgress patchInProgress) { + public PatchChange(ContentRevision beforeRevision, ContentRevision afterRevision, AbstractFilePatchInProgress patchInProgress) { super(beforeRevision, afterRevision, - patchInProgress.isBaseExists() || FilePatchStatus.ADDED.equals(patchInProgress.getStatus()) ? null : FileStatus.MERGED_WITH_CONFLICTS); + patchInProgress.isBaseExists() || FilePatchStatus.ADDED.equals(patchInProgress.getStatus()) + ? null + : FileStatus.MERGED_WITH_CONFLICTS); myPatchInProgress = patchInProgress; } - public FilePatchInProgress getPatchInProgress() { + public AbstractFilePatchInProgress getPatchInProgress() { return myPatchInProgress; } @@ -226,17 +207,9 @@ public class FilePatchInProgress implements Strippable { @Override public DiffRequestPresentable init() throws VcsException { if (myPatchInProgress.isConflictingChange()) { - final Getter revisionTextsGetter = new Getter() { - @Override - public ApplyPatchForBaseRevisionTexts get() { - return ApplyPatchForBaseRevisionTexts.create(project, myPatchInProgress.getCurrentBase(), - VcsUtil.getFilePath(myPatchInProgress.getCurrentBase()), - myPatchInProgress.getPatch(), baseContents); - } - }; - return new MergedDiffRequestPresentable(project, revisionTextsGetter, - myPatchInProgress.getCurrentBase(), myPatchInProgress.getPatch().getAfterVersionId()); - } else { + return myPatchInProgress.diffRequestForConflictingChanges(project, PatchChange.this, baseContents); + } + else { return new ChangeDiffRequestPresentable(project, PatchChange.this); } } @@ -250,6 +223,12 @@ public class FilePatchInProgress implements Strippable { } } + @NotNull + protected DiffRequestPresentable diffRequestForConflictingChanges(@NotNull Project project, + @NotNull PatchChange change, + @NotNull Getter baseContents) { + return new ChangeDiffRequestPresentable(project, change); + } public List getAutoBasesCopy() { final ArrayList result = new ArrayList(myAutoBases.size() + 1); @@ -309,7 +288,7 @@ public class FilePatchInProgress implements Strippable { private final int[] myParts; private StripCapablePath(final String path) { - final String corrected = path.trim().replace('\\', '/'); + final String corrected = PathUtil.toSystemIndependentName(path.trim()); mySourcePath = new StringBuilder(corrected); final String[] steps = corrected.split("/"); myStripMax = steps.length - 1; @@ -342,13 +321,13 @@ public class FilePatchInProgress implements Strippable { public void up() { if (canUp()) { - ++ myCurrentStrip; + ++myCurrentStrip; } } public void down() { if (canDown()) { - -- myCurrentStrip; + --myCurrentStrip; } } @@ -392,14 +371,16 @@ public class FilePatchInProgress implements Strippable { if (patch.getAfterName() != null) { myAfterIdx = 0; myParts[cnt] = new StripCapablePath(patch.getAfterName()); - ++ cnt; - } else { + ++cnt; + } + else { myAfterIdx = -1; } if (cnt < size) { myParts[cnt] = new StripCapablePath(patch.getBeforeName()); myBeforeIdx = cnt; - } else { + } + else { myBeforeIdx = 0; } } @@ -486,7 +467,7 @@ public class FilePatchInProgress implements Strippable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - FilePatchInProgress that = (FilePatchInProgress)o; + AbstractFilePatchInProgress that = (AbstractFilePatchInProgress)o; if (!myStrippable.equals(that.myStrippable)) return false; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java index 0ce41c6adf80..b11fea49e374 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java @@ -200,7 +200,7 @@ public class ApplyPatchAction extends DumbAwareAction { } @Nullable - private static CharSequence getBaseContents(final TextFilePatch patchBase, final CommitContext commitContext, final Project project) { + private static CharSequence getBaseContents(final FilePatch patchBase, final CommitContext commitContext, final Project project) { final BaseRevisionTextPatchEP baseRevisionTextPatchEP = Extensions.findExtension(PatchEP.EP_NAME, project, BaseRevisionTextPatchEP.class); if (baseRevisionTextPatchEP != null) { final String path = patchBase.getBeforeName() == null ? patchBase.getAfterName() : patchBase.getBeforeName(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDefaultExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDefaultExecutor.java index cd4a1feeb267..7df56d21c58e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDefaultExecutor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDefaultExecutor.java @@ -39,12 +39,7 @@ import java.util.LinkedList; import java.util.Map; import java.util.Set; -/** - * @author irengrig - * Date: 2/25/11 - * Time: 5:58 PM - */ -public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor { +public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor { private final Project myProject; public ApplyPatchDefaultExecutor(Project project) { @@ -58,7 +53,7 @@ public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor { } @Override - public void apply(MultiMap patchGroups, + public void apply(MultiMap patchGroups, LocalChangeList localList, String fileName, TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo) { @@ -69,8 +64,8 @@ public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor { for (VirtualFile base : patchGroups.keySet()) { final PatchApplier patchApplier = new PatchApplier(myProject, base, ObjectsConvertor.convert(patchGroups.get(base), - new Convertor() { - public FilePatch convert(FilePatchInProgress o) { + new Convertor() { + public FilePatch convert(AbstractFilePatchInProgress o) { return o.getPatch(); } }), localList, null, commitContext); @@ -144,10 +139,10 @@ public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor { } } - public static Set pathsFromGroups(MultiMap patchGroups) { + public static Set pathsFromGroups(MultiMap patchGroups) { final Set selectedPaths = new HashSet(); - final Collection values = patchGroups.values(); - for (FilePatchInProgress value : values) { + final Collection values = patchGroups.values(); + for (AbstractFilePatchInProgress value : values) { final String path = value.getPatch().getBeforeName() == null ? value.getPatch().getAfterName() : value.getPatch().getBeforeName(); selectedPaths.add(path); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index afa5384b8557..4172471be0de 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -20,10 +20,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diff.impl.patch.PatchReader; -import com.intellij.openapi.diff.impl.patch.PatchSyntaxException; -import com.intellij.openapi.diff.impl.patch.PatchVirtualFileReader; -import com.intellij.openapi.diff.impl.patch.TextFilePatch; +import com.intellij.openapi.diff.impl.patch.*; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; @@ -40,12 +37,13 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ObjectsConvertor; import com.intellij.openapi.vcs.VcsBundle; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; -import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable; -import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; -import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; +import com.intellij.openapi.vcs.changes.actions.*; +import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; +import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryFile; import com.intellij.openapi.vcs.changes.ui.*; import com.intellij.openapi.vfs.*; import com.intellij.ui.DocumentAdapter; @@ -76,7 +74,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { private final ZipperUpdater myLoadQueue; private final TextFieldWithBrowseButton myPatchFile; - private final List myPatches; + private final List myPatches; + private final List myBinaryShelvedPatches; private final MyChangeTreeList myChangesTreeList; private JComponent myCenterPanel; @@ -98,9 +97,20 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { private final boolean myCanChangePatchFile; private String myHelpId = "reference.dialogs.vcs.patch.apply"; + + public ApplyPatchDifferentiatedDialog(final Project project, + final ApplyPatchExecutor callback, + final List executors, + @NotNull final ApplyPatchMode applyPatchMode, + @NotNull final VirtualFile patchFile, + List binaryShelvedPatches) { + this(project, callback, executors, applyPatchMode, patchFile, null, null, binaryShelvedPatches); + } + + public ApplyPatchDifferentiatedDialog(final Project project, final ApplyPatchExecutor callback, final List executors, @NotNull final ApplyPatchMode applyPatchMode, @NotNull final VirtualFile patchFile) { - this(project, callback, executors, applyPatchMode, patchFile, null, null); + this(project, callback, executors, applyPatchMode, patchFile, null, null, null); } public ApplyPatchDifferentiatedDialog(final Project project, @@ -109,7 +119,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @NotNull final ApplyPatchMode applyPatchMode, @NotNull final List patches, @Nullable final LocalChangeList defaultList) { - this(project, callback, executors, applyPatchMode, null, patches, defaultList); + this(project, callback, executors, applyPatchMode, null, patches, defaultList, null); } private ApplyPatchDifferentiatedDialog(final Project project, @@ -118,7 +128,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @NotNull final ApplyPatchMode applyPatchMode, @Nullable final VirtualFile patchFile, @Nullable final List patches, - @Nullable final LocalChangeList defaultList) { + @Nullable final LocalChangeList defaultList, + @Nullable List binaryShelvedPatches) { super(project, true); myCallback = callback; myExecutors = executors; @@ -129,17 +140,18 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { descriptor.setTitle(VcsBundle.message("patch.apply.select.title")); myProject = project; - myPatches = new LinkedList(); + myPatches = new LinkedList(); myRecentPathFileChange = new AtomicReference(); - myChangesTreeList = new MyChangeTreeList(project, Collections.emptyList(), + myBinaryShelvedPatches = binaryShelvedPatches; + myChangesTreeList = new MyChangeTreeList(project, Collections.emptyList(), new Runnable() { public void run() { final NamedTrinity includedTrinity = new NamedTrinity(); - final Collection includedChanges = + final Collection includedChanges = myChangesTreeList.getIncludedChanges(); final Set> set = new HashSet>(); - for (FilePatchInProgress.PatchChange change : includedChanges) { - final TextFilePatch patch = change.getPatchInProgress().getPatch(); + for (AbstractFilePatchInProgress.PatchChange change : includedChanges) { + final FilePatch patch = change.getPatchInProgress().getPatch(); final Couple pair = Couple.of(patch.getBeforeName(), patch.getAfterName()); if (set.contains(pair)) continue; set.add(pair); @@ -226,8 +238,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myLoadQueue.queue(myUpdater); } - private void init(@NotNull List patches, final LocalChangeList localChangeList) { - final List matchedPatches = new MatchPatchPaths(myProject).execute(patches); + private void init(List patches, final LocalChangeList localChangeList) { + final List matchedPatches = new MatchPatchPaths(myProject).execute(patches); + //todo add shelved binary patches ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { if (localChangeList != null) { @@ -275,10 +288,10 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } private void runExecutor(ApplyPatchExecutor executor) { - final Collection included = getIncluded(); + final Collection included = getIncluded(); if (included.isEmpty()) return; - final MultiMap patchGroups = new MultiMap(); - for (FilePatchInProgress patchInProgress : included) { + final MultiMap patchGroups = new MultiMap(); + for (AbstractFilePatchInProgress patchInProgress : included) { patchGroups.putValue(patchInProgress.getBase(), patchInProgress); } final LocalChangeList selected = getSelectedChangeList(); @@ -325,9 +338,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { final PatchReader patchReader = loadPatches(filePresentation); if (patchReader == null) return; - List textPatches = patchReader.getPatches(); - final List matchedPatches = - textPatches != null ? new MatchPatchPaths(myProject).execute(textPatches) : ContainerUtil.emptyList(); + List filePatches = ContainerUtil.newArrayList(patchReader.getPatches()); + filePatches.addAll(myBinaryShelvedPatches); + final List matchedPatches = new MatchPatchPaths(myProject).execute(filePatches); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { @@ -394,7 +407,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { private void reset() { myPatches.clear(); - myChangesTreeList.setChangesToDisplay(Collections.emptyList()); + myChangesTreeList.setChangesToDisplay(Collections.emptyList()); myChangesTreeList.repaint(); myContainBasedChanges = false; paintBusy(false); @@ -469,40 +482,41 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private static class MyChangeTreeList extends ChangesTreeList { + private static class MyChangeTreeList extends ChangesTreeList { private MyChangeTreeList(Project project, - Collection initiallyIncluded, + Collection initiallyIncluded, @Nullable Runnable inclusionListener, @Nullable ChangeNodeDecorator decorator) { super(project, initiallyIncluded, true, false, inclusionListener, decorator); } @Override - protected DefaultTreeModel buildTreeModel(List changes, ChangeNodeDecorator changeNodeDecorator) { + protected DefaultTreeModel buildTreeModel(List changes, + ChangeNodeDecorator changeNodeDecorator) { TreeModelBuilder builder = new TreeModelBuilder(myProject, false); return builder.buildModel(ObjectsConvertor.convert(changes, - new Convertor() { - public Change convert(FilePatchInProgress.PatchChange o) { + new Convertor() { + public Change convert(AbstractFilePatchInProgress.PatchChange o) { return o; } }), changeNodeDecorator); } @Override - protected List getSelectedObjects(ChangesBrowserNode node) { + protected List getSelectedObjects(ChangesBrowserNode node) { final List under = node.getAllChangesUnder(); - return ObjectsConvertor.convert(under, new Convertor() { - public FilePatchInProgress.PatchChange convert(Change o) { - return (FilePatchInProgress.PatchChange)o; + return ObjectsConvertor.convert(under, new Convertor() { + public AbstractFilePatchInProgress.PatchChange convert(Change o) { + return (AbstractFilePatchInProgress.PatchChange)o; } }); } @Override - protected FilePatchInProgress.PatchChange getLeadSelectedObject(ChangesBrowserNode node) { + protected AbstractFilePatchInProgress.PatchChange getLeadSelectedObject(ChangesBrowserNode node) { final Object o = node.getUserObject(); - if (o instanceof FilePatchInProgress.PatchChange) { - return (FilePatchInProgress.PatchChange)o; + if (o instanceof AbstractFilePatchInProgress.PatchChange) { + return (AbstractFilePatchInProgress.PatchChange)o; } return null; } @@ -518,10 +532,10 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void actionPerformed(AnActionEvent e) { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); if ((selectedChanges.size() >= 1) && (sameBase(selectedChanges))) { - final FilePatchInProgress.PatchChange patchChange = selectedChanges.get(0); - final FilePatchInProgress patch = patchChange.getPatchInProgress(); + final AbstractFilePatchInProgress.PatchChange patchChange = selectedChanges.get(0); + final AbstractFilePatchInProgress patch = patchChange.getPatchInProgress(); final List autoBases = patch.getAutoBasesCopy(); if (autoBases.isEmpty() || (autoBases.size() == 1 && autoBases.get(0).equals(patch.getBase()))) { myNewBaseSelector.run(); @@ -536,14 +550,14 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void update(AnActionEvent e) { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); e.getPresentation().setEnabled((selectedChanges.size() >= 1) && (sameBase(selectedChanges))); } } - private static boolean sameBase(final List selectedChanges) { + private static boolean sameBase(final List selectedChanges) { VirtualFile base = null; - for (FilePatchInProgress.PatchChange change : selectedChanges) { + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { final VirtualFile changeBase = change.getPatchInProgress().getBase(); if (base == null) { base = changeBase; @@ -556,9 +570,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } private void updateTree(boolean doInitCheck) { - final List patchesToSelect = changes2patches(myChangesTreeList.getSelectedChanges()); - final List changes = getAllChanges(); - final Collection included = getIncluded(doInitCheck, changes); + final List patchesToSelect = changes2patches(myChangesTreeList.getSelectedChanges()); + final List changes = getAllChanges(); + final Collection included = getIncluded(doInitCheck, changes); myChangesTreeList.setChangesToDisplay(changes); myChangesTreeList.setIncludedChanges(included); @@ -567,8 +581,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } myChangesTreeList.repaint(); if ((!doInitCheck) && patchesToSelect != null) { - final List toSelect = new ArrayList(patchesToSelect.size()); - for (FilePatchInProgress.PatchChange change : changes) { + final List toSelect = + new ArrayList(patchesToSelect.size()); + for (AbstractFilePatchInProgress.PatchChange change : changes) { if (patchesToSelect.contains(change.getPatchInProgress())) { toSelect.add(change); } @@ -577,7 +592,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } myContainBasedChanges = false; - for (FilePatchInProgress patch : myPatches) { + for (AbstractFilePatchInProgress patch : myPatches) { if (patch.baseExistsOrAdded()) { myContainBasedChanges = true; break; @@ -585,17 +600,17 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private List getAllChanges() { + private List getAllChanges() { return ObjectsConvertor.convert(myPatches, - new Convertor() { - public FilePatchInProgress.PatchChange convert(FilePatchInProgress o) { + new Convertor() { + public AbstractFilePatchInProgress.PatchChange convert(AbstractFilePatchInProgress o) { return o.getChange(); } }); } - private static void acceptChange(final NamedTrinity trinity, final FilePatchInProgress.PatchChange change) { - final FilePatchInProgress patchInProgress = change.getPatchInProgress(); + private static void acceptChange(final NamedTrinity trinity, final AbstractFilePatchInProgress.PatchChange change) { + final AbstractFilePatchInProgress patchInProgress = change.getPatchInProgress(); if (FilePatchStatus.ADDED.equals(patchInProgress.getStatus())) { trinity.plusAdded(); } @@ -607,16 +622,17 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private Collection getIncluded(boolean doInitCheck, List changes) { + private Collection getIncluded(boolean doInitCheck, + List changes) { final NamedTrinity totalTrinity = new NamedTrinity(); final NamedTrinity includedTrinity = new NamedTrinity(); - final Collection included = new LinkedList(); + final Collection included = new LinkedList(); if (doInitCheck) { - for (FilePatchInProgress.PatchChange change : changes) { + for (AbstractFilePatchInProgress.PatchChange change : changes) { acceptChange(totalTrinity, change); - final FilePatchInProgress filePatchInProgress = change.getPatchInProgress(); - if (filePatchInProgress.baseExistsOrAdded()) { + final AbstractFilePatchInProgress abstractFilePatchInProgress = change.getPatchInProgress(); + if (abstractFilePatchInProgress.baseExistsOrAdded()) { acceptChange(includedTrinity, change); included.add(change); } @@ -624,14 +640,14 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } else { // todo maybe written pretty - final Collection includedNow = myChangesTreeList.getIncludedChanges(); - final Set toBeIncluded = new HashSet(); - for (FilePatchInProgress.PatchChange change : includedNow) { - final FilePatchInProgress patch = change.getPatchInProgress(); + final Collection includedNow = myChangesTreeList.getIncludedChanges(); + final Set toBeIncluded = new HashSet(); + for (AbstractFilePatchInProgress.PatchChange change : includedNow) { + final AbstractFilePatchInProgress patch = change.getPatchInProgress(); toBeIncluded.add(patch); } - for (FilePatchInProgress.PatchChange change : changes) { - final FilePatchInProgress patch = change.getPatchInProgress(); + for (AbstractFilePatchInProgress.PatchChange change : changes) { + final AbstractFilePatchInProgress patch = change.getPatchInProgress(); acceptChange(totalTrinity, change); if (toBeIncluded.contains(patch) && patch.baseExistsOrAdded()) { acceptChange(includedTrinity, change); @@ -653,10 +669,10 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { return; } - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); if (selectedChanges.size() >= 1) { - for (FilePatchInProgress.PatchChange patchChange : selectedChanges) { - final FilePatchInProgress patch = patchChange.getPatchInProgress(); + for (AbstractFilePatchInProgress.PatchChange patchChange : selectedChanges) { + final AbstractFilePatchInProgress patch = patchChange.getPatchInProgress(); patch.setNewBase(selectedFile); } updateTree(false); @@ -664,9 +680,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private static List changes2patches(final List selectedChanges) { - return ObjectsConvertor.convert(selectedChanges, new Convertor() { - public FilePatchInProgress convert(FilePatchInProgress.PatchChange o) { + private static List changes2patches(final List selectedChanges) { + return ObjectsConvertor.convert(selectedChanges, new Convertor() { + public AbstractFilePatchInProgress convert(AbstractFilePatchInProgress.PatchChange o) { return o.getPatchInProgress(); } }); @@ -691,10 +707,10 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myNewBaseSelector.run(); return null; } - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); if (selectedChanges.size() >= 1) { - for (FilePatchInProgress.PatchChange patchChange : selectedChanges) { - final FilePatchInProgress patch = patchChange.getPatchInProgress(); + for (AbstractFilePatchInProgress.PatchChange patchChange : selectedChanges) { + final AbstractFilePatchInProgress patch = patchChange.getPatchInProgress(); patch.setNewBase(selectedValue); } updateTree(false); @@ -789,11 +805,11 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { private static class MyChangeNodeDecorator implements ChangeNodeDecorator { public void decorate(Change change, SimpleColoredComponent component, boolean isShowFlatten) { - if (change instanceof FilePatchInProgress.PatchChange) { - final FilePatchInProgress.PatchChange patchChange = (FilePatchInProgress.PatchChange)change; + if (change instanceof AbstractFilePatchInProgress.PatchChange) { + final AbstractFilePatchInProgress.PatchChange patchChange = (AbstractFilePatchInProgress.PatchChange)change; if (!isShowFlatten) { // add change sub path - final TextFilePatch filePatch = patchChange.getPatchInProgress().getPatch(); + final FilePatch filePatch = patchChange.getPatchInProgress().getPatch(); final String patchPath = filePatch.getAfterName() == null ? filePatch.getBeforeName() : filePatch.getAfterName(); component.append(" "); component.append("[" + patchPath + "]", SimpleTextAttributes.GRAY_ATTRIBUTES); @@ -817,8 +833,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } public List> stressPartsOfFileName(final Change change, final String parentPath) { - if (change instanceof FilePatchInProgress.PatchChange) { - final FilePatchInProgress.PatchChange patchChange = (FilePatchInProgress.PatchChange)change; + if (change instanceof AbstractFilePatchInProgress.PatchChange) { + final AbstractFilePatchInProgress.PatchChange patchChange = (AbstractFilePatchInProgress.PatchChange)change; final String basePath = patchChange.getPatchInProgress().getBase().getPath(); final String basePathCorrected = basePath.trim().replace('/', File.separatorChar); if (parentPath.startsWith(basePathCorrected)) { @@ -833,10 +849,10 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private Collection getIncluded() { + private Collection getIncluded() { return ObjectsConvertor.convert(myChangesTreeList.getIncludedChanges(), - new Convertor() { - public FilePatchInProgress convert(FilePatchInProgress.PatchChange o) { + new Convertor() { + public AbstractFilePatchInProgress convert(AbstractFilePatchInProgress.PatchChange o) { return o.getPatchInProgress(); } }); @@ -859,8 +875,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void actionPerformed(AnActionEvent e) { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); - for (FilePatchInProgress.PatchChange change : selectedChanges) { + final List selectedChanges = myChangesTreeList.getSelectedChanges(); + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { change.getPatchInProgress().setZero(); } updateTree(false); @@ -880,17 +896,17 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void actionPerformed(AnActionEvent e) { if (!isEnabled()) return; - final List selectedChanges = myChangesTreeList.getSelectedChanges(); - for (FilePatchInProgress.PatchChange change : selectedChanges) { + final List selectedChanges = myChangesTreeList.getSelectedChanges(); + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { change.getPatchInProgress().down(); } updateTree(false); } private boolean isEnabled() { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); if (selectedChanges.isEmpty()) return false; - for (FilePatchInProgress.PatchChange change : selectedChanges) { + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { if (!change.getPatchInProgress().canDown()) return false; } return true; @@ -910,17 +926,17 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void actionPerformed(AnActionEvent e) { if (!isEnabled()) return; - final List selectedChanges = myChangesTreeList.getSelectedChanges(); - for (FilePatchInProgress.PatchChange change : selectedChanges) { + final List selectedChanges = myChangesTreeList.getSelectedChanges(); + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { change.getPatchInProgress().up(); } updateTree(false); } private boolean isEnabled() { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); + final List selectedChanges = myChangesTreeList.getSelectedChanges(); if (selectedChanges.isEmpty()) return false; - for (FilePatchInProgress.PatchChange change : selectedChanges) { + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { if (!change.getPatchInProgress().canUp()) return false; } return true; @@ -934,8 +950,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { @Override public void actionPerformed(AnActionEvent e) { - final List selectedChanges = myChangesTreeList.getSelectedChanges(); - for (FilePatchInProgress.PatchChange change : selectedChanges) { + final List selectedChanges = myChangesTreeList.getSelectedChanges(); + for (AbstractFilePatchInProgress.PatchChange change : selectedChanges) { change.getPatchInProgress().reset(); } updateTree(false); @@ -961,9 +977,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { private void showDiff() { if (ChangeListManager.getInstance(myProject).isFreezedWithNotification(null)) return; if (myPatches.isEmpty() || (!myContainBasedChanges)) return; - final List changes = getAllChanges(); + final List changes = getAllChanges(); Collections.sort(changes, myMyChangeComparator); - List selectedChanges = myChangesTreeList.getSelectedChanges(); + List selectedChanges = myChangesTreeList.getSelectedChanges(); int selectedIdx = 0; final ArrayList diffRequestPresentableList = new ArrayList(changes.size()); @@ -971,19 +987,39 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { selectedChanges = changes; } if (!selectedChanges.isEmpty()) { - final FilePatchInProgress.PatchChange c = selectedChanges.get(0); - for (FilePatchInProgress.PatchChange change : changes) { - final FilePatchInProgress patchInProgress = change.getPatchInProgress(); + final AbstractFilePatchInProgress.PatchChange c = selectedChanges.get(0); + for (AbstractFilePatchInProgress.PatchChange change : changes) { + final AbstractFilePatchInProgress patchInProgress = change.getPatchInProgress(); if (!patchInProgress.baseExistsOrAdded()) continue; - final TextFilePatch patch = patchInProgress.getPatch(); - final String path = patch.getBeforeName() == null ? patch.getAfterName() : patch.getBeforeName(); - final DiffRequestPresentable diffRequestPresentable = - change.createDiffRequestPresentable(myProject, new Getter() { + DiffRequestPresentable diffRequestPresentable; + if (patchInProgress instanceof BinaryFilePatchInProgress) { + final ShelvedBinaryFile file = ((BinaryFilePatchInProgress)patchInProgress).getPatch().getShelvedBinaryFile(); + diffRequestPresentable = new DiffRequestPresentableProxy() { + @NotNull @Override - public CharSequence get() { - return myReader.getBaseRevision(myProject, path); + public DiffRequestPresentable init() throws VcsException { + return new ChangeDiffRequestPresentable(myProject, file.createChange(myProject)); } - }); + + @Override + public String getPathPresentation() { + final File file1 = new File(VfsUtilCore.virtualToIoFile(patchInProgress.getBase()), + file.AFTER_PATH == null ? file.BEFORE_PATH : file.AFTER_PATH); + return FileUtil.toSystemDependentName(file1.getPath()); + } + }; + } + else { + final FilePatch patch = patchInProgress.getPatch(); + final String path = patch.getBeforeName() == null ? patch.getAfterName() : patch.getBeforeName(); + diffRequestPresentable = + change.createDiffRequestPresentable(myProject, new Getter() { + @Override + public CharSequence get() { + return myReader.getBaseRevision(myProject, path); + } + }); + } if (diffRequestPresentable != null) { diffRequestPresentableList.add(diffRequestPresentable); } @@ -997,8 +1033,8 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } - private class MyChangeComparator implements Comparator { - public int compare(FilePatchInProgress.PatchChange o1, FilePatchInProgress.PatchChange o2) { + private class MyChangeComparator implements Comparator { + public int compare(AbstractFilePatchInProgress.PatchChange o1, AbstractFilePatchInProgress.PatchChange o2) { if (PropertiesComponent.getInstance(myProject).isTrueValue("ChangesBrowser.SHOW_FLATTEN")) { return o1.getPatchInProgress().getIoCurrentBase().getName().compareTo(o2.getPatchInProgress().getIoCurrentBase().getName()); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchExecutor.java index 268d8decaa46..42ddc3ab9429 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchExecutor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchExecutor.java @@ -28,9 +28,10 @@ import java.util.Map; * Date: 2/25/11 * Time: 5:18 PM */ -public interface ApplyPatchExecutor { +public interface ApplyPatchExecutor { String getName(); - void apply(final MultiMap patchGroups, + + void apply(final MultiMap patchGroups, final LocalChangeList localList, String fileName, TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchIterator.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchIterator.java index 591c31d9ffc3..67037c89bee8 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchIterator.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchIterator.java @@ -38,7 +38,7 @@ public class AutoMatchIterator { myStrategies.add(new DefaultPatchStrategy(baseDir)); } - public List execute(final List list) { + public List execute(final List list) { final List creations = new LinkedList(); final PatchBaseDirectoryDetector directoryDetector = PatchBaseDirectoryDetector.getInstance(myProject); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java index 308281e06606..f1a14ce5a6c9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java @@ -28,21 +28,24 @@ import java.util.List; abstract class AutoMatchStrategy { protected final VirtualFile myBaseDir; - protected MultiMap myFolderDecisions; - protected final List myResult; + protected MultiMap myFolderDecisions; + protected final List myResult; AutoMatchStrategy(final VirtualFile baseDir) { myBaseDir = baseDir; - myResult = new LinkedList(); + myResult = new LinkedList(); myFolderDecisions = MultiMap.createSet(); } public abstract void acceptPatch(TextFilePatch patch, final Collection foundByName); + public abstract void processCreation(TextFilePatch creation); + public abstract void beforeCreations(); + public abstract boolean succeeded(); - public List getResult() { + public List getResult() { return myResult; } @@ -65,9 +68,10 @@ abstract class AutoMatchStrategy { protected void processCreationBasedOnFolderDecisions(final TextFilePatch creation) { final Collection variants = suggestFolderForCreation(creation); if (variants != null) { - myResult.add(new FilePatchInProgress(creation, variants, myBaseDir)); - } else { - myResult.add(new FilePatchInProgress(creation, null, myBaseDir)); + myResult.add(new TextFilePatchInProgress(creation, variants, myBaseDir)); + } + else { + myResult.add(new TextFilePatchInProgress(creation, null, myBaseDir)); } } @@ -79,7 +83,7 @@ abstract class AutoMatchStrategy { final Collection result = new LinkedList(); for (VirtualFile vf : in) { final String vfPath = vf.getPath(); - if ((caseSensitive && vfPath.endsWith(path)) || ((! caseSensitive) && StringUtil.endsWithIgnoreCase(vfPath, path))) { + if ((caseSensitive && vfPath.endsWith(path)) || ((!caseSensitive) && StringUtil.endsWithIgnoreCase(vfPath, path))) { result.add(vf); } } @@ -95,28 +99,32 @@ abstract class AutoMatchStrategy { } @Nullable - protected FilePatchInProgress processMatch(final TextFilePatch patch, final VirtualFile file) { + protected TextFilePatchInProgress processMatch(final TextFilePatch patch, final VirtualFile file) { final String beforeName = patch.getBeforeName(); if (beforeName == null) return null; final String[] parts = beforeName.replace('\\', '/').split("/"); VirtualFile parent = file.getParent(); int idx = parts.length - 2; while ((parent != null) && (idx >= 0)) { - if (! parent.getName().equals(parts[idx])) { + if (!parent.getName().equals(parts[idx])) { break; } parent = parent.getParent(); - -- idx; + --idx; } if (parent != null) { - final FilePatchInProgress result = new FilePatchInProgress(patch, null, myBaseDir); + final TextFilePatchInProgress result = new TextFilePatchInProgress(patch, null, myBaseDir); result.setNewBase(parent); int numDown = idx + 1; - for (int i = 0; i < numDown; i++) { - result.up(); - } + processStipUp(result, numDown); return result; } return null; } + + public static void processStipUp(AbstractFilePatchInProgress patchInProgress, int num) { + for (int i = 0; i < num; i++) { + patchInProgress.up(); + } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/BinaryFilePatchInProgress.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/BinaryFilePatchInProgress.java new file mode 100644 index 000000000000..148a6135a475 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/BinaryFilePatchInProgress.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.vcs.FilePath; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager.ShelvedBinaryFilePatch; +import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryContentRevision; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcsUtil.VcsUtil; + +import java.util.Collection; + +public class BinaryFilePatchInProgress extends AbstractFilePatchInProgress { + + protected BinaryFilePatchInProgress(ShelvedBinaryFilePatch patch, + Collection autoBases, + VirtualFile baseDir) { + super(ShelvedBinaryFilePatch.patchCopy(patch), autoBases, baseDir); + } + + @Override + public ContentRevision getNewContentRevision() { + if (FilePatchStatus.DELETED.equals(myStatus)) return null; + + if (myNewContentRevision != null) return myNewContentRevision; + if (myPatch.getAfterFileName() != null) { + final FilePath newFilePath = FilePatchStatus.ADDED.equals(myStatus) + ? VcsUtil.getFilePathOnNonLocal(myIoCurrentBase.getAbsolutePath(), + false) + : detectNewFilePathForMovedOrModified(); + myNewContentRevision = new ShelvedBinaryContentRevision(newFilePath, myPatch.getShelvedBinaryFile().SHELVED_PATH); + } + return myNewContentRevision; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchStrategy.java index ef8c21463504..833d164d68ad 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchStrategy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/DefaultPatchStrategy.java @@ -27,9 +27,9 @@ public class DefaultPatchStrategy extends AutoMatchStrategy { @Override public void acceptPatch(TextFilePatch patch, Collection foundByName) { - FilePatchInProgress longest = null; + TextFilePatchInProgress longest = null; for (VirtualFile file : foundByName) { - final FilePatchInProgress current = processMatch(patch, file); + final TextFilePatchInProgress current = processMatch(patch, file); if ((current != null) && ((longest == null) || (longest.getCurrentStrip() > current.getCurrentStrip()))) { longest = current; } @@ -38,7 +38,7 @@ public class DefaultPatchStrategy extends AutoMatchStrategy { registerFolderDecision(longest.getPatch().getBeforeName(), longest.getBase()); myResult.add(longest); } else { - myResult.add(new FilePatchInProgress(patch, null, myBaseDir)); + myResult.add(new TextFilePatchInProgress(patch, null, myBaseDir)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ImportToShelfExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ImportToShelfExecutor.java index 79d177e49f35..78c50dc26ef9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ImportToShelfExecutor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ImportToShelfExecutor.java @@ -48,7 +48,7 @@ import java.util.*; * Date: 2/25/11 * Time: 6:21 PM */ -public class ImportToShelfExecutor implements ApplyPatchExecutor { +public class ImportToShelfExecutor implements ApplyPatchExecutor { public static final String IMPORT_TO_SHELF = "Import to shelf"; private final Project myProject; @@ -62,7 +62,7 @@ public class ImportToShelfExecutor implements ApplyPatchExecutor { } @Override - public void apply(final MultiMap patchGroups, + public void apply(final MultiMap patchGroups, LocalChangeList localList, final String fileName, final TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo) { @@ -75,8 +75,8 @@ public class ImportToShelfExecutor implements ApplyPatchExecutor { for (VirtualFile virtualFile : patchGroups.keySet()) { final File ioCurrentBase = new File(virtualFile.getPath()); allPatches.addAll(ObjectsConvertor.convert(patchGroups.get(virtualFile), - new Convertor() { - public TextFilePatch convert(FilePatchInProgress o) { + new Convertor() { + public TextFilePatch convert(TextFilePatchInProgress o) { final TextFilePatch was = o.getPatch(); was.setBeforeName(FileUtil.toSystemIndependentName(FileUtil.getRelativePath(ioBase, new File(ioCurrentBase, was.getBeforeName())))); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/IndividualPiecesStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/IndividualPiecesStrategy.java index 7b0155ef9902..780c8b167343 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/IndividualPiecesStrategy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/IndividualPiecesStrategy.java @@ -17,11 +17,8 @@ package com.intellij.openapi.vcs.changes.patch; import com.intellij.openapi.diff.impl.patch.TextFilePatch; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.containers.MultiMap; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; class IndividualPiecesStrategy extends AutoMatchStrategy { private boolean mySucceeded; @@ -39,9 +36,9 @@ class IndividualPiecesStrategy extends AutoMatchStrategy { final Collection variants = filterVariants(patch, foundByName); if ((variants != null) && (! variants.isEmpty())) { - final FilePatchInProgress filePatchInProgress = new FilePatchInProgress(patch, variants, myBaseDir); - myResult.add(filePatchInProgress); - registerFolderDecision(patch.getBeforeName(), filePatchInProgress.getBase()); + final TextFilePatchInProgress textFilePatchInProgress = new TextFilePatchInProgress(patch, variants, myBaseDir); + myResult.add(textFilePatchInProgress); + registerFolderDecision(patch.getBeforeName(), textFilePatchInProgress.getBase()); } else { mySucceeded = false; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MatchPatchPaths.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MatchPatchPaths.java index 9d269ccd4d73..a66768779fcf 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MatchPatchPaths.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MatchPatchPaths.java @@ -16,15 +16,18 @@ package com.intellij.openapi.vcs.changes.patch; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diff.impl.patch.FilePatch; import com.intellij.openapi.diff.impl.patch.TextFilePatch; import com.intellij.openapi.diff.impl.patch.apply.GenericPatchApplier; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.ObjectsConvertor; +import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager.ShelvedBinaryFilePatch; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -36,6 +39,8 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import static com.intellij.openapi.vcs.changes.patch.AutoMatchStrategy.processStipUp; + public class MatchPatchPaths { private static final int BIG_FILE_BOUND = 100000; private final Project myProject; @@ -46,34 +51,34 @@ public class MatchPatchPaths { myBaseDir = myProject.getBaseDir(); } - public List execute(@NotNull final List list) { + public List execute(@NotNull final List list) { final PatchBaseDirectoryDetector directoryDetector = PatchBaseDirectoryDetector.getInstance(myProject); final List candidates = new ArrayList(list.size()); - final List newOrWithoutMatches = new ArrayList(); + final List newOrWithoutMatches = new ArrayList(); findCandidates(list, directoryDetector, candidates, newOrWithoutMatches); - final MultiMap result = new MultiMap(); + final MultiMap result = new MultiMap(); // process exact matches: if one, leave and extract. if several - leave only them filterExactMatches(candidates, result); // partially check by context - selectByContext(candidates, result); + selectByContextOrByStrip(candidates, result); // for text only // created or no variants workWithNotExisting(directoryDetector, newOrWithoutMatches, result); - return new ArrayList(result.values()); + return new ArrayList(result.values()); } - private void workWithNotExisting(PatchBaseDirectoryDetector directoryDetector, - List newOrWithoutMatches, - MultiMap result) { - for (TextFilePatch patch : newOrWithoutMatches) { + private void workWithNotExisting(@NotNull PatchBaseDirectoryDetector directoryDetector, + @NotNull List newOrWithoutMatches, + @NotNull MultiMap result) { + for (FilePatch patch : newOrWithoutMatches) { final String[] strings = patch.getAfterName().replace('\\', '/').split("/"); Pair best = null; for (int i = strings.length - 2; i >= 0; --i) { final String name = strings[i]; final Collection files = findFilesFromIndex(directoryDetector, name); - if (! files.isEmpty()) { + if (!files.isEmpty()) { // check all candidates for (VirtualFile file : files) { Pair pair = compareNamesImpl(strings, file, i); @@ -86,53 +91,44 @@ public class MatchPatchPaths { } } if (best != null) { - final FilePatchInProgress patchInProgress = new FilePatchInProgress(patch, null, myBaseDir); - patchInProgress.setNewBase(best.getFirst()); - int numDown = best.getSecond(); - for (int i = 0; i < numDown; i++) { - patchInProgress.up(); - } + final AbstractFilePatchInProgress patchInProgress = createPatchInProgress(patch, best.getFirst()); + if (patchInProgress == null) break; + processStipUp(patchInProgress, best.getSecond()); result.putValue(best.getFirst(), patchInProgress); } else { - final FilePatchInProgress patchInProgress = new FilePatchInProgress(patch, null, myBaseDir); + final AbstractFilePatchInProgress patchInProgress = createPatchInProgress(patch, myBaseDir); + if (patchInProgress == null) break; result.putValue(myBaseDir, patchInProgress); } } } - private static void selectByContext(List candidates, MultiMap result) { + private static void selectByContextOrByStrip(@NotNull List candidates, + @NotNull MultiMap result) { for (final PatchAndVariants candidate : candidates) { - int maxLines = -100; - FilePatchInProgress best = null; - for (FilePatchInProgress variant : candidate.getVariants()) { - final int lines = getMatchingLines(variant); - if (lines > maxLines) { - maxLines = lines; - best = variant; - } - } - putSelected(result, candidate.getVariants(), best); + candidate.findAndAddBestVariant(result); } } - private static void filterExactMatches(List candidates, MultiMap result) { + private static void filterExactMatches(@NotNull List candidates, + @NotNull MultiMap result) { for (Iterator iterator = candidates.iterator(); iterator.hasNext(); ) { final PatchAndVariants candidate = iterator.next(); if (candidate.getVariants().size() == 1) { - final FilePatchInProgress oneCandidate = candidate.getVariants().get(0); + final AbstractFilePatchInProgress oneCandidate = candidate.getVariants().get(0); result.putValue(oneCandidate.getBase(), oneCandidate); iterator.remove(); } else { - final List exact = new ArrayList(candidate.getVariants().size()); - for (FilePatchInProgress patch : candidate.getVariants()) { + final List exact = new ArrayList(candidate.getVariants().size()); + for (AbstractFilePatchInProgress patch : candidate.getVariants()) { if (patch.getCurrentStrip() == 0) { exact.add(patch); } } if (exact.size() == 1) { - final FilePatchInProgress patchInProgress = exact.get(0); + final AbstractFilePatchInProgress patchInProgress = exact.get(0); putSelected(result, candidate.getVariants(), patchInProgress); iterator.remove(); } @@ -143,10 +139,10 @@ public class MatchPatchPaths { } } - private void findCandidates(List list, - final PatchBaseDirectoryDetector directoryDetector, - List candidates, List newOrWithoutMatches) { - for (final TextFilePatch patch : list) { + private void findCandidates(@NotNull List list, + @NotNull final PatchBaseDirectoryDetector directoryDetector, + @NotNull List candidates, @NotNull List newOrWithoutMatches) { + for (final FilePatch patch : list) { final String fileName = patch.getBeforeFileName(); if (patch.isNewFile() || (patch.getBeforeName() == null)) { newOrWithoutMatches.add(patch); @@ -164,12 +160,14 @@ public class MatchPatchPaths { newOrWithoutMatches.add(patch); } else { - final List variants = ObjectsConvertor.convert(files, new Convertor() { - @Override - public FilePatchInProgress convert(VirtualFile o) { - return processMatch(patch, o); - } - }, ObjectsConvertor.NOT_NULL); + //files order is not defined, so get the best variant depends on it, too + final List variants = + ObjectsConvertor.convert(files, new Convertor() { + @Override + public AbstractFilePatchInProgress convert(VirtualFile o) { + return processMatch(patch, o); + } + }, ObjectsConvertor.NOT_NULL); if (variants.isEmpty()) { newOrWithoutMatches.add(patch); // just to be sure } @@ -189,19 +187,19 @@ public class MatchPatchPaths { }); } - private static void putSelected(MultiMap result, - final List variants, - FilePatchInProgress patchInProgress) { - patchInProgress.setAutoBases(ObjectsConvertor.convert(variants, new Convertor() { + private static void putSelected(@NotNull MultiMap result, + @NotNull final List variants, + @NotNull AbstractFilePatchInProgress patchInProgress) { + patchInProgress.setAutoBases(ObjectsConvertor.convert(variants, new Convertor() { @Override - public VirtualFile convert(FilePatchInProgress o) { + public VirtualFile convert(AbstractFilePatchInProgress o) { return o.getBase(); } }, ObjectsConvertor.NOT_NULL)); result.putValue(patchInProgress.getBase(), patchInProgress); } - private static int getMatchingLines(final FilePatchInProgress patch) { + private static int getMatchingLines(final AbstractFilePatchInProgress patch) { final VirtualFile base = patch.getCurrentBase(); if (base == null) return -1; String text; @@ -221,15 +219,43 @@ public class MatchPatchPaths { } private static class PatchAndVariants { - private final List myVariants; + @NotNull private final List myVariants; - private PatchAndVariants(List variants) { + private PatchAndVariants(@NotNull List variants) { myVariants = variants; } - public List getVariants() { + @NotNull + public List getVariants() { return myVariants; } + + public void findAndAddBestVariant(@NotNull MultiMap result) { + AbstractFilePatchInProgress best = ContainerUtil.getFirstItem(myVariants); + if (best == null) return; + if (best instanceof TextFilePatchInProgress) { + //only for text patches + int maxLines = -100; + for (AbstractFilePatchInProgress variant : myVariants) { + TextFilePatchInProgress textFilePAch = (TextFilePatchInProgress)variant; + final int lines = getMatchingLines(textFilePAch); + if (lines > maxLines) { + maxLines = lines; + best = textFilePAch; + } + } + putSelected(result, myVariants, best); + } + else { + int stripCounter = Integer.MAX_VALUE; + for (AbstractFilePatchInProgress variant : myVariants) { + if (variant.getCurrentStrip() < stripCounter) { + best = variant; + } + } + putSelected(result, myVariants, best); + } + } } private static Pair compareNames(final String beforeName, final VirtualFile file) { @@ -250,31 +276,23 @@ public class MatchPatchPaths { } @Nullable - private FilePatchInProgress processMatch(final TextFilePatch patch, final VirtualFile file) { + private static AbstractFilePatchInProgress processMatch(final FilePatch patch, final VirtualFile file) { final String beforeName = patch.getBeforeName(); - /*if (beforeName == null) return null; - final String[] parts = beforeName.replace('\\', '/').split("/"); - VirtualFile parent = file.getParent(); - int idx = parts.length - 2; - while ((parent != null) && (idx >= 0)) { - if (! parent.getName().equals(parts[idx])) { - break; - } - parent = parent.getParent(); - -- idx; - }*/ final Pair pair = compareNames(beforeName, file); if (pair == null) return null; final VirtualFile parent = pair.getFirst(); - if (parent != null) { - final FilePatchInProgress result = new FilePatchInProgress(patch, null, myBaseDir); - result.setNewBase(parent); - int numDown = pair.getSecond(); - for (int i = 0; i < numDown; i++) { - result.up(); - } - return result; + if (parent == null) return null; + final AbstractFilePatchInProgress result = createPatchInProgress(patch, parent); + if (result != null) { + processStipUp(result, pair.getSecond()); } - return null; + return result; + } + + @Nullable + private static AbstractFilePatchInProgress createPatchInProgress(@NotNull FilePatch patch, @NotNull VirtualFile dir) { + return patch instanceof TextFilePatch ? new TextFilePatchInProgress((TextFilePatch)patch, null, dir) : + patch instanceof ShelvedBinaryFilePatch ? new BinaryFilePatchInProgress((ShelvedBinaryFilePatch)patch, null, dir) + : null; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java index e485e023c827..c7ab8ed87968 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/OneBaseStrategy.java @@ -24,13 +24,13 @@ import java.util.*; class OneBaseStrategy extends AutoMatchStrategy { private boolean mySucceeded; - private final MultiMap myVariants; + private final MultiMap myVariants; private boolean myCheckExistingVariants; OneBaseStrategy(VirtualFile baseDir) { super(baseDir); mySucceeded = true; - myVariants = new MultiMap(); + myVariants = new MultiMap(); myCheckExistingVariants = false; } @@ -42,15 +42,15 @@ class OneBaseStrategy extends AutoMatchStrategy { mySucceeded = false; return; } - final List results = new LinkedList(); + final List results = new LinkedList(); final Set keysToRemove = new HashSet(myVariants.keySet()); for (VirtualFile file : foundByName) { - final FilePatchInProgress filePatchInProgress = processMatch(patch, file); - if (filePatchInProgress != null) { - final VirtualFile base = filePatchInProgress.getBase(); + final TextFilePatchInProgress textFilePatchInProgress = processMatch(patch, file); + if (textFilePatchInProgress != null) { + final VirtualFile base = textFilePatchInProgress.getBase(); if (myCheckExistingVariants && (! myVariants.containsKey(base))) continue; keysToRemove.remove(base); - results.add(filePatchInProgress); + results.add(textFilePatchInProgress); } } if (myCheckExistingVariants) { @@ -63,9 +63,9 @@ class OneBaseStrategy extends AutoMatchStrategy { } } final Collection exactMatch = filterVariants(patch, foundByName); - for (FilePatchInProgress filePatchInProgress : results) { - filePatchInProgress.setAutoBases(exactMatch); - myVariants.putValue(filePatchInProgress.getBase(), filePatchInProgress); + for (TextFilePatchInProgress textFilePatchInProgress : results) { + textFilePatchInProgress.setAutoBases(exactMatch); + myVariants.putValue(textFilePatchInProgress.getBase(), textFilePatchInProgress); } myCheckExistingVariants = true; } @@ -73,13 +73,13 @@ class OneBaseStrategy extends AutoMatchStrategy { @Override public void processCreation(TextFilePatch creation) { if (! mySucceeded) return; - final FilePatchInProgress filePatchInProgress; + final TextFilePatchInProgress textFilePatchInProgress; if (myVariants.isEmpty()) { - filePatchInProgress = new FilePatchInProgress(creation, null, myBaseDir); + textFilePatchInProgress = new TextFilePatchInProgress(creation, null, myBaseDir); } else { - filePatchInProgress = new FilePatchInProgress(creation, null, myVariants.keySet().iterator().next()); + textFilePatchInProgress = new TextFilePatchInProgress(creation, null, myVariants.keySet().iterator().next()); } - myResult.add(filePatchInProgress); + myResult.add(textFilePatchInProgress); } @Override @@ -91,12 +91,12 @@ class OneBaseStrategy extends AutoMatchStrategy { public void beforeCreations() { if (! mySucceeded) return; if (myVariants.size() > 1) { - Pair> privilegedSurvivor = null; + Pair> privilegedSurvivor = null; for (VirtualFile file : myVariants.keySet()) { - final Collection patches = myVariants.get(file); + final Collection patches = myVariants.get(file); int numStrip = -1; boolean sameStrip = true; - for (FilePatchInProgress patch : patches) { + for (TextFilePatchInProgress patch : patches) { if (numStrip == -1) { numStrip = patch.getCurrentStrip(); } else { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/TextFilePatchInProgress.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/TextFilePatchInProgress.java new file mode 100644 index 000000000000..c8068b33afdf --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/TextFilePatchInProgress.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.application.ApplicationManager; +import com.intellij.openapi.diff.impl.patch.TextFilePatch; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Getter; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.SimpleContentRevision; +import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcsUtil.VcsUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class TextFilePatchInProgress extends AbstractFilePatchInProgress { + + protected TextFilePatchInProgress(TextFilePatch patch, + Collection autoBases, + VirtualFile baseDir) { + super(patch.pathsOnlyCopy(), autoBases, baseDir); + } + + public ContentRevision getNewContentRevision() { + if (FilePatchStatus.DELETED.equals(myStatus)) return null; + + if (myNewContentRevision == null) { + myConflicts = null; + if (FilePatchStatus.ADDED.equals(myStatus)) { + final FilePath newFilePath = VcsUtil.getFilePathOnNonLocal(myIoCurrentBase.getAbsolutePath(), false); + final String content = myPatch.getNewFileText(); + myNewContentRevision = new SimpleContentRevision(content, newFilePath, myPatch.getAfterVersionId()); + } + else { + final FilePath newFilePath = detectNewFilePathForMovedOrModified(); + myNewContentRevision = new LazyPatchContentRevision(myCurrentBase, newFilePath, myPatch.getAfterVersionId(), myPatch); + if (myCurrentBase != null) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public void run() { + ((LazyPatchContentRevision)myNewContentRevision).getContent(); + } + }); + } + } + } + return myNewContentRevision; + } + + @NotNull + @Override + protected DiffRequestPresentable diffRequestForConflictingChanges(@NotNull final Project project, + @NotNull PatchChange change, + @NotNull final Getter baseContents) { + final Getter revisionTextsGetter = new Getter() { + @Override + public ApplyPatchForBaseRevisionTexts get() { + final VirtualFile currentBase = getCurrentBase(); + return ApplyPatchForBaseRevisionTexts.create(project, currentBase, + VcsUtil.getFilePath(currentBase), + getPatch(), baseContents); + } + }; + return new MergedDiffRequestPresentable(project, revisionTextsGetter, + getCurrentBase(), getPatch().getAfterVersionId()); + } +} \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java index 0f63335ea67f..fc14371c55b5 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java @@ -119,16 +119,16 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD final String showRecycled = element.getAttributeValue(ATTRIBUTE_SHOW_RECYCLED); if (showRecycled != null) { myShowRecycled = Boolean.parseBoolean(showRecycled); - } else { + } + else { myShowRecycled = true; } readExternal(element, myShelvedChangeLists, myRecycledShelvedChangeLists); - - } - public static void readExternal(final Element element, final List changes, final List recycled) throws InvalidDataException { + public static void readExternal(final Element element, final List changes, final List recycled) + throws InvalidDataException { changes.addAll(ShelvedChangeList.readChanges(element, false, true)); recycled.addAll(ShelvedChangeList.readChanges(element, true, true)); @@ -138,17 +138,17 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD public void writeExternal(Element element) throws WriteExternalException { element.setAttribute(ATTRIBUTE_SHOW_RECYCLED, Boolean.toString(myShowRecycled)); ShelvedChangeList.writeChanges(myShelvedChangeLists, myRecycledShelvedChangeLists, element); - } public List getShelvedChangeLists() { return Collections.unmodifiableList(myShelvedChangeLists); } - public ShelvedChangeList shelveChanges(final Collection changes, final String commitMessage, final boolean rollback) throws IOException, VcsException { + public ShelvedChangeList shelveChanges(final Collection changes, final String commitMessage, final boolean rollback) + throws IOException, VcsException { final List textChanges = new ArrayList(); final List binaryFiles = new ArrayList(); - for(Change change: changes) { + for (Change change : changes) { if (ChangesUtil.getFilePath(change).isDirectory()) { continue; } @@ -164,19 +164,20 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD try { File patchPath = getPatchPath(commitMessage); ProgressManager.checkCanceled(); - final List patches = IdeaTextPatchBuilder.buildPatch(myProject, textChanges, myProject.getBaseDir().getPresentableUrl(), false); + final List patches = + IdeaTextPatchBuilder.buildPatch(myProject, textChanges, myProject.getBaseDir().getPresentableUrl(), false); ProgressManager.checkCanceled(); CommitContext commitContext = new CommitContext(); baseRevisionsOfDvcsIntoContext(textChanges, commitContext); myFileProcessor.savePathFile( - new CompoundShelfFileProcessor.ContentProvider(){ - @Override - public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException { - UnifiedDiffWriter.write(myProject, patches, writer, "\n", commitContext); - } - }, - patchPath, commitContext); + new CompoundShelfFileProcessor.ContentProvider() { + @Override + public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException { + UnifiedDiffWriter.write(myProject, patches, writer, "\n", commitContext); + } + }, + patchPath, commitContext); changeList = new ShelvedChangeList(patchPath.toString(), commitMessage.replace('\n', ' '), binaryFiles); myShelvedChangeLists.add(changeList); @@ -215,22 +216,25 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } } - public ShelvedChangeList importFilePatches(final String fileName, final List patches, final PatchEP[] patchTransitExtensions) throws IOException { + public ShelvedChangeList importFilePatches(final String fileName, final List patches, final PatchEP[] patchTransitExtensions) + throws IOException { try { final File patchPath = getPatchPath(fileName); myFileProcessor.savePathFile( - new CompoundShelfFileProcessor.ContentProvider(){ - @Override - public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException { - UnifiedDiffWriter.write(myProject, patches, writer, "\n", patchTransitExtensions, commitContext); - } - }, - patchPath, new CommitContext()); + new CompoundShelfFileProcessor.ContentProvider() { + @Override + public void writeContentTo(final Writer writer, CommitContext commitContext) throws IOException { + UnifiedDiffWriter.write(myProject, patches, writer, "\n", patchTransitExtensions, commitContext); + } + }, + patchPath, new CommitContext()); - final ShelvedChangeList changeList = new ShelvedChangeList(patchPath.toString(), fileName.replace('\n', ' '), new SmartList()); + final ShelvedChangeList changeList = + new ShelvedChangeList(patchPath.toString(), fileName.replace('\n', ' '), new SmartList()); myShelvedChangeLists.add(changeList); return changeList; - } finally { + } + finally { notifyStateChanged(); } } @@ -239,7 +243,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD final List result = new ArrayList(); final LinkedList filesQueue = new LinkedList(files); - while (! filesQueue.isEmpty()) { + while (!filesQueue.isEmpty()) { ProgressManager.checkCanceled(); final VirtualFile file = filesQueue.removeFirst(); if (file.isDirectory()) { @@ -267,7 +271,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD file.getTimeStamp()); try { final List patchesList = loadPatches(myProject, file.getPath(), new CommitContext()); - if (! patchesList.isEmpty()) { + if (!patchesList.isEmpty()) { FileUtil.copy(new File(file.getPath()), patchPath); // add only if ok to read patch myShelvedChangeLists.add(list); @@ -281,7 +285,8 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD exceptionConsumer.consume(new VcsException(e)); } } - } finally { + } + finally { notifyStateChanged(); } return result; @@ -321,7 +326,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } return suggestPatchName(myProject, commitMessage.length() > PatchNameChecker.MAX ? commitMessage.substring(0, PatchNameChecker.MAX) : - commitMessage, file, VcsConfiguration.PATCH); + commitMessage, file, VcsConfiguration.PATCH); } public static File suggestPatchName(Project project, final String commitMessage, final File file, String extension) { @@ -334,9 +339,9 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } while (true) { final File nonexistentFile = FileUtil.findSequentNonexistentFile(file, defaultPath, - extension == null - ? VcsConfiguration.getInstance(project).getPatchFileExtension() - : extension); + extension == null + ? VcsConfiguration.getInstance(project).getPatchFileExtension() + : extension); if (nonexistentFile.getName().length() >= PatchNameChecker.MAX) { defaultPath = defaultPath.substring(0, defaultPath.length() - 1); continue; @@ -346,7 +351,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } public void unshelveChangeList(final ShelvedChangeList changeList, @Nullable final List changes, - @Nullable final List binaryFiles, final LocalChangeList targetChangeList) { + @Nullable final List binaryFiles, final LocalChangeList targetChangeList) { unshelveChangeList(changeList, changes, binaryFiles, targetChangeList, true); } @@ -405,8 +410,10 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } final BinaryPatchApplier binaryPatchApplier = new BinaryPatchApplier(); - final PatchApplier patchApplier = new PatchApplier(myProject, myProject.getBaseDir(), - patches, targetChangeList, binaryPatchApplier, commitContext, reverse, leftConflictTitle, rightConflictTitle); + final PatchApplier patchApplier = + new PatchApplier(myProject, myProject.getBaseDir(), + patches, targetChangeList, binaryPatchApplier, commitContext, reverse, leftConflictTitle, + rightConflictTitle); patchApplier.setIsSystemOperation(systemOperation); // after patch applier part @@ -429,8 +436,12 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD }); } - private static List loadTextPatches(final Project project, final ShelvedChangeList changeList, final List changes, final List remainingPatches, final CommitContext commitContext) - throws IOException, PatchSyntaxException { + private static List loadTextPatches(final Project project, + final ShelvedChangeList changeList, + final List changes, + final List remainingPatches, + final CommitContext commitContext) + throws IOException, PatchSyntaxException { final List textFilePatches = loadPatches(project, changeList.PATH, commitContext); if (changes != null) { @@ -478,10 +489,11 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD return new ArrayList(changeList.getBinaryFiles()); } ArrayList result = new ArrayList(); - for(ShelvedBinaryFile file: changeList.getBinaryFiles()) { + for (ShelvedBinaryFile file : changeList.getBinaryFiles()) { if (binaryFiles.contains(file)) { result.add(file); - } else { + } + else { remainingBinaries.add(file); } } @@ -516,7 +528,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } private static boolean needUnshelve(final FilePatch patch, final List changes) { - for(ShelvedChange change: changes) { + for (ShelvedChange change : changes) { if (Comparing.equal(patch.getBeforeName(), change.getBeforePath())) { return true; } @@ -586,7 +598,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD private void recycleChangeList(final ShelvedChangeList listCopy, final ShelvedChangeList newList) { if (newList != null) { for (Iterator shelvedChangeListIterator = listCopy.getBinaryFiles().iterator(); - shelvedChangeListIterator.hasNext();) { + shelvedChangeListIterator.hasNext(); ) { final ShelvedBinaryFile binaryFile = shelvedChangeListIterator.next(); for (ShelvedBinaryFile newBinary : newList.getBinaryFiles()) { if (Comparing.equal(newBinary.BEFORE_PATH, binaryFile.BEFORE_PATH) @@ -595,7 +607,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } } } - for (Iterator iterator = listCopy.getChanges(myProject).iterator(); iterator.hasNext();) { + for (Iterator iterator = listCopy.getChanges(myProject).iterator(); iterator.hasNext(); ) { final ShelvedChange change = iterator.next(); for (ShelvedChange newChange : newList.getChanges(myProject)) { if (Comparing.equal(change.getBeforePath(), newChange.getBeforePath()) && @@ -624,7 +636,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD } } - if (! listCopy.getBinaryFiles().isEmpty() || ! listCopy.getChanges(myProject).isEmpty()) { + if (!listCopy.getBinaryFiles().isEmpty() || !listCopy.getChanges(myProject).isEmpty()) { listCopy.setRecycled(true); myRecycledShelvedChangeLists.add(listCopy); notifyStateChanged(); @@ -639,9 +651,10 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD public void deleteChangeList(final ShelvedChangeList changeList) { deleteListImpl(changeList); - if (! changeList.isRecycled()) { + if (!changeList.isRecycled()) { myShelvedChangeLists.remove(changeList); - } else { + } + else { myRecycledShelvedChangeLists.remove(changeList); } notifyStateChanged(); @@ -651,7 +664,7 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD File file = new File(changeList.PATH); myFileProcessor.delete(file.getName()); - for(ShelvedBinaryFile binaryFile: changeList.getBinaryFiles()) { + for (ShelvedBinaryFile binaryFile : changeList.getBinaryFiles()) { final String path = binaryFile.SHELVED_PATH; if (path != null) { File binFile = new File(path); @@ -701,22 +714,30 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD setAfterName(myShelvedBinaryFile.AFTER_PATH); } + public static ShelvedBinaryFilePatch patchCopy(@NotNull final ShelvedBinaryFilePatch patch) { + return new ShelvedBinaryFilePatch(patch.getShelvedBinaryFile()); + } + @Override public String getBeforeFileName() { - String[] pathNameComponents = myShelvedBinaryFile.BEFORE_PATH.replace(File.separatorChar, '/').split("/"); - return pathNameComponents [pathNameComponents.length-1]; + return getFileName(myShelvedBinaryFile.BEFORE_PATH); } @Override public String getAfterFileName() { - String[] pathNameComponents = myShelvedBinaryFile.AFTER_PATH.replace(File.separatorChar, '/').split("/"); - return pathNameComponents [pathNameComponents.length-1]; + return getFileName(myShelvedBinaryFile.AFTER_PATH); + } + + @Nullable + private static String getFileName(String filePath) { + return filePath != null ? PathUtil.getFileName(filePath) : null; } @Override public boolean isNewFile() { return myShelvedBinaryFile.BEFORE_PATH == null; } + @Override public boolean isDeletedFile() { return myShelvedBinaryFile.AFTER_PATH == null; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java index 3522a2cff732..78d4c3da5d35 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java @@ -28,9 +28,12 @@ import com.intellij.openapi.vcs.changes.patch.ApplyPatchMode; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import java.io.File; import java.util.Collections; +import java.util.List; /** * @author irengrig @@ -46,17 +49,22 @@ public class UnshelveWithDialogAction extends DumbAwareAction { FileDocumentManager.getInstance().saveAllDocuments(); - final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(changeLists[0].PATH)); + ShelvedChangeList changeList = changeLists[0]; + final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(changeList.PATH)); if (virtualFile == null) { VcsBalloonProblemNotifier.showOverChangesView(project, "Can not find path file", MessageType.ERROR); return; } - if (! changeLists[0].getBinaryFiles().isEmpty()) { - VcsBalloonProblemNotifier.showOverChangesView(project, "Binary file(s) would be skipped.", MessageType.WARNING); - } + List binaryShelvedPatches = + ContainerUtil.map(changeList.getBinaryFiles(), new Function() { + @Override + public ShelveChangesManager.ShelvedBinaryFilePatch fun(ShelvedBinaryFile file) { + return new ShelveChangesManager.ShelvedBinaryFilePatch(file); + } + }); final ApplyPatchDifferentiatedDialog dialog = new ApplyPatchDifferentiatedDialog(project, new ApplyPatchDefaultExecutor(project), Collections.emptyList(), - ApplyPatchMode.UNSHELVE, virtualFile); + ApplyPatchMode.UNSHELVE, virtualFile, binaryShelvedPatches); dialog.setHelpId("reference.dialogs.vcs.unshelve"); dialog.show(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/ApplyPatchSaveToFileExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/ApplyPatchSaveToFileExecutor.java index 4de580ebac05..dcbca299be64 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/ApplyPatchSaveToFileExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/ApplyPatchSaveToFileExecutor.java @@ -33,8 +33,8 @@ import com.intellij.openapi.vcs.changes.CommitContext; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.openapi.vcs.changes.patch.ApplyPatchExecutor; -import com.intellij.openapi.vcs.changes.patch.FilePatchInProgress; import com.intellij.openapi.vcs.changes.patch.PatchWriter; +import com.intellij.openapi.vcs.changes.patch.TextFilePatchInProgress; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -55,7 +55,7 @@ import java.util.Map; * Date: 5/17/12 * Time: 6:02 PM */ -public class ApplyPatchSaveToFileExecutor implements ApplyPatchExecutor { +public class ApplyPatchSaveToFileExecutor implements ApplyPatchExecutor { private static final Logger LOG = Logger.getInstance(ApplyPatchSaveToFileExecutor.class); private final Project myProject; @@ -72,7 +72,7 @@ public class ApplyPatchSaveToFileExecutor implements ApplyPatchExecutor { } @Override - public void apply(MultiMap patchGroups, + public void apply(MultiMap patchGroups, LocalChangeList localList, String fileName, TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo) { @@ -101,17 +101,17 @@ public class ApplyPatchSaveToFileExecutor implements ApplyPatchExecutor { } } - public static List patchGroupsToOneGroup(MultiMap patchGroups, VirtualFile baseDir) + public static List patchGroupsToOneGroup(MultiMap patchGroups, VirtualFile baseDir) throws IOException { final List textPatches = new ArrayList(); final String baseDirPath = baseDir.getPath(); - for (Map.Entry> entry : patchGroups.entrySet()) { + for (Map.Entry> entry : patchGroups.entrySet()) { final VirtualFile vf = entry.getKey(); final String currBasePath = vf.getPath(); final String relativePath = VfsUtilCore.getRelativePath(vf, baseDir, '/'); final boolean toConvert = !StringUtil.isEmptyOrSpaces(relativePath) && !".".equals(relativePath); - for (FilePatchInProgress patchInProgress : entry.getValue()) { + for (TextFilePatchInProgress patchInProgress : entry.getValue()) { final TextFilePatch patch = patchInProgress.getPatch(); if (toConvert) { //correct paths diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java index 8ec2705b7718..15630e188a25 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java @@ -35,7 +35,7 @@ import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser; import com.intellij.openapi.vcs.changes.patch.ApplyPatchDifferentiatedDialog; import com.intellij.openapi.vcs.changes.patch.ApplyPatchExecutor; import com.intellij.openapi.vcs.changes.patch.ApplyPatchMode; -import com.intellij.openapi.vcs.changes.patch.FilePatchInProgress; +import com.intellij.openapi.vcs.changes.patch.TextFilePatchInProgress; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; @@ -226,7 +226,7 @@ public class MergeFromTheirsResolver { } } - private class TreeConflictApplyTheirsPatchExecutor implements ApplyPatchExecutor { + private class TreeConflictApplyTheirsPatchExecutor implements ApplyPatchExecutor { private final SvnVcs myVcs; private final ContinuationContext myInner; private final VirtualFile myBaseDir; @@ -243,7 +243,7 @@ public class MergeFromTheirsResolver { } @Override - public void apply(MultiMap patchGroups, LocalChangeList localList, String fileName, + public void apply(MultiMap patchGroups, LocalChangeList localList, String fileName, TransparentlyFailedValueI>, PatchSyntaxException> additionalInfo) { final List patches; try {