1 /*******************************************************************************
2 * Copyright (c) 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 * Robin Rosenberg - Git interface
11 *******************************************************************************/
12 package org
.spearce
.egit
.ui
.internal
;
14 import java
.lang
.reflect
.InvocationTargetException
;
16 import org
.eclipse
.compare
.CompareConfiguration
;
17 import org
.eclipse
.compare
.CompareEditorInput
;
18 import org
.eclipse
.compare
.IEditableContent
;
19 import org
.eclipse
.compare
.IResourceProvider
;
20 import org
.eclipse
.compare
.ITypedElement
;
21 import org
.eclipse
.compare
.structuremergeviewer
.DiffNode
;
22 import org
.eclipse
.compare
.structuremergeviewer
.Differencer
;
23 import org
.eclipse
.compare
.structuremergeviewer
.ICompareInput
;
24 import org
.eclipse
.compare
.structuremergeviewer
.IDiffElement
;
25 import org
.eclipse
.compare
.structuremergeviewer
.IStructureComparator
;
26 import org
.eclipse
.core
.resources
.IFile
;
27 import org
.eclipse
.core
.resources
.IFileState
;
28 import org
.eclipse
.core
.resources
.IResource
;
29 import org
.eclipse
.core
.resources
.IStorage
;
30 import org
.eclipse
.core
.runtime
.CoreException
;
31 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
32 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
33 import org
.eclipse
.osgi
.util
.NLS
;
34 import org
.eclipse
.team
.internal
.core
.history
.LocalFileRevision
;
35 import org
.eclipse
.team
.internal
.ui
.TeamUIMessages
;
36 import org
.eclipse
.team
.internal
.ui
.TeamUIPlugin
;
37 import org
.eclipse
.team
.internal
.ui
.Utils
;
38 import org
.eclipse
.team
.internal
.ui
.history
.FileRevisionTypedElement
;
39 import org
.eclipse
.team
.internal
.ui
.synchronize
.LocalResourceTypedElement
;
40 import org
.eclipse
.ui
.IWorkbenchPage
;
43 * The input provider for the compare editor when working on resources
46 public class GitCompareFileRevisionEditorInput
extends CompareEditorInput
{
48 private ITypedElement left
;
49 private ITypedElement right
;
52 * Creates a new CompareFileRevisionEditorInput.
57 public GitCompareFileRevisionEditorInput(ITypedElement left
, ITypedElement right
, IWorkbenchPage page
) {
58 super(new CompareConfiguration());
63 FileRevisionTypedElement
getRightRevision() {
64 if (right
instanceof FileRevisionTypedElement
) {
65 return (FileRevisionTypedElement
) right
;
70 FileRevisionTypedElement
getLeftRevision() {
71 if (left
instanceof FileRevisionTypedElement
) {
72 return (FileRevisionTypedElement
) left
;
77 private static void ensureContentsCached(FileRevisionTypedElement left
, FileRevisionTypedElement right
,
78 IProgressMonitor monitor
) {
81 left
.cacheContents(monitor
);
82 } catch (CoreException e
) {
88 right
.cacheContents(monitor
);
89 } catch (CoreException e
) {
95 private boolean isLeftEditable(ICompareInput input
) {
96 Object left
= input
.getLeft();
97 if (left
instanceof IEditableContent
) {
98 return ((IEditableContent
) left
).isEditable();
103 private IResource
getResource(ICompareInput input
) {
104 if (getLocalElement() != null) {
105 return ((IResourceProvider
) getLocalElement()).getResource();
110 private ICompareInput
createCompareInput() {
111 return compare(left
, right
);
114 private DiffNode
compare(ITypedElement left
, ITypedElement right
) {
115 if (left
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
116 // return new MyDiffContainer(null, left,right);
117 DiffNode diffNode
= new DiffNode(null,Differencer
.CHANGE
,null,left
,right
);
118 ITypedElement
[] lc
= (ITypedElement
[])((IStructureComparator
)left
).getChildren();
119 ITypedElement
[] rc
= (ITypedElement
[])((IStructureComparator
)right
).getChildren();
122 while (li
<lc
.length
&& ri
<rc
.length
) {
123 ITypedElement ln
= lc
[li
];
124 ITypedElement rn
= rc
[ri
];
125 int compareTo
= ln
.getName().compareTo(rn
.getName());
126 // TODO: Git ordering!
127 if (compareTo
== 0) {
129 diffNode
.add(compare(ln
,rn
));
132 } else if (compareTo
< 0) {
133 DiffNode childDiffNode
= new DiffNode(Differencer
.ADDITION
, null, ln
, null);
134 diffNode
.add(childDiffNode
);
135 if (ln
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
136 ITypedElement
[] children
= (ITypedElement
[])((IStructureComparator
)ln
).getChildren();
137 if(children
!= null && children
.length
> 0) {
138 for (ITypedElement child
: children
) {
139 childDiffNode
.add(addDirectoryFiles(child
, Differencer
.ADDITION
));
145 DiffNode childDiffNode
= new DiffNode(Differencer
.DELETION
, null, null, rn
);
146 diffNode
.add(childDiffNode
);
147 if (rn
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
148 ITypedElement
[] children
= (ITypedElement
[])((IStructureComparator
)rn
).getChildren();
149 if(children
!= null && children
.length
> 0) {
150 for (ITypedElement child
: children
) {
151 childDiffNode
.add(addDirectoryFiles(child
, Differencer
.DELETION
));
158 while (li
<lc
.length
) {
159 ITypedElement ln
= lc
[li
];
160 DiffNode childDiffNode
= new DiffNode(Differencer
.ADDITION
, null, ln
, null);
161 diffNode
.add(childDiffNode
);
162 if (ln
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
163 ITypedElement
[] children
= (ITypedElement
[])((IStructureComparator
)ln
).getChildren();
164 if(children
!= null && children
.length
> 0) {
165 for (ITypedElement child
: children
) {
166 childDiffNode
.add(addDirectoryFiles(child
, Differencer
.ADDITION
));
172 while (ri
<rc
.length
) {
173 ITypedElement rn
= rc
[ri
];
174 DiffNode childDiffNode
= new DiffNode(Differencer
.DELETION
, null, null, rn
);
175 diffNode
.add(childDiffNode
);
176 if (rn
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
177 ITypedElement
[] children
= (ITypedElement
[])((IStructureComparator
)rn
).getChildren();
178 if(children
!= null && children
.length
> 0) {
179 for (ITypedElement child
: children
) {
180 childDiffNode
.add(addDirectoryFiles(child
, Differencer
.DELETION
));
188 return new DiffNode(left
, right
);
192 private DiffNode
addDirectoryFiles(ITypedElement elem
, int diffType
) {
193 ITypedElement l
= null;
194 ITypedElement r
= null;
195 if (diffType
== Differencer
.DELETION
) {
201 if (elem
.getType().equals(ITypedElement
.FOLDER_TYPE
)) {
202 DiffNode diffNode
= null;
203 diffNode
= new DiffNode(null,Differencer
.CHANGE
,null,l
,r
);
204 ITypedElement
[] children
= (ITypedElement
[])((IStructureComparator
)elem
).getChildren();
205 for (ITypedElement child
: children
) {
206 diffNode
.add(addDirectoryFiles(child
, diffType
));
210 return new DiffNode(diffType
, null, l
, r
);
214 private void initLabels(ICompareInput input
) {
215 CompareConfiguration cc
= getCompareConfiguration();
216 if(left
!= null && left
instanceof GitResourceNode
) {
217 String ci
= ((GitResourceNode
)left
).getContentIdentifier();
219 cc
.setLeftLabel(ci
.substring(0, 7) + "..");
222 if(right
!= null && right
instanceof GitResourceNode
) {
223 String ci
= ((GitResourceNode
)right
).getContentIdentifier();
225 cc
.setRightLabel(ci
.substring(0, 7) + "..");
228 if (getLeftRevision() != null) {
229 String leftLabel
= getFileRevisionLabel(getLeftRevision());
230 cc
.setLeftLabel(leftLabel
);
231 } else if (getResource(input
) != null) {
232 String label
= NLS
.bind(TeamUIMessages
.CompareFileRevisionEditorInput_workspace
, new Object
[]{ input
.getLeft().getName() });
233 cc
.setLeftLabel(label
);
235 if (getRightRevision() != null) {
236 String rightLabel
= getFileRevisionLabel(getRightRevision());
237 cc
.setRightLabel(rightLabel
);
241 private String
getFileRevisionLabel(FileRevisionTypedElement element
) {
242 Object fileObject
= element
.getFileRevision();
243 if (fileObject
instanceof LocalFileRevision
){
244 return NLS
.bind(TeamUIMessages
.CompareFileRevisionEditorInput_localRevision
, new Object
[]{element
.getName(), element
.getTimestamp()});
246 return NLS
.bind(TeamUIMessages
.CompareFileRevisionEditorInput_repository
, new Object
[]{ element
.getName(), element
.getContentIdentifier()});
251 * @see org.eclipse.compare.CompareEditorInput#getToolTipText()
253 public String
getToolTipText() {
254 Object
[] titleObject
= new Object
[3];
255 titleObject
[0] = getLongName(left
);
256 titleObject
[1] = getContentIdentifier(getLeftRevision());
257 titleObject
[2] = getContentIdentifier(getRightRevision());
258 return NLS
.bind(TeamUIMessages
.CompareFileRevisionEditorInput_compareResourceAndVersions
, titleObject
);
262 * @see org.eclipse.compare.CompareEditorInput#getTitle()
264 public String
getTitle() {
265 Object
[] titleObject
= new Object
[3];
266 titleObject
[0] = getShortName(left
);
267 titleObject
[1] = getContentIdentifier(getLeftRevision());
268 titleObject
[2] = getContentIdentifier(getRightRevision());
269 return NLS
.bind(TeamUIMessages
.CompareFileRevisionEditorInput_compareResourceAndVersions
, titleObject
);
273 * @see org.eclipse.compare.CompareEditorInput#getAdapter(java.lang.Class)
275 public Object
getAdapter(Class adapter
) {
276 if (adapter
== IFile
.class || adapter
== IResource
.class) {
277 if (getLocalElement() != null) {
278 return getLocalElement().getResource();
282 return super.getAdapter(adapter
);
285 private String
getShortName(ITypedElement element
) {
286 if (element
instanceof FileRevisionTypedElement
){
287 FileRevisionTypedElement fileRevisionElement
= (FileRevisionTypedElement
) element
;
288 return fileRevisionElement
.getName();
290 else if (element
instanceof LocalResourceTypedElement
){
291 LocalResourceTypedElement typedContent
= (LocalResourceTypedElement
) element
;
292 return typedContent
.getResource().getName();
294 return element
.getName();
297 private String
getLongName(ITypedElement element
) {
298 if (element
instanceof FileRevisionTypedElement
){
299 FileRevisionTypedElement fileRevisionElement
= (FileRevisionTypedElement
) element
;
300 return fileRevisionElement
.getPath();
302 else if (element
instanceof LocalResourceTypedElement
){
303 LocalResourceTypedElement typedContent
= (LocalResourceTypedElement
) element
;
304 return typedContent
.getResource().getFullPath().toString();
306 return element
.getName();
309 private String
getContentIdentifier(ITypedElement element
){
310 if (element
instanceof FileRevisionTypedElement
){
311 FileRevisionTypedElement fileRevisionElement
= (FileRevisionTypedElement
) element
;
312 Object fileObject
= fileRevisionElement
.getFileRevision();
313 if (fileObject
instanceof LocalFileRevision
){
315 IStorage storage
= ((LocalFileRevision
) fileObject
).getStorage(new NullProgressMonitor());
316 if (Utils
.getAdapter(storage
, IFileState
.class) != null){
318 return TeamUIMessages
.CompareFileRevisionEditorInput_0
;
319 } else if (Utils
.getAdapter(storage
, IFile
.class) != null) {
321 return TeamUIMessages
.CompareFileRevisionEditorInput_1
;
323 } catch (CoreException e
) {
326 return fileRevisionElement
.getContentIdentifier();
329 return TeamUIMessages
.CompareFileRevisionEditorInput_2
;
333 // * @see org.eclipse.team.ui.synchronize.LocalResourceCompareEditorInput#fireInputChange()
335 // protected void fireInputChange() {
336 // ((DiffNode)getCompareResult()).fireChange();
340 // * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#contentsCreated()
342 // protected void contentsCreated() {
343 // super.contentsCreated();
344 // notifier.initialize();
348 // * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#handleDispose()
350 // protected void handleDispose() {
351 // super.handleDispose();
352 // notifier.dispose();
353 // if (getLocalElement() != null) {
354 // getLocalElement().discardBuffer();
358 private LocalResourceTypedElement
getLocalElement() {
359 if (left
instanceof LocalResourceTypedElement
) {
360 return (LocalResourceTypedElement
) left
;
365 protected Object
prepareInput(IProgressMonitor monitor
) throws InvocationTargetException
, InterruptedException
{
366 ICompareInput input
= createCompareInput();
367 getCompareConfiguration().setLeftEditable(isLeftEditable(input
));
368 getCompareConfiguration().setRightEditable(false);
369 ensureContentsCached(getLeftRevision(), getRightRevision(), monitor
);
371 setTitle(NLS
.bind(TeamUIMessages
.SyncInfoCompareInput_title
, new String
[] { input
.getName() }));
373 // The compare editor (Structure Compare) will show the diff filenames
374 // with their project relative path. So, no need to also show directory entries.
375 DiffNode flatDiffNode
= new DiffNode(null,Differencer
.CHANGE
,null,left
,right
);
376 flatDiffView(flatDiffNode
, (DiffNode
) input
);
381 private void flatDiffView(DiffNode rootNode
, DiffNode currentNode
) {
382 if(currentNode
!= null) {
383 IDiffElement
[] dElems
= currentNode
.getChildren();
385 for(IDiffElement dElem
: dElems
) {
386 DiffNode dNode
= (DiffNode
) dElem
;
387 if(dNode
.getChildren() != null && dNode
.getChildren().length
> 0) {
388 flatDiffView(rootNode
, dNode
);