diff options
author | Christian Halstrick | 2014-10-21 08:55:36 +0000 |
---|---|---|
committer | Matthias Sohn | 2015-02-02 19:15:54 +0000 |
commit | fd9695bf5cbca704bab51ff27b8716dbb0f5b729 (patch) | |
tree | 6a93486968c454608239df0c8b53b27eaa735a41 | |
parent | 7d00a85840fd35ba98a66a373f0fb915991ea962 (diff) | |
download | egit-fd9695bf5cbca704bab51ff27b8716dbb0f5b729.tar.gz egit-fd9695bf5cbca704bab51ff27b8716dbb0f5b729.tar.xz egit-fd9695bf5cbca704bab51ff27b8716dbb0f5b729.zip |
Let staging view use submodule repos
If the staging view is linked to the selected resource and if that
resource belongs to a submodule then staging view should also run in
the context of the submodule repo. This allows to work with submodules
in a similar manner than with native git. If I want to do a commit in a
submodule repo then select a resource in that submodule repo and you can
use Staging view to prepare the commit in the submodule repo. In native
git you would "cd" to a folder containing a file from the submodule to
switch context from the containing repo to the submodule repo. In EGit
you have to select a resource from the submodule to achieve the same.
RepositoryMapping is enhanced by one method which can return a submodule
repository. In future RepositoryMapping could be further enhanced to
support git submodules in general.
Bug: 382093
Bug: 446344
Change-Id: Ie61c597c87a68da16a92cd52fea0bc5a4ff5ec28
Also-By: Stefan Lay <stefan.lay@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
4 files changed, 88 insertions, 6 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/CoreText.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/CoreText.java index 3b3885614b..e92b70be61 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/CoreText.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/CoreText.java @@ -178,6 +178,9 @@ public class CoreText extends NLS { public static String RepositoryFinder_finding; /** */ + public static String RepositoryMapping_ExceptionSubmoduleWalk; + + /** */ public static String RepositoryUtil_DirectoryIsNotGitDirectory; /** */ diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/coretext.properties index 3a480e05fa..003a867d02 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/coretext.properties +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/coretext.properties @@ -67,6 +67,7 @@ GitProjectData_saveFailed=Saving Git team provider data to {0} failed. RebaseInteractivePlan_WriteRebaseTodoFailed=Error writing Rebase-Todo-File RepositoryFinder_finding=Searching for associated repositories. +RepositoryMapping_ExceptionSubmoduleWalk=Caught exception while walking submodules RepositoryUtil_DirectoryIsNotGitDirectory=Repository directory to configure does not look like a Git directory: {0} RepositoryUtil_noHead=NO-HEAD ResetOperation_performingReset=Performing {0} reset to {1} diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java index 4e4a278da3..dbafbe1b1f 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java @@ -27,8 +27,12 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.GitProvider; +import org.eclipse.egit.core.RepositoryCache; +import org.eclipse.egit.core.internal.CoreText; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.team.core.RepositoryProvider; /** @@ -55,6 +59,9 @@ public class RepositoryMapping { private IContainer container; + private final RepositoryCache repositoryCache = org.eclipse.egit.core.Activator + .getDefault().getRepositoryCache(); + /** * Construct a {@link RepositoryMapping} for a previously connected project. * @@ -143,6 +150,49 @@ public class RepositoryMapping { return db; } + /** + * @param res + * a resource + * @return the submodule repository if the resource is contained in a git + * submodule otherwise return {@code null}. The returned repository + * instance will always be taken from the {@link RepositoryCache} + * and the caller should not call close() on it. + * + * TODO add support for multiple nesting levels of submodules + */ + public synchronized Repository getSubmoduleRepository(IResource res) { + IPath projectRelativePath = res.getProjectRelativePath(); + if (projectRelativePath == null) + return null; + + String projectRelativePathStr = res.getProjectRelativePath().toString(); + try { + if (SubmoduleWalk.containsGitModulesFile(db)) { + SubmoduleWalk sw = SubmoduleWalk.forIndex(db); + while (sw.next()) { + if (projectRelativePathStr.startsWith(sw.getPath())) { + Repository subRepo = sw.getRepository(); + if (subRepo == null) + return null; + + Repository cachedRepo = null; + try { + cachedRepo = repositoryCache + .lookupRepository(subRepo.getDirectory()); + } finally { + subRepo.close(); + } + return cachedRepo; + } + } + } + } catch (IOException e) { + Activator.logWarning( + CoreText.RepositoryMapping_ExceptionSubmoduleWalk, e); + } + return db; + } + synchronized void setRepository(final Repository r) { db = r; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java index 8cefb091ac..b6489dcb42 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java @@ -11,6 +11,7 @@ package org.eclipse.egit.ui.internal.staging; import static org.eclipse.egit.ui.internal.CommonUtils.runCommand; import java.io.File; +import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; @@ -32,6 +33,7 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; @@ -93,6 +95,8 @@ import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; import org.eclipse.jface.preference.IPersistentPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; @@ -1873,12 +1877,34 @@ public class StagingView extends ViewPart implements IShowInSource { } private void showResource(final IResource resource) { - IProject project = resource.getProject(); - RepositoryMapping mapping = RepositoryMapping.getMapping(project); - if (mapping == null) - return; - if (mapping.getRepository() != currentRepository) - reload(mapping.getRepository()); + Repository newRep = getRepositoryOrNestedSubmoduleRepository(resource); + if (newRep != null && newRep != currentRepository) + reload(newRep); + } + + private Repository getRepositoryOrNestedSubmoduleRepository( + final IResource resource) { + final Repository[] repo = new Repository[1]; + try { + ModalContext.run(new IRunnableWithProgress() { + + public void run(IProgressMonitor monitor) { + IProject project = resource.getProject(); + RepositoryMapping mapping = RepositoryMapping + .getMapping(project); + if (mapping == null) + return; + repo[0] = mapping.getSubmoduleRepository(resource); + if (repo[0] == null) + repo[0] = mapping.getRepository(); + } + }, true, new NullProgressMonitor(), Display.getDefault()); + } catch (InvocationTargetException e) { + // ignore + } catch (InterruptedException e) { + // ignore + } + return repo[0]; } private void stage(IStructuredSelection selection) { @@ -1906,6 +1932,8 @@ public class StagingView extends ViewPart implements IShowInSource { IResource resource = AdapterUtils.adapt(element, IResource.class); if (resource != null) { RepositoryMapping mapping = RepositoryMapping.getMapping(resource); + // doesn't do anything if the current repository is a + // submodule of the mapped repo if (mapping != null && mapping.getRepository() == currentRepository) { String path = mapping.getRepoRelativePath(resource); // If resource corresponds to root of working directory |