Remove trailing whitespace across EGit
[egit.git] / org.eclipse.egit.core / src / org / eclipse / egit / core / project / RepositoryMapping.java
blob2b7e874bce86568ec9e8c5f849c15c752fc69afb
1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * Copyright (C) 2008, Shunichi Fuji <palglowr@gmail.com>
6 * Copyright (C) 2008, Google Inc.
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * http://www.eclipse.org/legal/epl-v10.html
12 *******************************************************************************/
13 package org.eclipse.egit.core.project;
15 import java.io.File;
16 import java.io.IOException;
17 import java.io.UnsupportedEncodingException;
18 import java.util.Properties;
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.Path;
26 import org.eclipse.egit.core.GitProvider;
27 import org.eclipse.team.core.RepositoryProvider;
28 import org.eclipse.jgit.lib.Constants;
29 import org.eclipse.jgit.lib.GitIndex;
30 import org.eclipse.jgit.lib.Repository;
31 import org.eclipse.jgit.lib.Tree;
32 import org.eclipse.jgit.lib.TreeEntry;
33 import org.eclipse.jgit.lib.GitIndex.Entry;
35 /**
36 * This class keeps track
38 public class RepositoryMapping {
39 static boolean isInitialKey(final String key) {
40 return key.endsWith(".gitdir");
43 private final String containerPath;
45 private final String gitdirPath;
47 private Repository db;
49 private String workdirPrefix;
51 private IContainer container;
53 /**
54 * Construct a {@link RepositoryMapping} for a previously connected project.
56 * @param p TODO
57 * @param initialKey TODO
59 public RepositoryMapping(final Properties p, final String initialKey) {
60 final int dot = initialKey.lastIndexOf('.');
62 containerPath = initialKey.substring(0, dot);
63 gitdirPath = p.getProperty(initialKey);
66 /**
67 * Construct a {@link RepositoryMapping} for previously
68 * unknown project.
70 * @param mappedContainer
71 * @param gitDir
73 public RepositoryMapping(final IContainer mappedContainer, final File gitDir) {
74 final IPath cLoc = mappedContainer.getLocation()
75 .removeTrailingSeparator();
76 final IPath gLoc = Path.fromOSString(gitDir.getAbsolutePath())
77 .removeTrailingSeparator();
78 final IPath gLocParent = gLoc.removeLastSegments(1);
79 String p;
80 int cnt;
82 container = mappedContainer;
83 containerPath = container.getProjectRelativePath().toPortableString();
85 if (cLoc.isPrefixOf(gLoc)) {
86 gitdirPath = gLoc.removeFirstSegments(
87 gLoc.matchingFirstSegments(cLoc)).toPortableString();
88 } else if (gLocParent.isPrefixOf(cLoc)) {
89 cnt = cLoc.segmentCount() - cLoc.matchingFirstSegments(gLocParent);
90 p = "";
91 while (cnt-- > 0) {
92 p += "../";
94 p += gLoc.segment(gLoc.segmentCount() - 1);
95 gitdirPath = p;
96 } else {
97 gitdirPath = gLoc.toPortableString();
101 IPath getContainerPath() {
102 return Path.fromPortableString(containerPath);
105 IPath getGitDirPath() {
106 return Path.fromPortableString(gitdirPath);
110 * @return the workdir file, i.e. where the files are checked out
112 public File getWorkDir() {
113 return getRepository().getWorkDir();
116 synchronized void clear() {
117 db = null;
118 workdirPrefix = null;
119 container = null;
123 * @return a reference to the repository object handled by this mapping
125 public synchronized Repository getRepository() {
126 return db;
129 synchronized void setRepository(final Repository r) {
130 db = r;
132 try {
133 workdirPrefix = getWorkDir().getCanonicalPath();
134 } catch (IOException err) {
135 workdirPrefix = getWorkDir().getAbsolutePath();
137 workdirPrefix = workdirPrefix.replace('\\', '/');
138 if (!workdirPrefix.endsWith("/"))
139 workdirPrefix += "/";
143 * @return the mapped container (currently project)
145 public synchronized IContainer getContainer() {
146 return container;
149 synchronized void setContainer(final IContainer c) {
150 container = c;
154 * Notify registered {@link RepositoryChangeListener}s of a change.
156 * @see GitProjectData#addRepositoryChangeListener(RepositoryChangeListener)
158 public void fireRepositoryChanged() {
159 GitProjectData.fireRepositoryChanged(this);
162 synchronized void store(final Properties p) {
163 p.setProperty(containerPath + ".gitdir", gitdirPath);
166 public String toString() {
167 return "RepositoryMapping[" + containerPath + " -> " + gitdirPath + "]";
171 * Check whether a resource has been changed relative to the checked out
172 * version. Content is assumed changed by this routine if the resource's
173 * modification time differs from what is recorded in the index, but the
174 * real content hasn't changed. The reason is performance.
176 * @param rsrc
177 * @return true if a resource differs in the workdir or index relative to
178 * HEAD
180 * @throws IOException
181 * @throws UnsupportedEncodingException
183 public boolean isResourceChanged(IResource rsrc) throws IOException, UnsupportedEncodingException {
184 Repository repository = getRepository();
185 GitIndex index = repository.getIndex();
186 String repoRelativePath = getRepoRelativePath(rsrc);
187 Tree headTree = repository.mapTree(Constants.HEAD);
188 TreeEntry blob = headTree!=null ? headTree.findBlobMember(repoRelativePath) : null;
189 Entry entry = index.getEntry(repoRelativePath);
190 if (rsrc instanceof IFile && entry == null && blob == null)
191 return false;
192 if (entry == null)
193 return true; // flags new resources as changes
194 if (blob == null)
195 return true; // added in index
196 boolean hashesDiffer = !entry.getObjectId().equals(blob.getId());
197 return hashesDiffer || entry.isModified(getWorkDir());
201 * @param rsrc
202 * @return the path relative to the Git repository, including base name.
204 public String getRepoRelativePath(final IResource rsrc) {
205 // We should only be called for resources that are actually
206 // in this repository, so we can safely assume that their
207 // path prefix matches workdirPrefix. Testing that here is
208 // rather expensive so we don't bother.
210 final int pfxLen = workdirPrefix.length();
211 final String p = rsrc.getLocation().toString();
212 final int pLen = p.length();
213 if (pLen > pfxLen)
214 return p.substring(pfxLen);
215 else if (p.length() == pfxLen - 1)
216 return "";
217 return null;
221 * Get the repository mapping for a resource
223 * @param resource
224 * @return the RepositoryMapping for this resource,
225 * or null for non GitProvider.
227 public static RepositoryMapping getMapping(final IResource resource) {
228 final IProject project = resource.getProject();
229 if (project == null)
230 return null;
232 final RepositoryProvider rp = RepositoryProvider.getProvider(project);
233 if (!(rp instanceof GitProvider))
234 return null;
236 if (((GitProvider)rp).getData() == null)
237 return null;
239 return ((GitProvider)rp).getData().getRepositoryMapping(resource);
243 * @return the name of the .git directory
245 public String getGitDir() {
246 return gitdirPath;