git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[EGIT PATCH 3/5] Fix RepositoryMapping.getRepoRelativePath to honor linked resources

From
Shawn O. Pearce <spearce@spearce.org>
Date
Aug 6, 2008, 03:09 UTC
Message-ID
<1217992180-5697-4-git-send-email-spearce@spearce.org>
In-Reply-To
<1217992180-5697-3-git-send-email-spearce@spearce.org>

If a project resource is linked to a repository working directory we should be locating the path of the resource within the repository by the path it appears in the filesystem, not the path it appears at in the Eclipse project structure. By using the filesystem location we can ensure the paths match what C Git would see when accessing the same resource.

By making this change we can now safely remove the subset concept from RepositoryMapping as it was a crude form of trying to come up with the same result when projects appeared within a repository.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../egit/core/op/ConnectProviderOperation.java     |   14 +----
 .../egit/core/project/RepositoryFinder.java        |   11 +--
 .../egit/core/project/RepositoryMapping.java       |   65 ++++++++-----------
 3 files changed, 32 insertions(+), 58 deletions(-)
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java b/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java
index 3ed3569..bf814f4 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java
@@ -15,10 +15,8 @@ import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspaceRunnable;
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.team.core.RepositoryProvider;
 import org.spearce.egit.core.Activator;
@@ -70,17 +68,7 @@ public class ConnectProviderOperation implements IWorkspaceRunnable {
 
 					db = new Repository(newGitDir);
 					db.create();
-					IPath gitDirParent = Path.fromOSString(
-							db.getDirectory().getAbsolutePath())
-							.removeLastSegments(1);
-					IPath cPath = project.getLocation();
-					String subset = null;
-					if (gitDirParent.isPrefixOf(cPath)) {
-						int n = cPath.matchingFirstSegments(gitDirParent);
-						subset = cPath.removeFirstSegments(n).toPortableString();
-					}
-					repos.add(new RepositoryMapping(project, db.getDirectory(),
-							subset));
+					repos.add(new RepositoryMapping(project, db.getDirectory()));
 					db.close();
 
 					// If we don't refresh the project directory right
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java
index 68cf79c..116a7bf 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java
@@ -92,17 +92,15 @@ public class RepositoryFinder {
 				final IResource[] children;
 
 				if (ownCfg.isFile()) {
-					register(c, ownCfg.getParentFile(), null);
+					register(c, ownCfg.getParentFile());
 				} else if (c.isLinked() || c instanceof IProject) {
-					String s = fsLoc.getName();
 					File p = fsLoc.getParentFile();
 					while (p != null) {
 						final File pCfg = configFor(p);
 						if (pCfg.isFile()) {
-							register(c, pCfg.getParentFile(), s);
+							register(c, pCfg.getParentFile());
 							break;
 						}
-						s = p.getName() + "/" + s;
 						p = p.getParentFile();
 					}
 				}
@@ -132,14 +130,13 @@ public class RepositoryFinder {
 		return new File(new File(fsLoc, ".git"), "config");
 	}
 
-	private void register(final IContainer c, final File gitdir,
-			final String subset) {
+	private void register(final IContainer c, final File gitdir) {
 		File f;
 		try {
 			f = gitdir.getCanonicalFile();
 		} catch (IOException ioe) {
 			f = gitdir.getAbsoluteFile();
 		}
-		results.add(new RepositoryMapping(c, f, subset));
+		results.add(new RepositoryMapping(c, f));
 	}
 }
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java
index 6a0b56f..17e8142 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java
@@ -41,10 +41,10 @@ public class RepositoryMapping {
 
 	private final String gitdirPath;
 
-	private final String subset;
-
 	private Repository db;
 
+	private String workdirPrefix;
+
 	private IContainer container;
 
 	/**
@@ -55,12 +55,9 @@ public class RepositoryMapping {
 	 */
 	public RepositoryMapping(final Properties p, final String initialKey) {
 		final int dot = initialKey.lastIndexOf('.');
-		String s;
 
 		containerPath = initialKey.substring(0, dot);
 		gitdirPath = p.getProperty(initialKey);
-		s = p.getProperty(containerPath + ".subset");
-		subset = "".equals(s) ? null : s;
 	}
 
 	/**
@@ -69,10 +66,8 @@ public class RepositoryMapping {
 	 *
 	 * @param mappedContainer
 	 * @param gitDir
-	 * @param subsetRoot
 	 */
-	public RepositoryMapping(final IContainer mappedContainer,
-			final File gitDir, final String subsetRoot) {
+	public RepositoryMapping(final IContainer mappedContainer, final File gitDir) {
 		final IPath cLoc = mappedContainer.getLocation()
 				.removeTrailingSeparator();
 		final IPath gLoc = Path.fromOSString(gitDir.getAbsolutePath())
@@ -98,8 +93,6 @@ public class RepositoryMapping {
 		} else {
 			gitdirPath = gLoc.toPortableString();
 		}
-
-		subset = "".equals(subsetRoot) ? null : subsetRoot;
 	}
 
 	IPath getContainerPath() {
@@ -111,17 +104,6 @@ public class RepositoryMapping {
 	}
 
 	/**
-	 * Eclipse projects typically reside one or more levels
-	 * below the repository. This method return the relative
-	 * path to the project. Null is returned instead of "".
-	 *
-	 * @return relative path from repository to project, or null
-	 */
-	public String getSubset() {
-		return subset;
-	}
-
-	/**
 	 * @return the workdir file, i.e. where the files are checked out
 	 */
 	public File getWorkDir() {
@@ -130,6 +112,7 @@ public class RepositoryMapping {
 
 	synchronized void clear() {
 		db = null;
+		workdirPrefix = null;
 		container = null;
 	}
 
@@ -142,6 +125,15 @@ public class RepositoryMapping {
 
 	synchronized void setRepository(final Repository r) {
 		db = r;
+
+		try {
+			workdirPrefix = getWorkDir().getCanonicalPath();
+		} catch (IOException err) {
+			workdirPrefix = getWorkDir().getAbsolutePath();
+		}
+		workdirPrefix = workdirPrefix.replace('\\', '/');
+		if (!workdirPrefix.endsWith("/"))
+			workdirPrefix += "/";
 	}
 
 	/**
@@ -166,9 +158,6 @@ public class RepositoryMapping {
 
 	synchronized void store(final Properties p) {
 		p.setProperty(containerPath + ".gitdir", gitdirPath);
-		if (subset != null && !"".equals(subset)) {
-			p.setProperty(containerPath + ".subset", subset);
-		}
 	}
 
 	public String toString() {
@@ -209,20 +198,20 @@ public class RepositoryMapping {
 	 * @param rsrc
 	 * @return the path relative to the Git repository, including base name.
 	 */
-	public String getRepoRelativePath(IResource rsrc) {
-		String prefix = getSubset();
-		String projectRelativePath = rsrc.getProjectRelativePath().toString();
-		String repoRelativePath;
-		if (prefix != null) {
-			if (projectRelativePath.length() == 0)
-				repoRelativePath = prefix;
-			else
-				repoRelativePath = prefix + "/" + projectRelativePath;
-		} else
-			repoRelativePath = projectRelativePath;
-
-		assert repoRelativePath != null;
-		return repoRelativePath;
+	public String getRepoRelativePath(final IResource rsrc) {
+		// We should only be called for resources that are actually
+		// in this repository, so we can safely assume that their
+		// path prefix matches workdirPrefix. Testing that here is
+		// rather expensive so we don't bother.
+		//
+		final int pfxLen = workdirPrefix.length();
+		final String p = rsrc.getLocation().toString();
+		final int pLen = p.length();
+		if (pLen > pfxLen)
+			return p.substring(pfxLen);
+		else if (p.length() == pfxLen - 1)
+			return "";
+		return null;
 	}
 
 	/**
-- 
1.6.0.rc1.250.g9b5e2
Previous: Shawn O. PearceNext: Shawn O. Pearce
Message 4 of 6 in “Support linked resources in repositories”
  1. 0/5 Support linked resources in repositoriesShawn O. Pearce, Aug 6, 2008
  2. 1/5 Remove the pointless GitProjectData resource change listenerShawn O. Pearce, Aug 6, 2008
  3. 2/5 Don't crash the decorator update loop when resources are deletedShawn O. Pearce, Aug 6, 2008
  4. 3/5 Fix RepositoryMapping.getRepoRelativePath to honor linked resourcesShawn O. Pearce, Aug 6, 2008
  5. 4/5 Change GitProjectData.getRepositoryMapping to work on linked resourcesShawn O. Pearce, Aug 6, 2008
  6. 5/5 Correct getRepositoryMapping callers to use any IResourceShawn O. Pearce, Aug 6, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.