1 /*******************************************************************************
2 * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org
.eclipse
.egit
.ui
.internal
.synchronize
.model
;
11 import static org
.eclipse
.compare
.structuremergeviewer
.Differencer
.RIGHT
;
12 import static org
.eclipse
.egit
.ui
.internal
.synchronize
.compare
.GitCompareInput
.getFileRevisionLabel
;
13 import static org
.eclipse
.jgit
.lib
.ObjectId
.zeroId
;
15 import java
.io
.IOException
;
17 import org
.eclipse
.compare
.CompareConfiguration
;
18 import org
.eclipse
.compare
.IResourceProvider
;
19 import org
.eclipse
.compare
.ITypedElement
;
20 import org
.eclipse
.compare
.structuremergeviewer
.ICompareInput
;
21 import org
.eclipse
.compare
.structuremergeviewer
.ICompareInputChangeListener
;
22 import org
.eclipse
.core
.resources
.IFile
;
23 import org
.eclipse
.core
.resources
.IResource
;
24 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
25 import org
.eclipse
.core
.runtime
.CoreException
;
26 import org
.eclipse
.core
.runtime
.IPath
;
27 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
28 import org
.eclipse
.egit
.core
.Activator
;
29 import org
.eclipse
.egit
.core
.synchronize
.GitCommitsModelCache
.Change
;
30 import org
.eclipse
.egit
.ui
.internal
.synchronize
.compare
.ComparisonDataSource
;
31 import org
.eclipse
.egit
.ui
.internal
.synchronize
.compare
.GitCompareInput
;
32 import org
.eclipse
.jgit
.lib
.AbbreviatedObjectId
;
33 import org
.eclipse
.jgit
.lib
.ObjectId
;
34 import org
.eclipse
.jgit
.lib
.Repository
;
35 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
36 import org
.eclipse
.jgit
.revwalk
.RevWalk
;
37 import org
.eclipse
.swt
.graphics
.Image
;
38 import org
.eclipse
.team
.ui
.mapping
.ISynchronizationCompareInput
;
39 import org
.eclipse
.team
.ui
.mapping
.SaveableComparison
;
42 * Git blob object representation in Git ChangeSet
44 public class GitModelBlob
extends GitModelObject
implements
45 ISynchronizationCompareInput
, IResourceProvider
{
47 private static final GitModelObject
[] empty
= new GitModelObject
[0];
49 private final Change change
;
51 private ITypedElement ancestorElement
;
53 private ITypedElement leftElement
;
55 private ITypedElement rightElement
;
58 * Absolute path to changed object
60 protected final IPath path
;
63 * {@link Repository} associated with this object
65 protected final Repository repo
;
71 * repository associated with this object
73 * change associated with this object
75 * absolute path of change
77 public GitModelBlob(GitModelObjectContainer parent
, Repository repo
,
78 Change change
, IPath path
) {
86 public GitModelObject
[] getChildren() {
91 public String
getName() {
92 return path
.lastSegment();
96 public IPath
getLocation() {
101 public boolean isContainer() {
106 public int getKind() {
107 return change
.getKind();
111 * @return abbreviated object id of base commit
113 public AbbreviatedObjectId
getBaseCommitId() {
114 return change
.getCommitId();
118 * @return abbreviated object id of remote commit
120 public AbbreviatedObjectId
getRemoteCommitId() {
121 return change
.getRemoteCommitId();
125 public int repositoryHashCode() {
126 return repo
.getWorkTree().hashCode();
130 public void dispose() {
131 // there is nothing to dispose
135 public String
toString() {
136 return "ModelBlob[objectId=" + change
.getObjectId() + ", location=" + getLocation() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
140 public Image
getImage() {
146 public ITypedElement
getAncestor() {
147 prepareTypedElements();
148 return ancestorElement
;
152 public ITypedElement
getLeft() {
153 prepareTypedElements();
158 public ITypedElement
getRight() {
159 prepareTypedElements();
164 public void addCompareInputChangeListener(
165 ICompareInputChangeListener listener
) {
166 // data in commit will never change, therefore change listeners are
171 public void removeCompareInputChangeListener(
172 ICompareInputChangeListener listener
) {
173 // data in commit will never change, therefore change listeners are
178 public void copy(boolean leftToRight
) {
179 // do nothing, we should disallow coping content between commits
183 public SaveableComparison
getSaveable() {
189 public void prepareInput(CompareConfiguration configuration
,
190 IProgressMonitor monitor
) throws CoreException
{
191 configuration
.setLeftLabel(getFileRevisionLabel(getLeft()));
192 configuration
.setRightLabel(getFileRevisionLabel(getRight()));
196 public String
getFullPath() {
197 return path
.toOSString();
201 public boolean isCompareInputFor(Object object
) {
207 public int hashCode() {
210 baseHash
= change
.getObjectId() != null ? change
.getObjectId()
214 remoteHash
= change
.getRemoteObjectId() != null ? change
215 .getRemoteObjectId().hashCode() : 41;
217 return baseHash ^ remoteHash ^ path
.hashCode();
221 public boolean equals(Object obj
) {
226 if (getClass() != obj
.getClass())
228 GitModelBlob other
= (GitModelBlob
) obj
;
229 if (change
== null) {
230 if (other
.change
!= null)
232 } else if (!change
.equals(other
.change
))
235 if (other
.path
!= null)
237 } else if (!path
.equals(other
.path
))
243 private void prepareTypedElements() {
244 if (ancestorElement
!= null) // other elements should also not be null
247 ComparisonDataSource baseData
;
248 ComparisonDataSource remoteData
;
250 RevCommit baseCommit
= null;
251 RevCommit remoteCommit
= null;
252 try (RevWalk rw
= new RevWalk(repo
)) {
253 rw
.setRetainBody(true);
254 if (change
.getCommitId() != null)
255 baseCommit
= rw
.parseCommit(change
.getCommitId().toObjectId());
256 if (change
.getRemoteCommitId() != null)
257 remoteCommit
= rw
.parseCommit(change
.getRemoteCommitId()
259 } catch (IOException e
) {
260 Activator
.logError(e
.getMessage(), e
);
262 if (baseCommit
== null && remoteCommit
!= null)
263 baseCommit
= remoteCommit
; // prevent from NPE for deleted files
265 ObjectId localId
= extractObjectId(change
.getObjectId());
266 ObjectId remoteId
= extractObjectId(change
.getRemoteObjectId());
268 if ((getKind() & RIGHT
) == RIGHT
) {
269 baseData
= new ComparisonDataSource(baseCommit
, localId
);
270 remoteData
= new ComparisonDataSource(remoteCommit
, remoteId
);
271 } else /* getKind() == LEFT */{
272 baseData
= new ComparisonDataSource(remoteCommit
, remoteId
);
273 remoteData
= new ComparisonDataSource(baseCommit
, localId
);
276 GitCompareInput compareInput
= getCompareInput(baseData
, remoteData
, remoteData
);
278 ancestorElement
= compareInput
.getAncestor();
279 leftElement
= compareInput
.getLeft();
280 rightElement
= compareInput
.getRight();
284 public IResource
getResource() {
285 IFile file
= ResourcesPlugin
.getWorkspace().getRoot()
286 .getFileForLocation(path
);
292 * Returns specific instance of {@link GitCompareInput} for particular
297 * @param ancestorData
298 * @return Git specific {@link ICompareInput}
300 protected GitCompareInput
getCompareInput(ComparisonDataSource baseData
,
301 ComparisonDataSource remoteData
, ComparisonDataSource ancestorData
) {
302 String gitPath
= Repository
.stripWorkDir(repo
.getWorkTree(), path
.toFile());
304 return new GitCompareInput(repo
, ancestorData
, baseData
, remoteData
,
308 private ObjectId
extractObjectId(AbbreviatedObjectId objectId
) {
309 if (objectId
!= null)
310 return objectId
.toObjectId();