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
.project
.RepositoryMapping
;
20 import org
.eclipse
.egit
.ui
.Activator
;
21 import org
.eclipse
.egit
.ui
.UIText
;
22 import org
.eclipse
.egit
.ui
.internal
.trace
.GitTraceLocation
;
23 import org
.eclipse
.jface
.text
.Document
;
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
;
35 import org
.eclipse
.osgi
.util
.NLS
;
36 import org
.eclipse
.team
.core
.RepositoryProvider
;
38 class GitDocument
extends Document
implements RepositoryListener
{
39 private final IResource resource
;
41 private ObjectId lastCommit
;
42 private ObjectId lastTree
;
43 private ObjectId lastBlob
;
45 static Map
<GitDocument
,Repository
> doc2repo
= new WeakHashMap
<GitDocument
, Repository
>();
47 static GitDocument
create(final IResource resource
) throws IOException
{
48 // TODO is this the right location?
49 if (GitTraceLocation
.UI
.isActive())
50 GitTraceLocation
.getTrace().trace(
51 GitTraceLocation
.UI
.getLocation(),
52 "(GitDocument) create: " + resource
); //$NON-NLS-1$
53 GitDocument ret
= null;
54 if (RepositoryProvider
.getProvider(resource
.getProject()) instanceof GitProvider
) {
55 ret
= new GitDocument(resource
);
57 final Repository repository
= ret
.getRepository();
58 if (repository
!= null)
59 repository
.addRepositoryChangedListener(ret
);
64 private GitDocument(IResource resource
) {
65 this.resource
= resource
;
66 GitDocument
.doc2repo
.put(this, getRepository());
69 private void setResolved(final AnyObjectId commit
, final AnyObjectId tree
, final AnyObjectId blob
, final String value
) {
70 lastCommit
= commit
!= null ? commit
.copy() : null;
71 lastTree
= tree
!= null ? tree
.copy() : null;
72 lastBlob
= blob
!= null ? blob
.copy() : null;
75 // TODO is this the right location?
76 if (GitTraceLocation
.UI
.isActive())
80 GitTraceLocation
.UI
.getLocation(),
81 "(GitDocument) resolved " + resource
+ " to " + lastBlob
+ " in " + lastCommit
+ "/" + lastTree
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
83 // TODO is this the right location?
84 if (GitTraceLocation
.UI
.isActive())
85 GitTraceLocation
.getTrace().trace(
86 GitTraceLocation
.UI
.getLocation(),
87 "(GitDocument) unresolved " + resource
); //$NON-NLS-1$
90 void populate() throws IOException
{
91 // TODO is this the right location?
92 if (GitTraceLocation
.UI
.isActive())
93 GitTraceLocation
.getTrace().trace(
94 GitTraceLocation
.UI
.getLocation(),"(GitDocument) populate: " + resource
); //$NON-NLS-1$
95 RepositoryMapping mapping
= RepositoryMapping
.getMapping(resource
);
96 if (mapping
== null) {
97 setResolved(null, null, null, ""); //$NON-NLS-1$
100 final String gitPath
= mapping
.getRepoRelativePath(resource
);
101 final Repository repository
= mapping
.getRepository();
102 String baseline
= GitQuickDiffProvider
.baseline
.get(repository
);
103 if (baseline
== null)
104 baseline
= Constants
.HEAD
;
105 ObjectId commitId
= repository
.resolve(baseline
);
106 if (commitId
!= null) {
107 if (commitId
.equals(lastCommit
)) {
108 // TODO is this the right location?
109 if (GitTraceLocation
.UI
.isActive())
110 GitTraceLocation
.getTrace().trace(
111 GitTraceLocation
.UI
.getLocation(),
112 "(GitDocument) already resolved"); //$NON-NLS-1$
116 String msg
= NLS
.bind(UIText
.GitDocument_errorResolveQuickdiff
,
117 new Object
[] { baseline
, resource
, repository
});
118 Activator
.logError(msg
, new Throwable());
119 setResolved(null, null, null, ""); //$NON-NLS-1$
122 Commit baselineCommit
= repository
.mapCommit(commitId
);
123 if (baselineCommit
== null) {
124 String msg
= NLS
.bind(UIText
.GitDocument_errorLoadCommit
,
125 new Object
[] { commitId
, baseline
, resource
, repository
});
126 Activator
.logError(msg
, new Throwable());
127 setResolved(null, null, null, ""); //$NON-NLS-1$
130 ObjectId treeId
= baselineCommit
.getTreeId();
131 if (treeId
.equals(lastTree
)) {
132 // TODO is this the right location?
133 if (GitTraceLocation
.UI
.isActive())
134 GitTraceLocation
.getTrace().trace(
135 GitTraceLocation
.UI
.getLocation(),
136 "(GitDocument) already resolved"); //$NON-NLS-1$
139 Tree baselineTree
= baselineCommit
.getTree();
140 if (baselineTree
== null) {
141 String msg
= NLS
.bind(UIText
.GitDocument_errorLoadTree
,
142 new Object
[] { treeId
, baseline
, resource
, repository
});
143 Activator
.logError(msg
, new Throwable());
144 setResolved(null, null, null, ""); //$NON-NLS-1$
147 TreeEntry blobEntry
= baselineTree
.findBlobMember(gitPath
);
148 if (blobEntry
!= null && !blobEntry
.getId().equals(lastBlob
)) {
149 // TODO is this the right location?
150 if (GitTraceLocation
.UI
.isActive())
151 GitTraceLocation
.getTrace().trace(
152 GitTraceLocation
.UI
.getLocation(),
153 "(GitDocument) compareTo: " + baseline
); //$NON-NLS-1$
154 ObjectLoader loader
= repository
.openBlob(blobEntry
.getId());
155 byte[] bytes
= loader
.getBytes();
157 // Get the encoding for the current version. As a matter of
158 // principle one might want to use the eclipse settings for the
159 // version we are retrieving as that may be defined by the
160 // project settings, but there is no historic API for this.
161 IEncodedStorage encodedStorage
= ((IEncodedStorage
)resource
);
163 if (encodedStorage
!= null)
164 charset
= encodedStorage
.getCharset();
166 charset
= resource
.getParent().getDefaultCharset();
167 } catch (CoreException e
) {
168 charset
= Constants
.CHARACTER_ENCODING
;
170 // Finally we could consider validating the content with respect
171 // to the content. We don't do that here.
172 String s
= new String(bytes
, charset
);
173 setResolved(commitId
, baselineTree
.getId(), blobEntry
.getId(), s
);
174 // TODO is this the right location?
175 if (GitTraceLocation
.UI
.isActive())
179 GitTraceLocation
.UI
.getLocation(),
180 "(GitDocument) has reference doc, size=" + s
.length() + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
182 if (blobEntry
== null)
183 setResolved(null, null, null, ""); //$NON-NLS-1$
185 // TODO is this the right location?
186 if (GitTraceLocation
.UI
.isActive())
187 GitTraceLocation
.getTrace().trace(
188 GitTraceLocation
.UI
.getLocation(),
189 "(GitDocument) already resolved"); //$NON-NLS-1$
194 // TODO is this the right location?
195 if (GitTraceLocation
.UI
.isActive())
196 GitTraceLocation
.getTrace().trace(
197 GitTraceLocation
.UI
.getLocation(),
198 "(GitDocument) dispose: " + resource
); //$NON-NLS-1$
199 doc2repo
.remove(this);
200 Repository repository
= getRepository();
201 if (repository
!= null)
202 repository
.removeRepositoryChangedListener(this);
205 public void refsChanged(final RefsChangedEvent e
) {
208 } catch (IOException e1
) {
209 Activator
.logError(UIText
.GitDocument_errorRefreshQuickdiff
, e1
);
213 public void indexChanged(final IndexChangedEvent e
) {
214 // Index not relevant at this moment
217 private Repository
getRepository() {
218 RepositoryMapping mapping
= RepositoryMapping
.getMapping(resource
);
219 return (mapping
!= null) ? mapping
.getRepository() : null;
223 * A change occurred to a repository. Update any GitDocument instances
224 * referring to such repositories.
226 * @param repository Repository which changed
227 * @throws IOException
229 static void refreshRelevant(final Repository repository
) throws IOException
{
230 for (Map
.Entry
<GitDocument
, Repository
> i
: doc2repo
.entrySet()) {
231 if (i
.getValue() == repository
) {
232 i
.getKey().populate();