{"thread":{"id":"14853","subject":"[EGIT PATCH 1/5] Remove the pointless GitProjectData resource change listener","startedAt":"2008-08-06T03:09:35Z","lastAt":"2008-08-06T03:09:40Z","messageCount":6,"participants":["Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"86309","messageId":"1217992180-5697-1-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":null,"subject":"[EGIT PATCH 0/5] Support linked resources in repositories","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:35Z","receivedAt":"2008-08-06T03:09:35Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Sometimes users need to create links inside of a project to point\nback to their Git working directory.  This is sort of like a symlink\nin POSIX, but its managed at the Eclipse workspace level.\n\nIf a resource is contained within a linked directory and that is\nalso within a Git repository we want to allow Git operations on\nthat linked resource to operate using the paths of the files as\nthey are in the repository working directory, and not the path of\nthe files in the Eclipse workspace.\n\nShawn O. Pearce (5):\n  Remove the pointless GitProjectData resource change listener\n  Don't crash the decorator update loop when resources are deleted\n  Fix RepositoryMapping.getRepoRelativePath to honor linked resources\n  Change GitProjectData.getRepositoryMapping to work on linked\n    resources\n  Correct getRepositoryMapping callers to use any IResource\n\n .../egit/core/op/ConnectProviderOperation.java     |   14 +---\n .../org/spearce/egit/core/op/UntrackOperation.java |    4 +-\n .../spearce/egit/core/project/GitProjectData.java  |  111 ++++++--------------\n .../egit/core/project/RepositoryFinder.java        |   11 +--\n .../egit/core/project/RepositoryMapping.java       |   79 ++++++--------\n .../egit/ui/internal/actions/CommitAction.java     |    2 +-\n .../internal/decorators/GitResourceDecorator.java  |   11 ++-\n 7 files changed, 81 insertions(+), 151 deletions(-)\n"},{"id":"86308","messageId":"1217992180-5697-2-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":"1217992180-5697-1-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 1/5] Remove the pointless GitProjectData resource change listener","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:36Z","receivedAt":"2008-08-06T03:09:36Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Apparently on any IResourceChangeEvent.POST_CHANGE we just burn some\nCPU time and generate some garbage for the GC to clean out later.  I\ncannot see a reason why this code is still here.  My memory says we\ndid this in the past to notify the resource decorator that it needs\nto update, or we used it for our cache tree invalidation.\n\nSince this code has no side effect other than to waste time we can\nsafely remove it, and cut our project down a little bit.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/egit/core/project/GitProjectData.java  |   64 --------------------\n 1 files changed, 0 insertions(+), 64 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\nindex 8754bd1..3d5424c 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\n@@ -29,8 +29,6 @@ import org.eclipse.core.resources.IProject;\n import org.eclipse.core.resources.IResource;\n import org.eclipse.core.resources.IResourceChangeEvent;\n import org.eclipse.core.resources.IResourceChangeListener;\n-import org.eclipse.core.resources.IResourceDelta;\n-import org.eclipse.core.resources.IResourceDeltaVisitor;\n import org.eclipse.core.resources.ResourcesPlugin;\n import org.eclipse.core.runtime.CoreException;\n import org.eclipse.core.runtime.Preferences;\n@@ -61,10 +59,6 @@ public class GitProjectData {\n \t\t@SuppressWarnings(\"synthetic-access\")\n \t\tpublic void resourceChanged(final IResourceChangeEvent event) {\n \t\t\tswitch (event.getType()) {\n-\t\t\tcase IResourceChangeEvent.POST_CHANGE:\n-\t\t\t\tprojectsChanged(event.getDelta().getAffectedChildren(\n-\t\t\t\t\t\tIResourceDelta.CHANGED));\n-\t\t\t\tbreak;\n \t\t\tcase IResourceChangeEvent.PRE_CLOSE:\n \t\t\t\tuncache((IProject) event.getResource());\n \t\t\t\tbreak;\n@@ -182,16 +176,6 @@ public class GitProjectData {\n \t\tActivator.trace(\"(GitProjectData) \" + m);\n \t}\n \n-\tprivate static void projectsChanged(final IResourceDelta[] projDeltas) {\n-\t\tfor (int k = 0; k < projDeltas.length; k++) {\n-\t\t\tfinal IResource r = projDeltas[k].getResource();\n-\t\t\tfinal GitProjectData d = get((IProject) r);\n-\t\t\tif (d != null) {\n-\t\t\t\td.notifyChanged(projDeltas[k]);\n-\t\t\t}\n-\t\t}\n-\t}\n-\n \tprivate synchronized static void cache(final IProject p,\n \t\t\tfinal GitProjectData d) {\n \t\tprojectDataCache.put(p, d);\n@@ -380,54 +364,6 @@ public class GitProjectData {\n \t\t}\n \t}\n \n-\tprivate void notifyChanged(final IResourceDelta projDelta) {\n-//\t\tfinal Set affectedMappings = new HashSet();\n-\t\ttry {\n-\t\t\tprojDelta.accept(new IResourceDeltaVisitor() {\n-\t\t\t\tpublic boolean visit(final IResourceDelta d)\n-\t\t\t\t\t\tthrows CoreException {\n-\t\t\t\t\tfinal int f = d.getFlags();\n-\t\t\t\t\tIResource res = d.getResource();\n-\t\t\t\t\tIResource r = res;\n-\t\t\t\t\tif ((f & IResourceDelta.CONTENT) != 0\n-\t\t\t\t\t\t\t|| (f & IResourceDelta.ENCODING) != 0\n-\t\t\t\t\t\t\t|| r instanceof IContainer) {\n-\t\t\t\t\t\tString s = null;\n-\t\t\t\t\t\tRepositoryMapping m = null;\n-\n-\t\t\t\t\t\twhile (r != null) {\n-\t\t\t\t\t\t\tm = getRepositoryMapping(r);\n-\t\t\t\t\t\t\tif (m != null) {\n-\t\t\t\t\t\t\t\tbreak;\n-\t\t\t\t\t\t\t}\n-\n-\t\t\t\t\t\t\tif (s != null) {\n-\t\t\t\t\t\t\t\ts = r.getName() + \"/\" + s;\n-\t\t\t\t\t\t\t} else {\n-\t\t\t\t\t\t\t\ts = r.getName();\n-\t\t\t\t\t\t\t}\n-\n-\t\t\t\t\t\t\tr = r.getParent();\n-\t\t\t\t\t\t}\n-\n-\t\t\t\t\t\tif (m == null) {\n-\t\t\t\t\t\t\treturn false;\n-\t\t\t\t\t\t} else if (s == null) {\n-\t\t\t\t\t\t\treturn true;\n-\t\t\t\t\t\t}\n-\t\t\t\t\t}\n-\t\t\t\t\treturn false;\n-\t\t\t\t}\n-\t\t\t});\n-\t\t} catch (CoreException ce) {\n-\t\t\t// We are in deep trouble. This should NOT have happend. Detach\n-\t\t\t// our listeners and forget it ever did.\n-\t\t\t//\n-\t\t\tdetachFromWorkspace();\n-\t\t\tActivator.logError(CoreText.GitProjectData_notifyChangedFailed, ce);\n-\t\t}\n-\t}\n-\n \tprivate File propertyFile() {\n \t\treturn new File(getProject()\n \t\t\t\t.getWorkingLocation(Activator.getPluginId()).toFile(),\n-- \n1.6.0.rc1.250.g9b5e2\n"},{"id":"86310","messageId":"1217992180-5697-3-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":"1217992180-5697-2-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 2/5] Don't crash the decorator update loop when resources are deleted","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:37Z","receivedAt":"2008-08-06T03:09:37Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"If a resource is deleted from the workspace we don't need to clear\nits GITFOLDERDIRTYSTATEPROPERTY from the item because it is gone.\nThere won't be anyone else to query for that flag, so the flag is\nnot relevant anymore.  Further trying to call accept() on those\nresources throws an exception because Eclipse won't let you touch\na deleted resource.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../internal/decorators/GitResourceDecorator.java  |   11 +++++++++--\n 1 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java\nindex 6d2f88e..84ad949 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java\n@@ -126,6 +126,14 @@ public class GitResourceDecorator extends LabelProvider implements\n \t\t\t\t\t\tIterator<IResource> i = resources.iterator();\n \t\t\t\t\t\tm = i.next();\n \t\t\t\t\t\ti.remove();\n+\n+\t\t\t\t\t\twhile (!m.isAccessible()) {\n+\t\t\t\t\t\t\tif (!i.hasNext())\n+\t\t\t\t\t\t\t\treturn Status.OK_STATUS;\n+\t\t\t\t\t\t\tm = i.next();\n+\t\t\t\t\t\t\ti.remove();\n+\t\t\t\t\t\t}\n+\n \t\t\t\t\t\tif (resources.size() > 0)\n \t\t\t\t\t\t\tschedule();\n \t\t\t\t\t}\n@@ -188,8 +196,7 @@ public class GitResourceDecorator extends LabelProvider implements\n \t} // End ResCL\n \n \tvoid clearDecorationState(IResource r) throws CoreException {\n-\t\tif (r.isAccessible())\n-\t\t\tr.setSessionProperty(GITFOLDERDIRTYSTATEPROPERTY, null);\n+\t\tr.setSessionProperty(GITFOLDERDIRTYSTATEPROPERTY, null);\n \t\tfireLabelProviderChanged(new LabelProviderChangedEvent(this, r));\n \t}\n \n-- \n1.6.0.rc1.250.g9b5e2\n"},{"id":"86311","messageId":"1217992180-5697-4-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":"1217992180-5697-3-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 3/5] Fix RepositoryMapping.getRepoRelativePath to honor linked resources","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:38Z","receivedAt":"2008-08-06T03:09:38Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"If a project resource is linked to a repository working directory we\nshould be locating the path of the resource within the repository by\nthe path it appears in the filesystem, not the path it appears at in\nthe Eclipse project structure.  By using the filesystem location we\ncan ensure the paths match what C Git would see when accessing the\nsame resource.\n\nBy making this change we can now safely remove the subset concept\nfrom RepositoryMapping as it was a crude form of trying to come up\nwith the same result when projects appeared within a repository.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../egit/core/op/ConnectProviderOperation.java     |   14 +----\n .../egit/core/project/RepositoryFinder.java        |   11 +--\n .../egit/core/project/RepositoryMapping.java       |   65 ++++++++-----------\n 3 files changed, 32 insertions(+), 58 deletions(-)\n\ndiff --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\nindex 3ed3569..bf814f4 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/ConnectProviderOperation.java\n@@ -15,10 +15,8 @@ import org.eclipse.core.resources.IProject;\n import org.eclipse.core.resources.IResource;\n import org.eclipse.core.resources.IWorkspaceRunnable;\n import org.eclipse.core.runtime.CoreException;\n-import org.eclipse.core.runtime.IPath;\n import org.eclipse.core.runtime.IProgressMonitor;\n import org.eclipse.core.runtime.NullProgressMonitor;\n-import org.eclipse.core.runtime.Path;\n import org.eclipse.core.runtime.SubProgressMonitor;\n import org.eclipse.team.core.RepositoryProvider;\n import org.spearce.egit.core.Activator;\n@@ -70,17 +68,7 @@ public class ConnectProviderOperation implements IWorkspaceRunnable {\n \n \t\t\t\t\tdb = new Repository(newGitDir);\n \t\t\t\t\tdb.create();\n-\t\t\t\t\tIPath gitDirParent = Path.fromOSString(\n-\t\t\t\t\t\t\tdb.getDirectory().getAbsolutePath())\n-\t\t\t\t\t\t\t.removeLastSegments(1);\n-\t\t\t\t\tIPath cPath = project.getLocation();\n-\t\t\t\t\tString subset = null;\n-\t\t\t\t\tif (gitDirParent.isPrefixOf(cPath)) {\n-\t\t\t\t\t\tint n = cPath.matchingFirstSegments(gitDirParent);\n-\t\t\t\t\t\tsubset = cPath.removeFirstSegments(n).toPortableString();\n-\t\t\t\t\t}\n-\t\t\t\t\trepos.add(new RepositoryMapping(project, db.getDirectory(),\n-\t\t\t\t\t\t\tsubset));\n+\t\t\t\t\trepos.add(new RepositoryMapping(project, db.getDirectory()));\n \t\t\t\t\tdb.close();\n \n \t\t\t\t\t// If we don't refresh the project directory right\ndiff --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\nindex 68cf79c..116a7bf 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryFinder.java\n@@ -92,17 +92,15 @@ public class RepositoryFinder {\n \t\t\t\tfinal IResource[] children;\n \n \t\t\t\tif (ownCfg.isFile()) {\n-\t\t\t\t\tregister(c, ownCfg.getParentFile(), null);\n+\t\t\t\t\tregister(c, ownCfg.getParentFile());\n \t\t\t\t} else if (c.isLinked() || c instanceof IProject) {\n-\t\t\t\t\tString s = fsLoc.getName();\n \t\t\t\t\tFile p = fsLoc.getParentFile();\n \t\t\t\t\twhile (p != null) {\n \t\t\t\t\t\tfinal File pCfg = configFor(p);\n \t\t\t\t\t\tif (pCfg.isFile()) {\n-\t\t\t\t\t\t\tregister(c, pCfg.getParentFile(), s);\n+\t\t\t\t\t\t\tregister(c, pCfg.getParentFile());\n \t\t\t\t\t\t\tbreak;\n \t\t\t\t\t\t}\n-\t\t\t\t\t\ts = p.getName() + \"/\" + s;\n \t\t\t\t\t\tp = p.getParentFile();\n \t\t\t\t\t}\n \t\t\t\t}\n@@ -132,14 +130,13 @@ public class RepositoryFinder {\n \t\treturn new File(new File(fsLoc, \".git\"), \"config\");\n \t}\n \n-\tprivate void register(final IContainer c, final File gitdir,\n-\t\t\tfinal String subset) {\n+\tprivate void register(final IContainer c, final File gitdir) {\n \t\tFile f;\n \t\ttry {\n \t\t\tf = gitdir.getCanonicalFile();\n \t\t} catch (IOException ioe) {\n \t\t\tf = gitdir.getAbsoluteFile();\n \t\t}\n-\t\tresults.add(new RepositoryMapping(c, f, subset));\n+\t\tresults.add(new RepositoryMapping(c, f));\n \t}\n }\ndiff --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\nindex 6a0b56f..17e8142 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java\n@@ -41,10 +41,10 @@ public class RepositoryMapping {\n \n \tprivate final String gitdirPath;\n \n-\tprivate final String subset;\n-\n \tprivate Repository db;\n \n+\tprivate String workdirPrefix;\n+\n \tprivate IContainer container;\n \n \t/**\n@@ -55,12 +55,9 @@ public class RepositoryMapping {\n \t */\n \tpublic RepositoryMapping(final Properties p, final String initialKey) {\n \t\tfinal int dot = initialKey.lastIndexOf('.');\n-\t\tString s;\n \n \t\tcontainerPath = initialKey.substring(0, dot);\n \t\tgitdirPath = p.getProperty(initialKey);\n-\t\ts = p.getProperty(containerPath + \".subset\");\n-\t\tsubset = \"\".equals(s) ? null : s;\n \t}\n \n \t/**\n@@ -69,10 +66,8 @@ public class RepositoryMapping {\n \t *\n \t * @param mappedContainer\n \t * @param gitDir\n-\t * @param subsetRoot\n \t */\n-\tpublic RepositoryMapping(final IContainer mappedContainer,\n-\t\t\tfinal File gitDir, final String subsetRoot) {\n+\tpublic RepositoryMapping(final IContainer mappedContainer, final File gitDir) {\n \t\tfinal IPath cLoc = mappedContainer.getLocation()\n \t\t\t\t.removeTrailingSeparator();\n \t\tfinal IPath gLoc = Path.fromOSString(gitDir.getAbsolutePath())\n@@ -98,8 +93,6 @@ public class RepositoryMapping {\n \t\t} else {\n \t\t\tgitdirPath = gLoc.toPortableString();\n \t\t}\n-\n-\t\tsubset = \"\".equals(subsetRoot) ? null : subsetRoot;\n \t}\n \n \tIPath getContainerPath() {\n@@ -111,17 +104,6 @@ public class RepositoryMapping {\n \t}\n \n \t/**\n-\t * Eclipse projects typically reside one or more levels\n-\t * below the repository. This method return the relative\n-\t * path to the project. Null is returned instead of \"\".\n-\t *\n-\t * @return relative path from repository to project, or null\n-\t */\n-\tpublic String getSubset() {\n-\t\treturn subset;\n-\t}\n-\n-\t/**\n \t * @return the workdir file, i.e. where the files are checked out\n \t */\n \tpublic File getWorkDir() {\n@@ -130,6 +112,7 @@ public class RepositoryMapping {\n \n \tsynchronized void clear() {\n \t\tdb = null;\n+\t\tworkdirPrefix = null;\n \t\tcontainer = null;\n \t}\n \n@@ -142,6 +125,15 @@ public class RepositoryMapping {\n \n \tsynchronized void setRepository(final Repository r) {\n \t\tdb = r;\n+\n+\t\ttry {\n+\t\t\tworkdirPrefix = getWorkDir().getCanonicalPath();\n+\t\t} catch (IOException err) {\n+\t\t\tworkdirPrefix = getWorkDir().getAbsolutePath();\n+\t\t}\n+\t\tworkdirPrefix = workdirPrefix.replace('\\\\', '/');\n+\t\tif (!workdirPrefix.endsWith(\"/\"))\n+\t\t\tworkdirPrefix += \"/\";\n \t}\n \n \t/**\n@@ -166,9 +158,6 @@ public class RepositoryMapping {\n \n \tsynchronized void store(final Properties p) {\n \t\tp.setProperty(containerPath + \".gitdir\", gitdirPath);\n-\t\tif (subset != null && !\"\".equals(subset)) {\n-\t\t\tp.setProperty(containerPath + \".subset\", subset);\n-\t\t}\n \t}\n \n \tpublic String toString() {\n@@ -209,20 +198,20 @@ public class RepositoryMapping {\n \t * @param rsrc\n \t * @return the path relative to the Git repository, including base name.\n \t */\n-\tpublic String getRepoRelativePath(IResource rsrc) {\n-\t\tString prefix = getSubset();\n-\t\tString projectRelativePath = rsrc.getProjectRelativePath().toString();\n-\t\tString repoRelativePath;\n-\t\tif (prefix != null) {\n-\t\t\tif (projectRelativePath.length() == 0)\n-\t\t\t\trepoRelativePath = prefix;\n-\t\t\telse\n-\t\t\t\trepoRelativePath = prefix + \"/\" + projectRelativePath;\n-\t\t} else\n-\t\t\trepoRelativePath = projectRelativePath;\n-\n-\t\tassert repoRelativePath != null;\n-\t\treturn repoRelativePath;\n+\tpublic String getRepoRelativePath(final IResource rsrc) {\n+\t\t// We should only be called for resources that are actually\n+\t\t// in this repository, so we can safely assume that their\n+\t\t// path prefix matches workdirPrefix. Testing that here is\n+\t\t// rather expensive so we don't bother.\n+\t\t//\n+\t\tfinal int pfxLen = workdirPrefix.length();\n+\t\tfinal String p = rsrc.getLocation().toString();\n+\t\tfinal int pLen = p.length();\n+\t\tif (pLen > pfxLen)\n+\t\t\treturn p.substring(pfxLen);\n+\t\telse if (p.length() == pfxLen - 1)\n+\t\t\treturn \"\";\n+\t\treturn null;\n \t}\n \n \t/**\n-- \n1.6.0.rc1.250.g9b5e2\n"},{"id":"86312","messageId":"1217992180-5697-5-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":"1217992180-5697-4-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 4/5] Change GitProjectData.getRepositoryMapping to work on linked resources","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:39Z","receivedAt":"2008-08-06T03:09:39Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"When we are looking up the mapping for a file contained within a linked\ndirectory the linked directory may be mapped to a Git repository that is\nnot the same as the project itself, or the project doesn't even have a\nGit repository.\n\nThis may also be necessary for submodules.  For example a single project\nin Eclipse may actually contain several Git submodules below it and each\nmust have its own RepositoryMapping.\n\nWe now store the RepositoryMapping for a given IContainer directly on\nthat container using a session property.  This way Eclipse manages the\nhash lookups for us, and we can efficiently walk up the tree to locate\nthe nearest mapping for any resource.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/egit/core/project/GitProjectData.java  |   47 +++++++++++++-------\n 1 files changed, 31 insertions(+), 16 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\nindex 3d5424c..9998880 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/GitProjectData.java\n@@ -32,6 +32,7 @@ import org.eclipse.core.resources.IResourceChangeListener;\n import org.eclipse.core.resources.ResourcesPlugin;\n import org.eclipse.core.runtime.CoreException;\n import org.eclipse.core.runtime.Preferences;\n+import org.eclipse.core.runtime.QualifiedName;\n import org.eclipse.osgi.util.NLS;\n import org.eclipse.team.core.RepositoryProvider;\n import org.spearce.egit.core.Activator;\n@@ -71,6 +72,9 @@ public class GitProjectData {\n \t\t}\n \t}\n \n+\tprivate static QualifiedName MAPPING_KEY = new QualifiedName(\n+\t\t\tGitProjectData.class.getName(), \"RepositoryMapping\");\n+\n \t/**\n \t * Start listening for resource changes.\n \t *\n@@ -226,8 +230,6 @@ public class GitProjectData {\n \n \tprivate final Collection mappings;\n \n-\tprivate final Map c2mapping;\n-\n \tprivate final Set protectedResources;\n \n \t/**\n@@ -239,7 +241,6 @@ public class GitProjectData {\n \tpublic GitProjectData(final IProject p) {\n \t\tproject = p;\n \t\tmappings = new ArrayList();\n-\t\tc2mapping = new HashMap();\n \t\tprotectedResources = new HashSet();\n \t}\n \n@@ -267,15 +268,16 @@ public class GitProjectData {\n \t * @throws CoreException\n \t */\n \tpublic void markTeamPrivateResources() throws CoreException {\n-\t\tfinal Iterator i = c2mapping.entrySet().iterator();\n-\t\twhile (i.hasNext()) {\n-\t\t\tfinal Map.Entry e = (Map.Entry) i.next();\n-\t\t\tfinal IContainer c = (IContainer) e.getKey();\n+\t\tfor (final Object rmObj : mappings) {\n+\t\t\tfinal RepositoryMapping rm = (RepositoryMapping)rmObj;\n+\t\t\tfinal IContainer c = rm.getContainer();\n+\t\t\tif (c == null)\n+\t\t\t\tcontinue; // Not fully mapped yet?\n+\n \t\t\tfinal IResource dotGit = c.findMember(\".git\");\n \t\t\tif (dotGit != null) {\n \t\t\t\ttry {\n-\t\t\t\t\tfinal Repository r = ((RepositoryMapping) e.getValue())\n-\t\t\t\t\t\t\t.getRepository();\n+\t\t\t\t\tfinal Repository r = rm.getRepository();\n \t\t\t\t\tfinal File dotGitDir = dotGit.getLocation().toFile()\n \t\t\t\t\t\t\t.getCanonicalFile();\n \t\t\t\t\tif (dotGitDir.equals(r.getDirectory())) {\n@@ -298,14 +300,23 @@ public class GitProjectData {\n \t}\n \n \t/**\n-\t * TODO: check usage, we should probably declare the parameter\n-\t * as IProject.\n-\t *\n-\t * @param r Eclipse project\n+\t * @param r any workbench resource contained within this project.\n \t * @return the mapping for the specified project\n \t */\n-\tpublic RepositoryMapping getRepositoryMapping(final IResource r) {\n-\t\treturn (RepositoryMapping) c2mapping.get(r);\n+\tpublic RepositoryMapping getRepositoryMapping(IResource r) {\n+\t\ttry {\n+\t\t\twhile (r != null) {\n+\t\t\t\tfinal RepositoryMapping m;\n+\n+\t\t\t\tm = (RepositoryMapping) r.getSessionProperty(MAPPING_KEY);\n+\t\t\t\tif (m != null)\n+\t\t\t\t\treturn m;\n+ \t\t\t\tr = r.getParent();\n+\t\t\t}\n+\t\t} catch (CoreException err) {\n+\t\t\tActivator.logError(\"Falied finding RepositoryMapping\", err);\n+\t\t}\n+\t\treturn null;\n \t}\n \n \tprivate void delete() {\n@@ -445,7 +456,11 @@ public class GitProjectData {\n \t\tm.fireRepositoryChanged();\n \n \t\ttrace(\"map \" + c + \" -> \" + m.getRepository());\n-\t\tc2mapping.put(c, m);\n+\t\ttry {\n+\t\t\tc.setSessionProperty(MAPPING_KEY, m);\n+\t\t} catch (CoreException err) {\n+\t\t\tActivator.logError(\"Failed to cache RepositoryMapping\", err);\n+\t\t}\n \n \t\tdotGit = c.findMember(\".git\");\n \t\tif (dotGit != null && dotGit.getLocation().toFile().equals(git)) {\n-- \n1.6.0.rc1.250.g9b5e2\n"},{"id":"86313","messageId":"1217992180-5697-6-git-send-email-spearce@spearce.org","threadId":"14853","inReplyTo":"1217992180-5697-5-git-send-email-spearce@spearce.org","subject":"[EGIT PATCH 5/5] Correct getRepositoryMapping callers to use any IResource","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-08-06T03:09:40Z","receivedAt":"2008-08-06T03:09:40Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We really need to use the exact resource we want a mapping for, even\nif that is an IFile, because the file may be in a different repository\nthan the project it is contained in.  This can happen due to linked\nresources, or due to submodules.  Either way the mapping cannot be\ndriven by the project.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../org/spearce/egit/core/op/UntrackOperation.java |    4 +---\n .../egit/core/project/RepositoryMapping.java       |   14 +++++++-------\n .../egit/ui/internal/actions/CommitAction.java     |    2 +-\n 3 files changed, 9 insertions(+), 11 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java b/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java\nindex 369ff38..b491e6d 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java\n@@ -15,7 +15,6 @@ import java.util.IdentityHashMap;\n import java.util.Iterator;\n \n import org.eclipse.core.resources.IContainer;\n-import org.eclipse.core.resources.IProject;\n import org.eclipse.core.resources.IResource;\n import org.eclipse.core.resources.IResourceVisitor;\n import org.eclipse.core.resources.IWorkspaceRunnable;\n@@ -67,9 +66,8 @@ public class UntrackOperation implements IWorkspaceRunnable {\n \t\t\t\tobj = ((IAdaptable)obj).getAdapter(IResource.class);\n \t\t\t\tif (obj instanceof IResource) {\n \t\t\t\t\tfinal IResource toRemove = (IResource)obj;\n-\t\t\t\t\tfinal IProject p = toRemove.getProject();\t\t\t\t\t\n \t\t\t\t\tfinal GitProjectData pd = GitProjectData.get(toRemove.getProject());\n-\t\t\t\t\tfinal RepositoryMapping rm = pd.getRepositoryMapping(p);\n+\t\t\t\t\tfinal RepositoryMapping rm = pd.getRepositoryMapping(toRemove);\n \t\t\t\t\tfinal GitIndex index = rm.getRepository().getIndex();\n \t\t\t\t\ttomerge.put(rm, Boolean.TRUE);\n \t\t\t\t\tif (toRemove instanceof IContainer) {\ndiff --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\nindex 17e8142..961dbaf 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/project/RepositoryMapping.java\n@@ -221,15 +221,15 @@ public class RepositoryMapping {\n \t * @return the RepositoryMapping for this resource,\n \t *         or null for non GitProvider.\n \t */\n-\tpublic static RepositoryMapping getMapping(IResource resource) {\n-\t\tIProject project = resource.getProject();\n+\tpublic static RepositoryMapping getMapping(final IResource resource) {\n+\t\tfinal IProject project = resource.getProject();\n \t\tif (project == null)\n \t\t\treturn null;\n-\t\tRepositoryProvider provider = RepositoryProvider.getProvider(project);\n-\t\tif (!(provider instanceof GitProvider))\n+\n+\t\tfinal RepositoryProvider rp = RepositoryProvider.getProvider(project);\n+\t\tif (!(rp instanceof GitProvider))\n \t\t\treturn null;\n-\t\tGitProvider gp = (GitProvider)provider;\n-\t\tRepositoryMapping repositoryMapping = gp.getData().getRepositoryMapping(project);\n-\t\treturn repositoryMapping;\n+\n+\t\treturn ((GitProvider)rp).getData().getRepositoryMapping(resource);\n \t}\n }\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CommitAction.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CommitAction.java\nindex db38c10..4956be3 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CommitAction.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CommitAction.java\n@@ -363,7 +363,7 @@ public class CommitAction extends RepositoryAction {\n \n \t\ttry {\n \t\t\tRepositoryMapping repositoryMapping = projectData\n-\t\t\t\t\t.getRepositoryMapping(resource.getProject());\n+\t\t\t\t\t.getRepositoryMapping(resource);\n \n \t\t\tif (isChanged(repositoryMapping, resource)) {\n \t\t\t\tfiles.add(resource);\n-- \n1.6.0.rc1.250.g9b5e2\n"}]}