1 /*******************************************************************************
2 * Copyright (C) 2008, 2009 Robin Rosenberg <robin.rosenberg@dewire.com>
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
.decorators
;
11 import java
.io
.IOException
;
13 import java
.util
.WeakHashMap
;
15 import org
.eclipse
.core
.resources
.IEncodedStorage
;
16 import org
.eclipse
.core
.resources
.IResource
;
17 import org
.eclipse
.core
.runtime
.CoreException
;
18 import org
.eclipse
.egit
.core
.GitProvider
;
19 import org
.eclipse
.egit
.core
.internal
.trace
.GitTraceLocation
;
20 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
21 import org
.eclipse
.egit
.ui
.Activator
;
22 import org
.eclipse
.jface
.text
.Document
;
23 import org
.eclipse
.team
.core
.RepositoryProvider
;
24 import org
.eclipse
.jgit
.lib
.AnyObjectId
;
25 import org
.eclipse
.jgit
.lib
.Commit
;
26 import org
.eclipse
.jgit
.lib
.Constants
;
27 import org
.eclipse
.jgit
.lib
.IndexChangedEvent
;
28 import org
.eclipse
.jgit
.lib
.ObjectId
;
29 import org
.eclipse
.jgit
.lib
.ObjectLoader
;
30 import org
.eclipse
.jgit
.lib
.RefsChangedEvent
;
31 import org
.eclipse
.jgit
.lib
.Repository
;
32 import org
.eclipse
.jgit
.lib
.RepositoryListener
;
33 import org
.eclipse
.jgit
.lib
.Tree
;
34 import org
.eclipse
.jgit
.lib
.TreeEntry
;
36 class GitDocument
extends Document
implements RepositoryListener
{
37 private final IResource resource
;
39 private ObjectId lastCommit
;
40 private ObjectId lastTree
;
41 private ObjectId lastBlob
;
43 static Map
<GitDocument
,Repository
> doc2repo
= new WeakHashMap
<GitDocument
, Repository
>();
45 static GitDocument
create(final IResource resource
) throws IOException
{
46 // TODO is this the right location?
47 if (GitTraceLocation
.UI
.isActive())
48 GitTraceLocation
.getTrace().trace(
49 GitTraceLocation
.UI
.getLocation(),
50 "(GitDocument) create: " + resource
); //$NON-NLS-1$
51 GitDocument ret
= null;
52 if (RepositoryProvider
.getProvider(resource
.getProject()) instanceof GitProvider
) {
53 ret
= new GitDocument(resource
);
55 final Repository repository
= ret
.getRepository();
56 if (repository
!= null)
57 repository
.addRepositoryChangedListener(ret
);
62 private GitDocument(IResource resource
) {
63 this.resource
= resource
;
64 GitDocument
.doc2repo
.put(this, getRepository());
67 private void setResolved(final AnyObjectId commit
, final AnyObjectId tree
, final AnyObjectId blob
, final String value
) {
68 lastCommit
= commit
!= null ? commit
.copy() : null;
69 lastTree
= tree
!= null ? tree
.copy() : null;
70 lastBlob
= blob
!= null ? blob
.copy() : null;
73 // TODO is this the right location?
74 if (GitTraceLocation
.UI
.isActive())
78 GitTraceLocation
.UI
.getLocation(),
79 "(GitDocument) resolved " + resource
+ " to " + lastBlob
+ " in " + lastCommit
+ "/" + lastTree
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
81 // TODO is this the right location?
82 if (GitTraceLocation
.UI
.isActive())
83 GitTraceLocation
.getTrace().trace(
84 GitTraceLocation
.UI
.getLocation(),
85 "(GitDocument) unresolved " + resource
); //$NON-NLS-1$
88 void populate() throws IOException
{
89 // TODO is this the right location?
90 if (GitTraceLocation
.UI
.isActive())
91 GitTraceLocation
.getTrace().trace(
92 GitTraceLocation
.UI
.getLocation(),"(GitDocument) populate: " + resource
); //$NON-NLS-1$
93 RepositoryMapping mapping
= RepositoryMapping
.getMapping(resource
);
94 if (mapping
== null) {
95 setResolved(null, null, null, ""); //$NON-NLS-1$
98 final String gitPath
= mapping
.getRepoRelativePath(resource
);
99 final Repository repository
= mapping
.getRepository();
100 String baseline
= GitQuickDiffProvider
.baseline
.get(repository
);
101 if (baseline
== null)
102 baseline
= Constants
.HEAD
;
103 ObjectId commitId
= repository
.resolve(baseline
);
104 if (commitId
!= null) {
105 if (commitId
.equals(lastCommit
)) {
106 // TODO is this the right location?
107 if (GitTraceLocation
.UI
.isActive())
108 GitTraceLocation
.getTrace().trace(
109 GitTraceLocation
.UI
.getLocation(),
110 "(GitDocument) already resolved"); //$NON-NLS-1$
114 Activator
.logError("Could not resolve quickdiff baseline "
115 + baseline
+ " corresponding to " + resource
+ " in "
116 + repository
, new Throwable());
117 setResolved(null, null, null, ""); //$NON-NLS-1$
120 Commit baselineCommit
= repository
.mapCommit(commitId
);
121 if (baselineCommit
== null) {
122 Activator
.logError("Could not load commit " + commitId
+ " for "
123 + baseline
+ " corresponding to " + resource
+ " in "
124 + repository
, new Throwable());
125 setResolved(null, null, null, ""); //$NON-NLS-1$
128 ObjectId treeId
= baselineCommit
.getTreeId();
129 if (treeId
.equals(lastTree
)) {
130 // TODO is this the right location?
131 if (GitTraceLocation
.UI
.isActive())
132 GitTraceLocation
.getTrace().trace(
133 GitTraceLocation
.UI
.getLocation(),
134 "(GitDocument) already resolved"); //$NON-NLS-1$
137 Tree baselineTree
= baselineCommit
.getTree();
138 if (baselineTree
== null) {
139 Activator
.logError("Could not load tree " + treeId
+ " for "
140 + baseline
+ " corresponding to " + resource
+ " in "
141 + repository
, new Throwable());
142 setResolved(null, null, null, ""); //$NON-NLS-1$
145 TreeEntry blobEntry
= baselineTree
.findBlobMember(gitPath
);
146 if (blobEntry
!= null && !blobEntry
.getId().equals(lastBlob
)) {
147 // TODO is this the right location?
148 if (GitTraceLocation
.UI
.isActive())
149 GitTraceLocation
.getTrace().trace(
150 GitTraceLocation
.UI
.getLocation(),
151 "(GitDocument) compareTo: " + baseline
); //$NON-NLS-1$
152 ObjectLoader loader
= repository
.openBlob(blobEntry
.getId());
153 byte[] bytes
= loader
.getBytes();
155 // Get the encoding for the current version. As a matter of
156 // principle one might want to use the eclipse settings for the
157 // version we are retrieving as that may be defined by the
158 // project settings, but there is no historic API for this.
159 IEncodedStorage encodedStorage
= ((IEncodedStorage
)resource
);
161 if (encodedStorage
!= null)
162 charset
= encodedStorage
.getCharset();
164 charset
= resource
.getParent().getDefaultCharset();
165 } catch (CoreException e
) {
166 charset
= Constants
.CHARACTER_ENCODING
;
168 // Finally we could consider validating the content with respect
169 // to the content. We don't do that here.
170 String s
= new String(bytes
, charset
);
171 setResolved(commitId
, baselineTree
.getId(), blobEntry
.getId(), s
);
172 // TODO is this the right location?
173 if (GitTraceLocation
.UI
.isActive())
177 GitTraceLocation
.UI
.getLocation(),
178 "(GitDocument) has reference doc, size=" + s
.length() + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
180 if (blobEntry
== null)
181 setResolved(null, null, null, ""); //$NON-NLS-1$
183 // TODO is this the right location?
184 if (GitTraceLocation
.UI
.isActive())
185 GitTraceLocation
.getTrace().trace(
186 GitTraceLocation
.UI
.getLocation(),
187 "(GitDocument) already resolved"); //$NON-NLS-1$
192 // TODO is this the right location?
193 if (GitTraceLocation
.UI
.isActive())
194 GitTraceLocation
.getTrace().trace(
195 GitTraceLocation
.UI
.getLocation(),
196 "(GitDocument) dispose: " + resource
); //$NON-NLS-1$
197 doc2repo
.remove(this);
198 Repository repository
= getRepository();
199 if (repository
!= null)
200 repository
.removeRepositoryChangedListener(this);
203 public void refsChanged(final RefsChangedEvent e
) {
206 } catch (IOException e1
) {
207 Activator
.logError("Failed to refresh quickdiff", e1
);
211 public void indexChanged(final IndexChangedEvent e
) {
212 // Index not relevant at this moment
215 private Repository
getRepository() {
216 RepositoryMapping mapping
= RepositoryMapping
.getMapping(resource
);
217 return (mapping
!= null) ? mapping
.getRepository() : null;
221 * A change occurred to a repository. Update any GitDocument instances
222 * referring to such repositories.
224 * @param repository Repository which changed
225 * @throws IOException
227 static void refreshRelevant(final Repository repository
) throws IOException
{
228 for (Map
.Entry
<GitDocument
, Repository
> i
: doc2repo
.entrySet()) {
229 if (i
.getValue() == repository
) {
230 i
.getKey().populate();