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@xxxxxxxxxxx> --- .../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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html