diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/DataTransferMessages.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/DataTransferMessages.java index f79651548fe6..f564865c0997 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/DataTransferMessages.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/DataTransferMessages.java @@ -109,6 +109,7 @@ public class DataTransferMessages extends NLS { public static String WizardProjectsImportPage_projectLabel; public static String WizardProjectsImportPage_hideExistingProjects; public static String WizardProjectsImportPage_closeProjectsAfterImport; + public static String WizardProjectsImportPage_skipDotFolders; public static String WizardProjectsImportPage_invalidProjectName; // --- Export Wizards --- @@ -186,6 +187,7 @@ public class DataTransferMessages extends NLS { public static String SmartImportWizardPage_selectAtLeastOneFolderToOpenAsProject; public static String SmartImportWizardPage_showOtherSpecializedImportWizard; public static String SmartImportWizardPage_closeProjectsAfterImport; + public static String SmartImportWizardPage_skipDotFolders; public static String SmartImportJob_discardRootProject_title; public static String SmartImportJob_discardRootProject_description; diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/EclipseProjectConfigurator.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/EclipseProjectConfigurator.java index 166a5ff6e535..77b242f06c7d 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/EclipseProjectConfigurator.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/EclipseProjectConfigurator.java @@ -44,7 +44,7 @@ public Set findConfigurableLocations(File root, IProgressMonitor monitor) Set projectFiles = new LinkedHashSet<>(); Set visitedDirectories = new HashSet<>(); WizardProjectsImportPage.collectProjectFilesFromDirectory(projectFiles, root, visitedDirectories, true, - monitor); + false, monitor); Set res = new LinkedHashSet<>(); for (File projectFile : projectFiles) { res.add(projectFile.getParentFile()); diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportJob.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportJob.java index 8fd1ba72da3a..c7bf30593484 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportJob.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportJob.java @@ -74,6 +74,7 @@ public class SmartImportJob extends Job { private boolean deepChildrenDetection; private final boolean configureProjects; private boolean closeProjectsAfterImport; + private boolean skipDotFolders = true; private boolean reconfigureEclipseProjects; private IWorkingSet[] workingSets; @@ -347,6 +348,9 @@ private Set searchAndImportChildrenProjectsRecursively(final IContaine final Set res = Collections.synchronizedSet(new HashSet<>()); for (IResource childResource : parentContainer.members()) { if (childResource.getType() == IResource.FOLDER && !childResource.isDerived()) { + if (skipDotFolders && childResource.getName().startsWith(".")) { //$NON-NLS-1$ + continue; + } IPath location = childResource.getLocation(); if (location == null) { continue; @@ -530,6 +534,18 @@ private Set toPathSet(Set resources) { return res; } + private static boolean isInsideDotFolder(File file) { + File current = file; + while (current != null) { + String name = current.getName(); + if (!name.isEmpty() && name.startsWith(".")) { //$NON-NLS-1$ + return true; + } + current = current.getParentFile(); + } + return false; + } + /** * @param refreshMode One {@link IResource#BACKGROUND_REFRESH} for background refresh, or {@link IResource#NONE} for immediate refresh */ @@ -684,6 +700,9 @@ public Map> getImportProposals(IProgressMonitor for (ProjectConfigurator configurator : activeConfigurators) { configurator.removeDirtyDirectories(res); } + if (this.skipDotFolders) { + res.keySet().removeIf(SmartImportJob::isInsideDotFolder); + } this.importProposals = res; } return this.importProposals; @@ -723,6 +742,22 @@ void setCloseProjectsAfterImport(boolean closeProjectsAfterImport) { this.closeProjectsAfterImport = closeProjectsAfterImport; } + /** + * @param skipDotFolders + * if true, folders starting with '.' (e.g. .git) are skipped + * during project scanning + */ + void setSkipDotFolders(boolean skipDotFolders) { + this.skipDotFolders = skipDotFolders; + } + + /** + * @return whether folders starting with '.' are skipped during scanning + */ + public boolean isSkipDotFolders() { + return this.skipDotFolders; + } + /** * Forget the initial import proposals. */ diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportRootWizardPage.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportRootWizardPage.java index 40c27c58696c..9b1f62694020 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportRootWizardPage.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportRootWizardPage.java @@ -120,6 +120,8 @@ public class SmartImportRootWizardPage extends WizardPage { private static final String STORE_CONFIGURE_NATURES = "SmartImportRootWizardPage.STORE_CONFIGURE_NATURES"; //$NON-NLS-1$ + private static final String STORE_SKIP_DOT_FOLDERS = "SmartImportRootWizardPage.STORE_SKIP_DOT_FOLDERS"; //$NON-NLS-1$ + // Root private File selection; private Combo rootDirectoryText; @@ -135,6 +137,7 @@ public class SmartImportRootWizardPage extends WizardPage { private boolean closeProjectsAfterImport = false; private boolean detectNestedProjects = true; private boolean configureProjects = true; + private boolean skipDotFolders = true; // Working sets private Set workingSets; private WorkingSetGroup workingSetsGroup; @@ -475,6 +478,19 @@ public void widgetSelected(SelectionEvent e) { * Creates the UI elements for the import options */ private void createConfigurationOptions(Composite parent) { + GridData layoutData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1); + final Button skipDotFoldersCheckbox = new Button(parent, SWT.CHECK); + skipDotFoldersCheckbox.setText(DataTransferMessages.SmartImportWizardPage_skipDotFolders); + skipDotFoldersCheckbox.setLayoutData(layoutData); + skipDotFoldersCheckbox.setSelection(this.skipDotFolders); + skipDotFoldersCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + SmartImportRootWizardPage.this.skipDotFolders = skipDotFoldersCheckbox.getSelection(); + refreshProposals(); + } + }); + Button closeProjectsCheckbox = new Button(parent, SWT.CHECK); closeProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_closeProjectsAfterImport); closeProjectsCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1)); @@ -508,10 +524,9 @@ public void widgetSelected(SelectionEvent e) { DataTransferMessages.SmartImportWizardPage_availableDetectors_title, message.toString()); } }); - GridData layoutData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1); final Button detectNestedProjectsCheckbox = new Button(parent, SWT.CHECK); detectNestedProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_detectNestedProjects); - detectNestedProjectsCheckbox.setLayoutData(layoutData); + detectNestedProjectsCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1)); detectNestedProjectsCheckbox.setSelection(this.detectNestedProjects); detectNestedProjectsCheckbox.addSelectionListener(new SelectionAdapter() { @Override @@ -523,7 +538,7 @@ public void widgetSelected(SelectionEvent e) { final Button configureProjectsCheckbox = new Button(parent, SWT.CHECK); configureProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_configureProjects); - configureProjectsCheckbox.setLayoutData(layoutData); + configureProjectsCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1)); configureProjectsCheckbox.setSelection(this.configureProjects); configureProjectsCheckbox.addSelectionListener(new SelectionAdapter() { @Override @@ -825,6 +840,13 @@ boolean isCloseProjectsAfterImport() { return closeProjectsAfterImport; } + /** + * @return whether folders starting with '.' should be skipped during scanning + */ + boolean isSkipDotFolders() { + return skipDotFolders; + } + private void refreshProposals() { stopAndDisconnectCurrentWork(); this.potentialProjects = Collections.emptyMap(); @@ -956,6 +978,9 @@ private void loadWidgetStates() { closeProjectsAfterImport = dialogSettings.getBoolean(STORE_CLOSE_IMPORTED); detectNestedProjects = dialogSettings.getBoolean(STORE_NESTED_PROJECTS); configureProjects = dialogSettings.getBoolean(STORE_CONFIGURE_NATURES); + if (dialogSettings.get(STORE_SKIP_DOT_FOLDERS) != null) { + skipDotFolders = dialogSettings.getBoolean(STORE_SKIP_DOT_FOLDERS); + } } } @@ -969,6 +994,7 @@ private void saveWidgetStates() { dialogSettings.put(STORE_CLOSE_IMPORTED, closeProjectsAfterImport); dialogSettings.put(STORE_NESTED_PROJECTS, detectNestedProjects); dialogSettings.put(STORE_CONFIGURE_NATURES, configureProjects); + dialogSettings.put(STORE_SKIP_DOT_FOLDERS, skipDotFolders); } } diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportWizard.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportWizard.java index aed6fca7d5f5..64f338ab7332 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportWizard.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/SmartImportWizard.java @@ -288,6 +288,7 @@ public SmartImportJob createOrGetConfiguredImportJob() { // WS change automatically this.easymportJob.setWorkingSets(projectRootPage.getSelectedWorkingSets()); this.easymportJob.setCloseProjectsAfterImport(projectRootPage.isCloseProjectsAfterImport()); + this.easymportJob.setSkipDotFolders(projectRootPage.isSkipDotFolders()); return this.easymportJob; } @@ -337,7 +338,8 @@ private static boolean matchesPage(SmartImportJob job, SmartImportRootWizardPage boolean sameSource = jobRoot.equals(pageRoot) || (isValidArchive(pageRoot) && getExpandDirectory(pageRoot).getAbsoluteFile().equals(jobRoot)); return sameSource && job.isDetectNestedProjects() == page.isDetectNestedProject() - && job.isConfigureProjects() == page.isConfigureProjects(); + && job.isConfigureProjects() == page.isConfigureProjects() + && job.isSkipDotFolders() == page.isSkipDotFolders(); } } \ No newline at end of file diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardProjectsImportPage.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardProjectsImportPage.java index 46f7570b782f..647902da70df 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardProjectsImportPage.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardProjectsImportPage.java @@ -321,6 +321,8 @@ public boolean select(Viewer viewer, Object parentElement, private static final String STORE_ARCHIVE_SELECTED = "WizardProjectsImportPage.STORE_ARCHIVE_SELECTED"; //$NON-NLS-1$ + private static final String STORE_SKIP_DOT_FOLDERS = "WizardProjectsImportPage.STORE_SKIP_DOT_FOLDERS"; //$NON-NLS-1$ + private Combo directoryPathField; private CheckboxTreeViewer projectsList; @@ -341,6 +343,10 @@ public boolean select(Viewer viewer, Object parentElement, private boolean hideConflictingProjects = false; + private Button skipDotFoldersCheckbox; + + private boolean skipDotFolders = true; + private ProjectRecord[] selectedProjects = new ProjectRecord[0]; // Keep track of the directory that we browsed to last time @@ -505,6 +511,22 @@ public void widgetSelected(SelectionEvent e) { } })); Dialog.applyDialogFont(hideConflictingProjectsCheckbox); + + skipDotFoldersCheckbox = new Button(optionsGroup, SWT.CHECK); + skipDotFoldersCheckbox.setText(DataTransferMessages.WizardProjectsImportPage_skipDotFolders); + skipDotFoldersCheckbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + skipDotFoldersCheckbox.setSelection(skipDotFolders); + skipDotFoldersCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + skipDotFolders = skipDotFoldersCheckbox.getSelection(); + if (projectFromDirectoryRadio.getSelection()) { + updateProjectsListAndPreventFocusLostHandling(directoryPathField.getText().trim(), true); + } else { + updateProjectsListAndPreventFocusLostHandling(archivePathField.getText().trim(), true); + } + } + }); } /** @@ -940,7 +962,7 @@ else if (dirSelected && directory.isDirectory()) { Collection files = new ArrayList<>(); if (!collectProjectFilesFromDirectory(files, directory, - null, nestedProjects, monitor)) { + null, nestedProjects, skipDotFolders, monitor)) { return; } Iterator filesIterator3 = files.iterator(); @@ -1064,12 +1086,14 @@ private TarFile getSpecifiedTarSourceFile(String fileName) { * Set of canonical paths of directories, used as recursion guard * @param nestedProjects * whether to look for nested projects + * @param skipDotFolders + * whether to skip folders starting with '.' (e.g. .git) * @param monitor * The monitor to report to * @return boolean true if the operation was completed. */ static boolean collectProjectFilesFromDirectory(Collection files, File directory, - Set directoriesVisited, boolean nestedProjects, IProgressMonitor monitor) { + Set directoriesVisited, boolean nestedProjects, boolean skipDotFolders, IProgressMonitor monitor) { if (monitor.isCanceled()) { return false; @@ -1110,20 +1134,24 @@ static boolean collectProjectFilesFromDirectory(Collection files, File dir // no project description found or search for nested projects enabled, // so recurse into sub-directories for (File dir : directories) { - if (!dir.getName().equals(METADATA_FOLDER)) { - try { - String canonicalPath = dir.getCanonicalPath(); - if (!directoriesVisited.add(canonicalPath)) { - // already been here --> do not recurse - continue; - } - } catch (IOException exception) { - StatusManager.getManager().handle(StatusUtil.newError(exception)); - + if (dir.getName().equals(METADATA_FOLDER)) { + continue; + } + if (skipDotFolders && dir.getName().startsWith(".")) { //$NON-NLS-1$ + continue; + } + try { + String canonicalPath = dir.getCanonicalPath(); + if (!directoriesVisited.add(canonicalPath)) { + // already been here --> do not recurse + continue; } - collectProjectFilesFromDirectory(files, dir, - directoriesVisited, nestedProjects, monitor); + } catch (IOException exception) { + StatusManager.getManager().handle(StatusUtil.newError(exception)); + } + collectProjectFilesFromDirectory(files, dir, + directoriesVisited, nestedProjects, skipDotFolders, monitor); } return true; } @@ -1565,6 +1593,12 @@ public void restoreWidgetValues() { // trigger a selection event for the button to make sure the filter is set // properly at page creation hideConflictingProjectsCheckbox.notifyListeners(SWT.Selection, new Event()); + + // checkbox + if (settings.get(STORE_SKIP_DOT_FOLDERS) != null) { + skipDotFolders = settings.getBoolean(STORE_SKIP_DOT_FOLDERS); + } + skipDotFoldersCheckbox.setSelection(skipDotFolders); } // Second, check to see if we don't have an initial path, @@ -1644,6 +1678,8 @@ public void saveWidgetValues() { settings.put(STORE_CLOSE_CREATED_PROJECTS_ID, closeProjectsCheckbox.getSelection()); settings.put(STORE_HIDE_CONFLICTING_PROJECTS_ID, hideConflictingProjectsCheckbox.getSelection()); + + settings.put(STORE_SKIP_DOT_FOLDERS, skipDotFoldersCheckbox.getSelection()); } } @@ -1674,6 +1710,15 @@ public Button getNestedProjectsCheckbox() { return nestedProjectsCheckbox; } + /** + * Method used for test suite. + * + * @return Button skip dot folders checkbox + */ + public Button getSkipDotFoldersCheckbox() { + return skipDotFoldersCheckbox; + } + @Override public void handleEvent(Event event) { } diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/messages.properties b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/messages.properties index 1eeaeb3f3b3c..9c55a28d3cd4 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/messages.properties +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/messages.properties @@ -112,6 +112,7 @@ WizardProjectsImportPage_invalidProjectName=Invalid Project WizardProjectsImportPage_projectLabel={0} ({1}) WizardProjectsImportPage_hideExistingProjects=H&ide projects that already exist in the workspace WizardProjectsImportPage_closeProjectsAfterImport=Cl&ose newly imported projects upon completion +WizardProjectsImportPage_skipDotFolders=S&kip folders starting with '.' (e.g. .git) # --- Export Wizards --- DataTransfer_export = Export @@ -213,4 +214,5 @@ SmartImportWizardPage_incompleteExpand_title=Incomplete expansion SmartImportWizardPage_incompleteExpand_message=Archive expansion didn''t complete successfully. It''s recommend that you clean directory {0} and try importing again. SmartImportWizardPage_selectAtLeastOneFolderToOpenAsProject=Select at least one folder to import as project. SmartImportWizardPage_showOtherSpecializedImportWizard=Show other specialized import wizards -SmartImportWizardPage_closeProjectsAfterImport=Cl&ose newly imported projects upon completion \ No newline at end of file +SmartImportWizardPage_closeProjectsAfterImport=Cl&ose newly imported projects upon completion +SmartImportWizardPage_skipDotFolders=S&kip folders starting with '.' (e.g. .git) \ No newline at end of file diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/ImportExistingProjectsWizardTest.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/ImportExistingProjectsWizardTest.java index dc573e1f4179..67b9e90b0330 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/ImportExistingProjectsWizardTest.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/ImportExistingProjectsWizardTest.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URL; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -53,6 +54,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.dialogs.ImportExportWizard; @@ -1221,4 +1223,78 @@ public void test23DoNotShowProjectwithSameNameForZipImport() throws CoreExceptio } } + @Test + public void test24CollectProjectFilesSkipsDotFoldersWhenEnabled() throws IOException { + File tempDir = Files.createTempDirectory("skipDotFolderTest").toFile(); + try { + // Create a normal project + File normalProject = new File(tempDir, "normalProject"); + normalProject.mkdirs(); + Files.writeString(new File(normalProject, ".project").toPath(), + "normalProject"); + + // Create a project inside a .git folder + File dotGitFolder = new File(tempDir, ".git"); + File hiddenProject = new File(dotGitFolder, "modules/hiddenProject"); + hiddenProject.mkdirs(); + Files.writeString(new File(hiddenProject, ".project").toPath(), + "hiddenProject"); + + // With skipDotFolders=true (default), only normalProject should be found + WizardProjectsImportPage wpip = getNewWizard(); + wpip.getProjectFromDirectoryRadio().setSelection(true); + wpip.getNestedProjectsCheckbox().setSelection(true); + // skipDotFolders defaults to true + wpip.updateProjectsList(tempDir.getAbsolutePath()); + + ProjectRecord[] selectedProjects = wpip.getProjectRecords(); + ArrayList projectNames = new ArrayList<>(); + for (ProjectRecord record : selectedProjects) { + projectNames.add(record.getProjectName()); + } + assertTrue("normalProject should be found", projectNames.contains("normalProject")); + assertFalse("hiddenProject inside .git should be skipped", projectNames.contains("hiddenProject")); + } finally { + FileSystemHelper.clear(tempDir); + } + } + + @Test + public void test25CollectProjectFilesFindsProjectsInDotFoldersWhenDisabled() throws IOException { + File tempDir = Files.createTempDirectory("noSkipDotFolderTest").toFile(); + try { + // Create a normal project + File normalProject = new File(tempDir, "normalProject"); + normalProject.mkdirs(); + Files.writeString(new File(normalProject, ".project").toPath(), + "normalProject"); + + // Create a project inside a .git folder + File dotGitFolder = new File(tempDir, ".git"); + File hiddenProject = new File(dotGitFolder, "hiddenProject"); + hiddenProject.mkdirs(); + Files.writeString(new File(hiddenProject, ".project").toPath(), + "hiddenProject"); + + // With skipDotFolders=false, both projects should be found + WizardProjectsImportPage wpip = getNewWizard(); + wpip.getProjectFromDirectoryRadio().setSelection(true); + wpip.getNestedProjectsCheckbox().setSelection(true); + wpip.getSkipDotFoldersCheckbox().setSelection(false); + wpip.getSkipDotFoldersCheckbox().notifyListeners(SWT.Selection, new Event()); + wpip.updateProjectsList(tempDir.getAbsolutePath()); + + ProjectRecord[] selectedProjects = wpip.getProjectRecords(); + ArrayList projectNames = new ArrayList<>(); + for (ProjectRecord record : selectedProjects) { + projectNames.add(record.getProjectName()); + } + assertTrue("normalProject should be found", projectNames.contains("normalProject")); + assertTrue("hiddenProject inside .git should be found when skip is disabled", + projectNames.contains("hiddenProject")); + } finally { + FileSystemHelper.clear(tempDir); + } + } + } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/SmartImportTests.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/SmartImportTests.java index 7f013fc26188..f2ccbfe1d088 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/SmartImportTests.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/datatransfer/SmartImportTests.java @@ -35,6 +35,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -71,6 +72,7 @@ import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.dialogs.FilteredTree; import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.internal.wizards.datatransfer.SmartImportJob; import org.eclipse.ui.internal.wizards.datatransfer.SmartImportRootWizardPage; import org.eclipse.ui.internal.wizards.datatransfer.SmartImportWizard; import org.eclipse.ui.tests.TestPlugin; @@ -513,4 +515,63 @@ private static Combo getComboWithSelection(String selection, Composite parent) { } return null; } + + @Test + public void testSmartImportSkipsDotFolders() throws Exception { + // Create a temp directory with a project inside a .git folder + java.nio.file.Path tempDir = Files.createTempDirectory("smartImportSkipDotTest"); + try { + // Create a normal project with ImportMe marker file + File normalProject = new File(tempDir.toFile(), "normalProject"); + normalProject.mkdirs(); + new File(normalProject, "importme").createNewFile(); + + // Create a project inside a .git folder (should be skipped) + File dotGitFolder = new File(tempDir.toFile(), ".git"); + File hiddenProject = new File(dotGitFolder, "hiddenProject"); + hiddenProject.mkdirs(); + new File(hiddenProject, "importme").createNewFile(); + + SmartImportWizard wizard = new SmartImportWizard(); + wizard.setInitialImportSource(tempDir.toFile()); + proceedSmartImportWizard(wizard); + + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + for (IProject project : projects) { + assertFalse("Project inside .git folder should not be imported", + project.getLocation().toFile().getAbsolutePath().contains(".git")); + } + } finally { + org.eclipse.core.tests.harness.FileSystemHelper.clear(tempDir.toFile()); + } + } + + @Test + public void testSmartImportJobSkipsDotFoldersInProposals() throws Exception { + java.nio.file.Path tempDir = Files.createTempDirectory("smartImportProposalTest"); + try { + // Create a normal Eclipse project + File normalProject = new File(tempDir.toFile(), "normalProject"); + normalProject.mkdirs(); + Files.writeString(new File(normalProject, ".project").toPath(), + "normalProject"); + + // Create an Eclipse project inside a .git folder + File dotGitFolder = new File(tempDir.toFile(), ".git"); + File hiddenProject = new File(dotGitFolder, "modules/hiddenProject"); + hiddenProject.mkdirs(); + Files.writeString(new File(hiddenProject, ".project").toPath(), + "hiddenProject"); + + // Default skipDotFolders=true: .git projects should be filtered out + SmartImportJob jobSkip = new SmartImportJob(tempDir.toFile(), Collections.emptySet(), true, true); + Map proposalsSkip = jobSkip.getImportProposals(new NullProgressMonitor()); + for (File proposed : proposalsSkip.keySet()) { + assertFalse("Proposal inside .git folder should be filtered out by default", + proposed.getAbsolutePath().contains(".git")); + } + } finally { + org.eclipse.core.tests.harness.FileSystemHelper.clear(tempDir.toFile()); + } + } }