blob: 7ad09399557238c16002a4e6f9e4953d795c5ece [file] [log] [blame]
package org.eclipse.compare.internal.patch;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.ResourceNode;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.Differencer;
import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.viewers.ITreeContentProvider;
public class PreviewPatchPageInput extends PatcherCompareEditorInput {
protected PreviewPatchPage2 previewPatchPage;
private HashMap filesToDiffs;
private boolean containsHunkErrors = false;
public PreviewPatchPageInput(){
super();
}
public PreviewPatchPageInput(CompareConfiguration config){
super(config);
}
protected void updateTree() {
if (viewer == null)
return;
//
// Get the elements from the content provider
ITreeContentProvider contentProvider = (ITreeContentProvider) viewer
.getContentProvider();
Object[] projects = contentProvider.getElements(root);
// Iterate through projects and call reset on each project
for (int j = 0; j < projects.length; j++) {
if ((projects[j] instanceof PatcherDiffNode) && ((PatcherDiffNode)projects[j]).getPatchNodeType() == PatcherDiffNode.PROJECT) {
PatcherDiffNode projectNode = (PatcherDiffNode) projects[j];
//call reset on the project
projectNode.getDiffProject().reset(workspacePatcher, previewPatchPage.getStripPrefixSegments(), previewPatchPage.getFuzzFactor());
IDiffElement[] diffNodes = projectNode.getChildren();
for (int i = 0; i < diffNodes.length; i++) {
viewer.update(diffNodes[i], null);
IDiffElement[] hunkNodes = ((PatcherDiffNode) diffNodes[i]).getChildren();
for (int k = 0; k < hunkNodes.length; k++) {
viewer.update(hunkNodes[k], null);
}
}
} else {
PatcherDiffNode diffNode = (PatcherDiffNode) projects[j];
diffNode.getDiff().reset(workspacePatcher, previewPatchPage.getStripPrefixSegments(), previewPatchPage.getFuzzFactor());
IDiffElement[] diffNodes = diffNode.getChildren();
for (int i = 0; i < diffNodes.length; i++) {
viewer.update(diffNodes[i], null);
IDiffElement[] hunkNodes = ((PatcherDiffNode) diffNodes[i])
.getChildren();
for (int k = 0; k < hunkNodes.length; k++) {
viewer.update(hunkNodes[k], null);
}
}
}
}
viewer.refresh();
updateEnablements();
}
protected void buildTree(WorkspacePatcher patcher){
//clean root
if (root.hasChildren()) {
resetRoot();
}
//new nodes to diffs mapping
nodesToDiffs = new HashMap();
filesToDiffs = new HashMap();
if (patcher.isWorkspacePatch()){
processProjects(patcher.getDiffProjects());
} else {
processDiffs(patcher.getDiffs());
}
viewer.setInput(root);
viewer.refresh();
}
private void processDiffs(Diff[] diffs) {
for (int i = 0; i < diffs.length; i++) {
IPath filePath = new Path(diffs[i].getLabel( diffs[i]));
IFile tempFile = workspacePatcher.existsInTarget(filePath);
processDiff(diffs[i], tempFile, root);
}
}
private void processProjects(DiffProject[] diffProjects) {
//create diffProject nodes
for (int i = 0; i < diffProjects.length; i++) {
PatcherDiffNode projectNode = new PatcherDiffNode(root,Differencer.CHANGE, null, diffProjects[i], null, diffProjects[i]);
Iterator iter = diffProjects[i].fDiffs.iterator();
while (iter.hasNext()){
Object obj = iter.next();
if (obj instanceof Diff) {
Diff diff = (Diff) obj;
IPath filePath = new Path(diff.getLabel(diff));
IFile tempFile = diffProjects[i].getFile(filePath);
processDiff(diff, tempFile, projectNode);
}
}
}
}
private void processDiff(Diff diff, IFile tempFile, DiffNode rootNode) {
byte[] bytes;
try {
bytes = quickPatch(tempFile, workspacePatcher, diff);
int differencer = Differencer.CHANGE;
if (failedHunks.size() != 0) {
differencer += Differencer.CONFLICTING;
}
ITypedElement tempNode;
PatchedFileNode patchedNode;
if (tempFile != null && tempFile.exists()) {
tempNode = new ResourceNode(tempFile);
patchedNode = new PatchedFileNode(bytes, tempNode.getType(),
tempFile.getProjectRelativePath().toString(), true);
filesToDiffs.put(tempFile, diff);
} else {
IPath filePath = new Path(diff.getLabel(diff));
tempNode = new PatchedFileNode(new byte[0], filePath
.getFileExtension(),
PatchMessages.PatcherCompareEditorInput_FileNotFound);
patchedNode = new PatchedFileNode(bytes, tempNode.getType(), ""); //$NON-NLS-1$
}
//PatchedFileWrapper patchedFileWrapper = new PatchedFileWrapper(patchedNode);
PatcherDiffNode diffNode = new PatcherDiffNode(rootNode,differencer, tempNode, tempNode, patchedNode, diff);
nodesToDiffs.put(diff, diffNode);
//process hunks
Hunk[] hunks = diff.getHunks();
for (int j = 0; j < hunks.length; j++) {
processHunk(hunks[j], diff, diffNode, tempFile, tempNode, patchedNode);
}
} catch (CoreException e) {//ignore
}
}
private void processHunk(Hunk hunk, Diff diff,PatcherDiffNode diffNode, IFile fileToPatch, ITypedElement resourceNode, PatchedFileNode patchedNode) {
Diff tempDiff = new Diff(diff.fOldPath, diff.fOldDate, diff.fNewPath,diff.fNewDate);
tempDiff.add(hunk);
try {
quickPatch(fileToPatch, workspacePatcher, tempDiff);
int differencer = Differencer.NO_CHANGE;
switch (hunk.getHunkType()) {
case Hunk.ADDED:
differencer += Differencer.ADDITION;
break;
case Hunk.CHANGED:
differencer += Differencer.CHANGE;
break;
case Hunk.DELETED:
differencer += Differencer.DELETION;
break;
}
// only add a hunk to the node if it can't be patched
if (failedHunks.size() != 0) {
containsHunkErrors = true;
/* differencer += Differencer.CONFLICTING;
String[] hunkContents = createInput(hunk);
PatchedFileNode ancestor = new PatchedFileNode( hunkContents[LEFT].getBytes(), hunk.fParent.getPath().getFileExtension(), hunk.getDescription());
PatchedFileNode patchedNode2 = new PatchedFileNode(hunkContents[RIGHT].getBytes(), resourceNode.getType(),hunk.getDescription());
//create the new hunk node
new PatcherDiffNode(diffNode,differencer, ancestor, resourceNode, patchedNode2, hunk);
*/
String strippedHunk= stripContextFromHunk(hunk);
PatchedFileNode strippedHunkNode = new HunkPatchedFileNode(strippedHunk.getBytes(),resourceNode.getType()/*"manualHunkMerge"*/, hunk.getDescription());
PatchedFileWrapper patchedFileWrapper = new PatchedFileWrapper(patchedNode);
//create ancestor
String[] hunkContents = createInput(hunk);
PatchedFileNode ancestor = new PatchedFileNode( hunkContents[LEFT].getBytes(), hunk.fParent.getPath().getFileExtension(), hunk.getDescription());
PatcherDiffNode parentNode = new PatcherDiffNode(diffNode, Differencer.CHANGE, ancestor, patchedFileWrapper,strippedHunkNode, hunk);
patchedFileWrapper.addContentChangeListener(previewPatchPage);
patchedFileWrapper.setParent(parentNode);
}
} catch (CoreException e) {//ignore
}
}
/**
* Stores a pointer back to the PreviewPatchPage
*
* @param page
*/
public void setPreviewPatchPage(PreviewPatchPage2 page) {
previewPatchPage = page;
}
/**
* Makes sure that at least one hunk is checked off in the tree before
* allowing the patch to be applied.
*/
protected void updateEnablements() {
boolean atLeastOneIsEnabled = false;
if (viewer != null) {
ITreeContentProvider contentProvider = (ITreeContentProvider) viewer
.getContentProvider();
Object[] projects = contentProvider.getElements(root);
// Iterate through projects
for (int j = 0; j < projects.length; j++) {
if (!(projects[j] instanceof PatcherDiffNode)) {
DiffNode project = (DiffNode) projects[j];
// Iterate through project diffs
Object[] diffs = project.getChildren();
for (int i = 0; i < diffs.length; i++) {
PatcherDiffNode diff = (PatcherDiffNode) diffs[i];
atLeastOneIsEnabled = updateEnablement(
atLeastOneIsEnabled, diff);
}
} else if (projects[j] instanceof PatcherDiffNode) {
atLeastOneIsEnabled = updateEnablement(atLeastOneIsEnabled,
(PatcherDiffNode) projects[j]);
}
}
}
previewPatchPage.setPageComplete(atLeastOneIsEnabled);
}
private boolean updateEnablement(boolean oneIsEnabled,
PatcherDiffNode diffNode) {
/*boolean checked = ((CheckboxDiffTreeViewer) viewer)
.getChecked(diffNode);
Diff diff = diffNode.getDiff();
Assert.isNotNull(diff);
diff.setEnabled(checked);
if (checked) {
Object[] hunkItems = diffNode.getChildren();
for (int h = 0; h < hunkItems.length; h++) {
PatcherDiffNode hunkNode = (PatcherDiffNode) hunkItems[h];
checked = ((CheckboxDiffTreeViewer) viewer)
.getChecked(hunkNode);
Hunk hunk = hunkNode.getHunk();
Assert.isNotNull(hunk);
hunk.setEnabled(checked);
if (checked) {
// For workspace patch: before setting enabled flag, make
// sure that the project
// that contains this hunk actually exists in the workspace.
// This is to guard against the
//case of having a new file in a patch that is being applied to a project that
//doesn't currently exist.
boolean projectExists = true;
DiffProject project = (DiffProject) diff.getParent(null);
if (project != null) {
projectExists = project.getProject().exists();
}
if (projectExists)
oneIsEnabled = true;
}
}
}
*/
return true;
}
public boolean containsHunkErrors() {
return containsHunkErrors;
}
private String stripContextFromHunk(Hunk hunk) {
String[] hunkLines = hunk.getLines();
StringBuffer result= new StringBuffer();
for (int i= 0; i<hunkLines.length; i++) {
String line= hunkLines[i];
String rest= line.substring(1);
switch (line.charAt(0)) {
case ' ' :
//skip the context
break;
case '-' :
//don't add removed lines
break;
case '+' :
result.append(rest);
break;
}
}
return result.toString();
}
public void addHunksToFile(IFile rpTargetResource, Hunk[] hunks) {
Object obj = filesToDiffs.get(rpTargetResource);
if (obj != null && obj instanceof Diff){
for (int i = 0; i < hunks.length; i++) {
hunks[i].setParent((Diff) obj);
((Diff) obj).add(hunks[i]);
}
} else {
//couldn't find file either create a new diff or new project etc.
DiffProject diffProject = null;
if (workspacePatcher.isWorkspacePatch()){
//see if the project already exists
IProject project = rpTargetResource.getProject();
DiffProject[] diffProjects = workspacePatcher.getDiffProjects();
for (int i = 0; i < diffProjects.length; i++) {
if (diffProjects[i].getProject().equals(project)){
diffProject = diffProjects[i];
break;
}
}
if (diffProject == null){
//create a new diff project
diffProject = new DiffProject(project);
//add the diffProject to the array
DiffProject[] newProjectArray = new DiffProject[diffProjects.length + 1];
System.arraycopy(diffProjects, 0, newProjectArray, 0, diffProjects.length);
//add the new project to the end
newProjectArray[diffProjects.length] = diffProject;
workspacePatcher.setDiffProjects(newProjectArray);
}
}
//Create a new diff
Diff tempDiff = new Diff(rpTargetResource.getProjectRelativePath(), 0, rpTargetResource.getProjectRelativePath(), 0);
for (int i = 0; i < hunks.length; i++) {
tempDiff.add(hunks[i]);
}
//add diffProject is not null only in the workspace patch case
if (diffProject != null){
diffProject.addDiff(tempDiff);
workspacePatcher.addDiff(tempDiff);
} else {
//not a workspace patch, add newly created diff to patcher
workspacePatcher.addDiff(tempDiff);
}
//add new diff to altered diffs
previewPatchPage.setAlteredDiff(tempDiff);
filesToDiffs.put(rpTargetResource, tempDiff);
}
}
}