Git Repositories View: Allow to "remove" multiple Repositories
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / decorators / GitDocument.java
blob9b5a43ddca9bb77bba4bbea3ea379b6cecd08973
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;
12 import java.util.Map;
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);
56 ret.populate();
57 final Repository repository = ret.getRepository();
58 if (repository != null)
59 repository.addRepositoryChangedListener(ret);
61 return 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;
73 set(value);
74 if (blob != null)
75 // TODO is this the right location?
76 if (GitTraceLocation.UI.isActive())
77 GitTraceLocation
78 .getTrace()
79 .trace(
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$
82 else
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$
98 return;
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$
113 return;
115 } else {
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$
120 return;
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$
128 return;
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$
137 return;
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$
145 return;
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();
156 String charset;
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);
162 try {
163 if (encodedStorage != null)
164 charset = encodedStorage.getCharset();
165 else
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())
176 GitTraceLocation
177 .getTrace()
178 .trace(
179 GitTraceLocation.UI.getLocation(),
180 "(GitDocument) has reference doc, size=" + s.length() + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
181 } else {
182 if (blobEntry == null)
183 setResolved(null, null, null, ""); //$NON-NLS-1$
184 else
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$
193 void dispose() {
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) {
206 try {
207 populate();
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();