diff options
3 files changed, 117 insertions, 18 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitProjectSetCapabilityTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitProjectSetCapabilityTest.java index 78457c0d2f..0ade99bf6b 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitProjectSetCapabilityTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitProjectSetCapabilityTest.java @@ -11,6 +11,7 @@ package org.eclipse.egit.core.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.File; import java.util.ArrayList; @@ -34,6 +35,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.util.FileUtils; import org.eclipse.team.core.ProjectSetSerializationContext; +import org.eclipse.team.core.TeamException; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -191,6 +193,50 @@ public class GitProjectSetCapabilityTest { assertEquals("stable", xbMapping.getRepository().getBranch()); } + @Test + public void testImportWithMultipleCallsForSameDestinationRepo() throws Exception { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IPath reposPath = root.getLocation().append("repos"); + pathsToClean.add(reposPath.toFile()); + + IPath xPath = reposPath.append("x"); + IProject xaProject = createProject(xPath, "xa"); + IProject xbProject = createProject(xPath, "xb"); + String url = createUrl(xPath); + createRepository(xPath, url, "stable"); + xaProject.delete(false, true, null); + xbProject.delete(false, true, null); + + String xaReference = createProjectReference(xPath, "master", "xa"); + String xbReference = createProjectReference(xPath, "master", "xb"); + + // This should work because there is not yet a repo at the destination + capability.addToWorkspace(new String[] { xaReference }, + new ProjectSetSerializationContext(), + new NullProgressMonitor()); + + // This should work because the repo that is already there is for the + // same remote URL. It's assumed to be ok and will skip cloning and + // directly import the project. + capability.addToWorkspace(new String[] { xbReference }, + new ProjectSetSerializationContext(), + new NullProgressMonitor()); + + pathsToClean.add(root.getLocation().append("x").toFile()); + + IPath otherPathWithX = reposPath.append("other").append("x"); + String otherReferenceWithDifferentUrl = createProjectReference(otherPathWithX, "master", "xb"); + + try { + capability.addToWorkspace(new String[] { otherReferenceWithDifferentUrl }, + new ProjectSetSerializationContext(), + new NullProgressMonitor()); + fail("Should throw TeamException when a repo exists at the place but doesn't have the same URL."); + } catch (TeamException e) { + // This is expected + } + } + private IProject createProject(String name) throws CoreException { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IProject p = root.getProject(name); @@ -237,4 +283,12 @@ public class GitProjectSetCapabilityTest { project.getProject(), gitDir); operation.execute(null); } + + private static String createProjectReference(IPath repoPath, String branch, String projectPath) { + return "1.0," + createUrl(repoPath) + "," + branch + "," + projectPath; + } + + private static String createUrl(IPath repoPath) { + return repoPath.toFile().toURI().toString(); + } } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties index 7599c69251..b06b5ee41e 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties @@ -80,7 +80,7 @@ The resource cannot be moved, renamed or deleted due to an internal error. Error_CanonicalFile=Unable to determine a canonical file path. ProjectReference_InvalidTokensCount={0} tokens expected in project reference but {1} had been found: {2} -GitProjectSetCapability_CloneToExistingDirectory=Destination directory {0} exists. Don''t clone {1} from {2} to prevent data loss. +GitProjectSetCapability_CloneToExistingDirectory=Destination directory {0} already exists and doesn't contain the expected Git repository. Won''t clone {1} from {2} to prevent data loss. GitProjectSetCapability_ExportCouldNotGetBranch=Could not get current branch from repository of project {0}. GitProjectSetCapability_ExportNoRemote=No remote URL configured for current branch in repository of project {0}. diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/ProjectReferenceImporter.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/ProjectReferenceImporter.java index a55778a6a9..b030c74bc3 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/ProjectReferenceImporter.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/ProjectReferenceImporter.java @@ -9,6 +9,7 @@ package org.eclipse.egit.core.internal; import java.io.File; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.ArrayList; @@ -35,7 +36,10 @@ import org.eclipse.egit.core.CoreText; import org.eclipse.egit.core.ProjectReference; import org.eclipse.egit.core.op.CloneOperation; import org.eclipse.egit.core.op.ConnectProviderOperation; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.transport.URIish; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.TeamException; @@ -80,27 +84,35 @@ public class ProjectReferenceImporter { final IPath workDir = getWorkingDir(gitUrl, branch, branches.keySet()); + final File repositoryPath = workDir.append( + Constants.DOT_GIT_EXT).toFile(); + + boolean shouldClone = true; + if (workDir.toFile().exists()) { - final Collection<String> projectNames = new LinkedList<String>(); - for (final ProjectReference projectReference : projects) - projectNames.add(projectReference.getProjectDir()); - throw new TeamException( - NLS.bind( - CoreText.GitProjectSetCapability_CloneToExistingDirectory, - new Object[] { workDir, projectNames, - gitUrl })); + if (repositoryAlreadyExistsForUrl(repositoryPath, gitUrl)) + shouldClone = false; + else { + final Collection<String> projectNames = new LinkedList<String>(); + for (final ProjectReference projectReference : projects) + projectNames.add(projectReference.getProjectDir()); + throw new TeamException( + NLS.bind( + CoreText.GitProjectSetCapability_CloneToExistingDirectory, + new Object[] { workDir, projectNames, + gitUrl })); + } } try { - int timeout = 60; - String refName = Constants.R_HEADS + branch; - final CloneOperation cloneOperation = new CloneOperation( - gitUrl, true, null, workDir.toFile(), refName, - Constants.DEFAULT_REMOTE_NAME, timeout); - cloneOperation.run(monitor); - - final File repositoryPath = workDir.append( - Constants.DOT_GIT_EXT).toFile(); + if (shouldClone) { + int timeout = 60; + String refName = Constants.R_HEADS + branch; + final CloneOperation cloneOperation = new CloneOperation( + gitUrl, true, null, workDir.toFile(), refName, + Constants.DEFAULT_REMOTE_NAME, timeout); + cloneOperation.run(monitor); + } Activator.getDefault().getRepositoryUtil() .addConfiguredRepository(repositoryPath); @@ -176,6 +188,39 @@ public class ProjectReferenceImporter { return workDir; } + private static boolean repositoryAlreadyExistsForUrl(File repositoryPath, + URIish gitUrl) { + if (repositoryPath.exists()) { + try { + FileRepository existingRepository = new FileRepository( + repositoryPath); + boolean exists = containsRemoteForUrl( + existingRepository.getConfig(), gitUrl); + existingRepository.close(); + return exists; + } catch (IOException e) { + return false; + } catch (URISyntaxException e) { + return false; + } + } + return false; + } + + private static boolean containsRemoteForUrl(Config config, URIish url) throws URISyntaxException { + Set<String> remotes = config.getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION); + for (String remote : remotes) { + String remoteUrl = config.getString( + ConfigConstants.CONFIG_REMOTE_SECTION, + remote, + ConfigConstants.CONFIG_KEY_URL); + URIish existingUrl = new URIish(remoteUrl); + if (existingUrl.equals(url)) + return true; + } + return false; + } + private List<IProject> importProjects(final Set<ProjectReference> projects, final IPath workDir, final File repositoryPath, final IProgressMonitor monitor) throws TeamException { |