public async Task AspNetCore_MultiFileNesting() { string projectFileName = Util.GetSampleProject("aspnetcore-empty-30", "aspnetcore-empty-30.sln"); using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), projectFileName)) { var project = sol.GetAllProjectsWithFlavor <AspNetCoreProjectExtension> ().FirstOrDefault(); var dir = project.BaseDirectory; project.AddDirectory("FileNesting"); var rootFile = AddFile(project, Path.Combine(dir, "FileNesting", "bootstrap.css")); Assert.That(FileNestingService.GetChildren(rootFile), Is.Null); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile)?.Count() ?? 0, Is.EqualTo(0)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile)?.Count() ?? 0, Is.EqualTo(0)); // This should be nested under bootstrap.css var mapFile = AddFile(project, Path.Combine(dir, "FileNesting", "bootstrap.css.map")); Assert.That(FileNestingService.GetChildren(rootFile), Contains.Item(mapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile), Contains.Item(mapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile)?.Count() ?? 0, Is.EqualTo(1)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile), Contains.Item(mapFile)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile)?.Count() ?? 0, Is.EqualTo(1)); Assert.That(FileNestingService.GetDependentOrNestedChildren(mapFile)?.Count() ?? 0, Is.EqualTo(0)); Assert.That(FileNestingService.GetDependentOrNestedTree(mapFile)?.Count() ?? 0, Is.EqualTo(0)); // This should be nested under bootstrap.css var minFile = AddFile(project, Path.Combine(dir, "FileNesting", "bootstrap.min.css")); Assert.That(FileNestingService.GetChildren(rootFile), Contains.Item(minFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile), Contains.Item(minFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile)?.Count() ?? 0, Is.EqualTo(2)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile), Contains.Item(minFile)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile)?.Count() ?? 0, Is.EqualTo(2)); Assert.That(FileNestingService.GetDependentOrNestedChildren(minFile)?.Count() ?? 0, Is.EqualTo(0)); Assert.That(FileNestingService.GetDependentOrNestedTree(minFile)?.Count() ?? 0, Is.EqualTo(0)); // This should be nested under bootstrap.min.css var minMapFile = AddFile(project, Path.Combine(dir, "FileNesting", "bootstrap.min.css.map")); Assert.That(FileNestingService.GetChildren(rootFile), !Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile), !Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(rootFile)?.Count() ?? 0, Is.EqualTo(2)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile), Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedTree(rootFile)?.Count() ?? 0, Is.EqualTo(3)); Assert.That(FileNestingService.GetChildren(minFile), Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(minFile), Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedChildren(minFile)?.Count() ?? 0, Is.EqualTo(1)); Assert.That(FileNestingService.GetDependentOrNestedTree(minFile), Contains.Item(minMapFile)); Assert.That(FileNestingService.GetDependentOrNestedTree(minFile)?.Count() ?? 0, Is.EqualTo(1)); // Check if all files are taken into account when renaming the top one var files = MonoDevelop.Ide.ProjectOperations.GetDependentFilesToRename(rootFile, "reboot.css"); Assert.That(files.Count, Is.EqualTo(3)); Assert.True(files.Any(x => x.File == mapFile && x.NewName == "reboot.css.map")); Assert.True(files.Any(x => x.File == minFile && x.NewName == "reboot.min.css")); Assert.True(files.Any(x => x.File == minMapFile && x.NewName == "reboot.min.css.map")); } }
public void RemoveFilesFromProject(bool delete, List <ProjectFile> files) { foreach (var file in files) { var project = file.Project; var inFolder = project.Files.GetFilesInVirtualPath(file.ProjectVirtualPath.ParentDirectory).ToList(); if (inFolder.Count == 1 && inFolder [0] == file && project.Files.GetFileWithVirtualPath(file.ProjectVirtualPath.ParentDirectory) == null) { // This is the last project file in the folder. Make sure we keep // a reference to the folder, so it is not deleted from the tree. var folderFile = new ProjectFile(project.BaseDirectory.Combine(file.ProjectVirtualPath.ParentDirectory)); folderFile.Subtype = Subtype.Directory; project.Files.Add(folderFile); } var children = FileNestingService.GetDependentOrNestedTree(file); if (children != null) { foreach (var child in children.ToArray()) { // Delete file before removing them from the project to avoid Remove items being added // if the project is currently being saved in memory or to disk. if (delete) { FileService.DeleteFile(child.Name); } project.Files.Remove(child); } } // Delete file before removing them from the project to avoid Remove items being added // if the project is currently being saved in memory or to disk. if (delete && !file.IsLink && File.Exists(file.Name)) { FileService.DeleteFile(file.Name); } project.Files.Remove(file); } }
public override void DeleteMultipleItems() { var projects = new Set <SolutionItem> (); var files = new List <ProjectFile> (); bool hasChildren = false; foreach (var node in CurrentNodes) { var pf = (ProjectFile)node.DataItem; projects.Add(pf.Project); if (pf.HasChildren || FileNestingService.HasChildren(pf)) { hasChildren = true; } files.Add(pf); } var removeFromProject = new AlertButton(GettextCatalog.GetString("_Remove from Project"), Gtk.Stock.Remove); string question; string secondaryText = null; bool filesExist = CheckAnyFileExists(files); if (filesExist) { secondaryText = GettextCatalog.GetString("The Delete option permanently removes the file from your hard disk. " + "Click Remove from Project if you only want to remove it from your current solution."); } if (hasChildren) { if (files.Count == 1) { question = GettextCatalog.GetString("Are you sure you want to remove the file {0} and " + "its code-behind children from project {1}?", Path.GetFileName(files[0].Name), files[0].Project.Name); } else { question = GettextCatalog.GetString("Are you sure you want to remove the selected files and " + "their code-behind children from the project?"); } } else { if (files.Count == 1) { question = GettextCatalog.GetString("Are you sure you want to remove file {0} from project {1}?", Path.GetFileName(files[0].Name), files[0].Project.Name); } else { question = GettextCatalog.GetString("Are you sure you want to remove the selected files from the project?"); } } var result = MessageService.AskQuestion(question, secondaryText, GetDeleteConfirmationButtons(filesExist, removeFromProject)); if (result != removeFromProject && result != AlertButton.Delete) { return; } foreach (var file in files) { var project = file.Project; var inFolder = project.Files.GetFilesInVirtualPath(file.ProjectVirtualPath.ParentDirectory).ToList(); if (inFolder.Count == 1 && inFolder [0] == file && project.Files.GetFileWithVirtualPath(file.ProjectVirtualPath.ParentDirectory) == null) { // This is the last project file in the folder. Make sure we keep // a reference to the folder, so it is not deleted from the tree. var folderFile = new ProjectFile(project.BaseDirectory.Combine(file.ProjectVirtualPath.ParentDirectory)); folderFile.Subtype = Subtype.Directory; project.Files.Add(folderFile); } var children = FileNestingService.GetDependentOrNestedTree(file); if (children != null) { foreach (var child in children.ToArray()) { project.Files.Remove(child); if (result == AlertButton.Delete) { FileService.DeleteFile(child.Name); } } } project.Files.Remove(file); if (result == AlertButton.Delete && !file.IsLink) { FileService.DeleteFile(file.Name); } } IdeApp.ProjectOperations.SaveAsync(projects); }
async System.Threading.Tasks.Task DropNode(HashSet <SolutionItem> projectsToSave, object dataObject, HashSet <ProjectFile> groupedFiles, DragOperation operation) { FilePath targetDirectory = GetFolderPath(CurrentNode.DataItem); FilePath source; string what; Project targetProject = (Project)CurrentNode.GetParentDataItem(typeof(Project), true); Project sourceProject; IEnumerable <ProjectFile> groupedChildren = null; if (dataObject is ProjectFolder) { source = ((ProjectFolder)dataObject).Path; sourceProject = ((ProjectFolder)dataObject).Project; what = Path.GetFileName(source); } else if (dataObject is ProjectFile) { ProjectFile file = (ProjectFile)dataObject; // if this ProjectFile is one of the grouped files being pulled in by a parent being copied/moved, ignore it if (groupedFiles.Contains(file)) { return; } if (file.DependsOnFile != null && operation == DragOperation.Move) { // unlink this file from its parent (since its parent is not being moved) file.DependsOn = null; // if moving a linked file into its containing folder, simply unlink it from its parent if (file.FilePath.ParentDirectory == targetDirectory) { projectsToSave.Add(targetProject); return; } } sourceProject = file.Project; if (sourceProject != null && file.IsLink) { source = sourceProject.BaseDirectory.Combine(file.ProjectVirtualPath); } else { source = file.FilePath; } groupedChildren = FileNestingService.GetDependentOrNestedTree(file); what = null; } else if (dataObject is Gtk.SelectionData) { SelectionData data = (SelectionData)dataObject; if (data.Type != "text/uri-list") { return; } string sources = System.Text.Encoding.UTF8.GetString(data.Data); Console.WriteLine("text/uri-list:\n{0}", sources); string[] files = sources.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); for (int n = 0; n < files.Length; n++) { Uri uri = new Uri(files[n]); if (uri.Scheme != "file") { return; } if (Directory.Exists(uri.LocalPath)) { return; } files[n] = uri.LocalPath; } IdeApp.ProjectOperations.AddFilesToProject(targetProject, files, targetDirectory); projectsToSave.Add(targetProject); return; } else if (dataObject is SolutionFolderFileNode) { var sff = (SolutionFolderFileNode)dataObject; sff.Parent.Files.Remove(sff.Path); await IdeApp.ProjectOperations.SaveAsync(sff.Parent.ParentSolution); source = ((SolutionFolderFileNode)dataObject).Path; sourceProject = null; what = null; } else { return; } var targetPath = targetDirectory.Combine(source.FileName); // If copying to the same directory, make a copy with a different name if (targetPath == source) { targetPath = ProjectOperations.GetTargetCopyName(targetPath, dataObject is ProjectFolder); } var targetChildPaths = groupedChildren != null?groupedChildren.Select(child => { var targetChildPath = targetDirectory.Combine(child.FilePath.FileName); if (targetChildPath == child.FilePath) { targetChildPath = ProjectOperations.GetTargetCopyName(targetChildPath, false); } return(targetChildPath); }).ToList() : null; if (dataObject is ProjectFolder) { string q; if (operation == DragOperation.Move) { if (targetPath.ParentDirectory == targetProject.BaseDirectory) { q = GettextCatalog.GetString("Do you really want to move the folder '{0}' to the root folder of project '{1}'?", what, targetProject.Name); } else { q = GettextCatalog.GetString("Do you really want to move the folder '{0}' to the folder '{1}'?", what, targetDirectory.FileName); } if (!MessageService.Confirm(q, AlertButton.Move)) { return; } } else { if (targetPath.ParentDirectory == targetProject.BaseDirectory) { q = GettextCatalog.GetString("Do you really want to copy the folder '{0}' to the root folder of project '{1}'?", what, targetProject.Name); } else { q = GettextCatalog.GetString("Do you really want to copy the folder '{0}' to the folder '{1}'?", what, targetDirectory.FileName); } if (!MessageService.Confirm(q, AlertButton.Copy)) { return; } } } else if (dataObject is ProjectFile) { var items = Enumerable.Repeat(targetPath, 1); if (targetChildPaths != null) { items = items.Concat(targetChildPaths); } foreach (var file in items) { if (File.Exists(file)) { if (!MessageService.Confirm(GettextCatalog.GetString("The file '{0}' already exists. Do you want to overwrite it?", file.FileName), AlertButton.OverwriteFile)) { return; } } } } var filesToSave = new List <Document> (); foreach (Document doc in IdeApp.Workbench.Documents) { if (doc.IsDirty && doc.IsFile) { if (doc.Name == source || doc.Name.StartsWith(source + Path.DirectorySeparatorChar)) { filesToSave.Add(doc); } else if (groupedChildren != null) { foreach (ProjectFile f in groupedChildren) { if (doc.Name == f.Name) { filesToSave.Add(doc); } } } } } if (filesToSave.Count > 0) { StringBuilder sb = new StringBuilder(); foreach (Document doc in filesToSave) { if (sb.Length > 0) { sb.Append(",\n"); } sb.Append(Path.GetFileName(doc.Name)); } string question; if (operation == DragOperation.Move) { if (filesToSave.Count == 1) { question = GettextCatalog.GetString("Do you want to save the file '{0}' before the move operation?", sb.ToString()); } else { question = GettextCatalog.GetString("Do you want to save the following files before the move operation?\n\n{0}", sb.ToString()); } } else { if (filesToSave.Count == 1) { question = GettextCatalog.GetString("Do you want to save the file '{0}' before the copy operation?", sb.ToString()); } else { question = GettextCatalog.GetString("Do you want to save the following files before the copy operation?\n\n{0}", sb.ToString()); } } AlertButton noSave = new AlertButton(GettextCatalog.GetString("Don't Save")); AlertButton res = MessageService.AskQuestion(question, AlertButton.Cancel, noSave, AlertButton.Save); if (res == AlertButton.Cancel) { return; } if (res == AlertButton.Save) { try { foreach (Document doc in filesToSave) { await doc.Save(); } } catch (Exception ex) { MessageService.ShowError(GettextCatalog.GetString("Save operation failed."), ex); return; } } } if (operation == DragOperation.Move && sourceProject != null) { projectsToSave.Add(sourceProject); } if (targetProject != null) { projectsToSave.Add(targetProject); } bool move = operation == DragOperation.Move; var opText = move ? GettextCatalog.GetString("Moving files...") : GettextCatalog.GetString("Copying files..."); using (var monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor(opText, Stock.StatusSolutionOperation, true)) { // If we drag and drop a node in the treeview corresponding to a directory, do not move // the entire directory. We should only move the files which exist in the project. Otherwise // we will need a lot of hacks all over the code to prevent us from incorrectly moving version // control related files such as .svn directories // Note: if we are transferring a ProjectFile, this will copy/move the ProjectFile's DependentChildren as well. IdeApp.ProjectOperations.TransferFiles(monitor, sourceProject, source, targetProject, targetPath, move, sourceProject != null); } }