Initial EGit contribution to eclipse.org
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / GitCompareFileRevisionEditorInput.java
blob60d7da1855f67499a9d85032d2359703d3744c94
1 /*******************************************************************************
2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * http://www.eclipse.org/legal/epl-v10.html
9 *******************************************************************************/
10 package org.eclipse.egit.ui.internal;
12 import java.lang.reflect.InvocationTargetException;
14 import org.eclipse.compare.CompareConfiguration;
15 import org.eclipse.compare.IEditableContent;
16 import org.eclipse.compare.IResourceProvider;
17 import org.eclipse.compare.ITypedElement;
18 import org.eclipse.compare.structuremergeviewer.DiffNode;
19 import org.eclipse.compare.structuremergeviewer.Differencer;
20 import org.eclipse.compare.structuremergeviewer.ICompareInput;
21 import org.eclipse.compare.structuremergeviewer.IDiffElement;
22 import org.eclipse.compare.structuremergeviewer.IStructureComparator;
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IFileState;
25 import org.eclipse.core.resources.IResource;
26 import org.eclipse.core.resources.IStorage;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IProgressMonitor;
29 import org.eclipse.core.runtime.NullProgressMonitor;
30 import org.eclipse.egit.core.Activator;
31 import org.eclipse.osgi.util.NLS;
32 import org.eclipse.team.internal.core.history.LocalFileRevision;
33 import org.eclipse.team.internal.ui.TeamUIMessages;
34 import org.eclipse.team.internal.ui.TeamUIPlugin;
35 import org.eclipse.team.internal.ui.Utils;
36 import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
37 import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
38 import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
39 import org.eclipse.ui.IWorkbenchPage;
41 /**
42 * The input provider for the compare editor when working on resources
43 * under Git control.
45 public class GitCompareFileRevisionEditorInput extends SaveableCompareEditorInput {
47 private ITypedElement left;
48 private ITypedElement right;
50 /**
51 * Creates a new CompareFileRevisionEditorInput.
52 * @param left
53 * @param right
54 * @param page
56 public GitCompareFileRevisionEditorInput(ITypedElement left, ITypedElement right, IWorkbenchPage page) {
57 super(new CompareConfiguration(), page);
58 this.left = left;
59 this.right = right;
62 FileRevisionTypedElement getRightRevision() {
63 if (right instanceof FileRevisionTypedElement) {
64 return (FileRevisionTypedElement) right;
66 return null;
69 FileRevisionTypedElement getLeftRevision() {
70 if (left instanceof FileRevisionTypedElement) {
71 return (FileRevisionTypedElement) left;
73 return null;
76 private static void ensureContentsCached(FileRevisionTypedElement left, FileRevisionTypedElement right,
77 IProgressMonitor monitor) {
78 if (left != null) {
79 try {
80 left.cacheContents(monitor);
81 } catch (CoreException e) {
82 TeamUIPlugin.log(e);
85 if (right != null) {
86 try {
87 right.cacheContents(monitor);
88 } catch (CoreException e) {
89 TeamUIPlugin.log(e);
94 private boolean isLeftEditable(ICompareInput input) {
95 Object tmpLeft = input.getLeft();
96 return isEditable(tmpLeft);
99 private boolean isRightEditable(ICompareInput input) {
100 Object tmpRight = input.getRight();
101 return isEditable(tmpRight);
104 private boolean isEditable(Object object) {
105 if (object instanceof IEditableContent) {
106 return ((IEditableContent) object).isEditable();
108 return false;
111 private IResource getResource(ICompareInput input) {
112 if (getLocalElement() != null) {
113 return ((IResourceProvider) getLocalElement()).getResource();
115 return null;
118 private ICompareInput createCompareInput() {
119 return compare(left, right);
122 private DiffNode compare(ITypedElement left, ITypedElement right) {
123 if (left.getType().equals(ITypedElement.FOLDER_TYPE)) {
124 // return new MyDiffContainer(null, left,right);
125 DiffNode diffNode = new DiffNode(null,Differencer.CHANGE,null,left,right);
126 ITypedElement[] lc = (ITypedElement[])((IStructureComparator)left).getChildren();
127 ITypedElement[] rc = (ITypedElement[])((IStructureComparator)right).getChildren();
128 int li=0;
129 int ri=0;
130 while (li<lc.length && ri<rc.length) {
131 ITypedElement ln = lc[li];
132 ITypedElement rn = rc[ri];
133 int compareTo = ln.getName().compareTo(rn.getName());
134 // TODO: Git ordering!
135 if (compareTo == 0) {
136 if (!ln.equals(rn))
137 diffNode.add(compare(ln,rn));
138 ++li;
139 ++ri;
140 } else if (compareTo < 0) {
141 DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
142 diffNode.add(childDiffNode);
143 if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
144 ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
145 if(children != null && children.length > 0) {
146 for (ITypedElement child : children) {
147 childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
151 ++li;
152 } else {
153 DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
154 diffNode.add(childDiffNode);
155 if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
156 ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
157 if(children != null && children.length > 0) {
158 for (ITypedElement child : children) {
159 childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
163 ++ri;
166 while (li<lc.length) {
167 ITypedElement ln = lc[li];
168 DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
169 diffNode.add(childDiffNode);
170 if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
171 ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
172 if(children != null && children.length > 0) {
173 for (ITypedElement child : children) {
174 childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
178 ++li;
180 while (ri<rc.length) {
181 ITypedElement rn = rc[ri];
182 DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
183 diffNode.add(childDiffNode);
184 if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
185 ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
186 if(children != null && children.length > 0) {
187 for (ITypedElement child : children) {
188 childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
192 ++ri;
194 return diffNode;
195 } else {
196 return new DiffNode(left, right);
200 private DiffNode addDirectoryFiles(ITypedElement elem, int diffType) {
201 ITypedElement l = null;
202 ITypedElement r = null;
203 if (diffType == Differencer.DELETION) {
204 r = elem;
205 } else {
206 l = elem;
209 if (elem.getType().equals(ITypedElement.FOLDER_TYPE)) {
210 DiffNode diffNode = null;
211 diffNode = new DiffNode(null,Differencer.CHANGE,null,l,r);
212 ITypedElement[] children = (ITypedElement[])((IStructureComparator)elem).getChildren();
213 for (ITypedElement child : children) {
214 diffNode.add(addDirectoryFiles(child, diffType));
216 return diffNode;
217 } else {
218 return new DiffNode(diffType, null, l, r);
222 private void initLabels(ICompareInput input) {
223 CompareConfiguration cc = getCompareConfiguration();
224 if(left != null && left instanceof GitResourceNode) {
225 String ci = ((GitResourceNode)left).getContentIdentifier();
226 if(ci != null) {
227 cc.setLeftLabel(ci.substring(0, 7) + "..");
230 if(right != null && right instanceof GitResourceNode) {
231 String ci = ((GitResourceNode)right).getContentIdentifier();
232 if(ci != null) {
233 cc.setRightLabel(ci.substring(0, 7) + "..");
236 if (getLeftRevision() != null) {
237 String leftLabel = getFileRevisionLabel(getLeftRevision());
238 cc.setLeftLabel(leftLabel);
239 } else if (getResource(input) != null) {
240 String label = NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_workspace, new Object[]{ input.getLeft().getName() });
241 cc.setLeftLabel(label);
243 if (getRightRevision() != null) {
244 String rightLabel = getFileRevisionLabel(getRightRevision());
245 cc.setRightLabel(rightLabel);
249 private String getFileRevisionLabel(FileRevisionTypedElement element) {
250 Object fileObject = element.getFileRevision();
251 if (fileObject instanceof LocalFileRevision){
252 return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_localRevision, new Object[]{element.getName(), element.getTimestamp()});
253 } else {
254 return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_repository, new Object[]{ element.getName(), element.getContentIdentifier()});
258 /* (non-Javadoc)
259 * @see org.eclipse.compare.CompareEditorInput#getToolTipText()
261 public String getToolTipText() {
262 Object[] titleObject = new Object[3];
263 titleObject[0] = getLongName(left);
264 titleObject[1] = getContentIdentifier(getLeftRevision());
265 titleObject[2] = getContentIdentifier(getRightRevision());
266 return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_compareResourceAndVersions, titleObject);
269 /* (non-Javadoc)
270 * @see org.eclipse.compare.CompareEditorInput#getTitle()
272 public String getTitle() {
273 Object[] titleObject = new Object[3];
274 titleObject[0] = getShortName(left);
275 titleObject[1] = getContentIdentifier(getLeftRevision());
276 titleObject[2] = getContentIdentifier(getRightRevision());
277 return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_compareResourceAndVersions, titleObject);
280 /* (non-Javadoc)
281 * @see org.eclipse.compare.CompareEditorInput#getAdapter(java.lang.Class)
283 public Object getAdapter(Class adapter) {
284 if (adapter == IFile.class || adapter == IResource.class) {
285 if (getLocalElement() != null) {
286 return getLocalElement().getResource();
288 return null;
290 return super.getAdapter(adapter);
293 private String getShortName(ITypedElement element) {
294 if (element instanceof FileRevisionTypedElement){
295 FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
296 return fileRevisionElement.getName();
298 else if (element instanceof LocalResourceTypedElement){
299 LocalResourceTypedElement typedContent = (LocalResourceTypedElement) element;
300 return typedContent.getResource().getName();
302 return element.getName();
305 private String getLongName(ITypedElement element) {
306 if (element instanceof FileRevisionTypedElement){
307 FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
308 return fileRevisionElement.getPath();
310 else if (element instanceof LocalResourceTypedElement){
311 LocalResourceTypedElement typedContent = (LocalResourceTypedElement) element;
312 return typedContent.getResource().getFullPath().toString();
314 return element.getName();
317 private String getContentIdentifier(ITypedElement element){
318 if (element instanceof FileRevisionTypedElement){
319 FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
320 Object fileObject = fileRevisionElement.getFileRevision();
321 if (fileObject instanceof LocalFileRevision){
322 try {
323 IStorage storage = ((LocalFileRevision) fileObject).getStorage(new NullProgressMonitor());
324 if (Utils.getAdapter(storage, IFileState.class) != null){
325 //local revision
326 return TeamUIMessages.CompareFileRevisionEditorInput_0;
327 } else if (Utils.getAdapter(storage, IFile.class) != null) {
328 //current revision
329 return TeamUIMessages.CompareFileRevisionEditorInput_1;
331 } catch (CoreException e) {
332 Activator.logError("Problem getting content identifier", e);
334 } else {
335 return fileRevisionElement.getContentIdentifier();
338 return TeamUIMessages.CompareFileRevisionEditorInput_2;
341 @Override
342 protected void fireInputChange() {
345 // /* (non-Javadoc)
346 // * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#contentsCreated()
347 // */
348 // protected void contentsCreated() {
349 // super.contentsCreated();
350 // notifier.initialize();
351 // }
353 // /* (non-Javadoc)
354 // * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#handleDispose()
355 // */
356 // protected void handleDispose() {
357 // super.handleDispose();
358 // notifier.dispose();
359 // if (getLocalElement() != null) {
360 // getLocalElement().discardBuffer();
361 // }
362 // }
364 private LocalResourceTypedElement getLocalElement() {
365 if (left instanceof LocalResourceTypedElement) {
366 return (LocalResourceTypedElement) left;
368 return null;
371 @Override
372 protected ICompareInput prepareCompareInput(IProgressMonitor monitor)
373 throws InvocationTargetException, InterruptedException {
374 ICompareInput input = createCompareInput();
375 getCompareConfiguration().setLeftEditable(isLeftEditable(input));
376 getCompareConfiguration().setRightEditable(isRightEditable(input));
377 ensureContentsCached(getLeftRevision(), getRightRevision(), monitor);
378 initLabels(input);
379 setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title, new String[] { input.getName() }));
381 // The compare editor (Structure Compare) will show the diff filenames
382 // with their project relative path. So, no need to also show directory entries.
383 DiffNode flatDiffNode = new DiffNode(null,Differencer.CHANGE,null,left,right);
384 flatDiffView(flatDiffNode, (DiffNode) input);
386 return flatDiffNode;
389 private void flatDiffView(DiffNode rootNode, DiffNode currentNode) {
390 if(currentNode != null) {
391 IDiffElement[] dElems = currentNode.getChildren();
392 if(dElems != null) {
393 for(IDiffElement dElem : dElems) {
394 DiffNode dNode = (DiffNode) dElem;
395 if(dNode.getChildren() != null && dNode.getChildren().length > 0) {
396 flatDiffView(rootNode, dNode);
397 } else {
398 rootNode.add(dNode);