Skip to content

Commit

Permalink
Remove missing files from sln folders
Browse files Browse the repository at this point in the history
Fixes #1
  • Loading branch information
timabell committed Dec 22, 2023
1 parent fcc095e commit a247f1e
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/CLI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class CLI(IGuidGenerator? guidGenerator = null)
{
private readonly IGuidGenerator _guidGenerator = guidGenerator ?? new DefaultGuidGenerator();
private const string SolutionItemsName = "SolutionItems";
private const char SlnItemPathSeparator = '\\';
private static SolutionParser _parser = new();
private static Guid _solutionFolderTypeGuid = new ProjectTypeMapper().ToGuid(ProjectType.SolutionFolder);

Expand Down Expand Up @@ -88,13 +89,19 @@ private static void SyncFile(SolutionFolder solutionItems, string path)
private void SyncFolder(SolutionFolder parentFolder, DirectoryInfo directory, string path)
{
var solutionFolder = FindOrCreateSolutionFolder(parentFolder.Projects, directory.Name, directory.Name);
foreach (var file in directory.EnumerateFiles())
var files = directory.GetFiles();
foreach (var file in files)
{
if (solutionFolder.Files.All(f => f.Split('\\').Last() != file.Name))
if (solutionFolder.Files.Select(f => f.SlnItemName()).All(f => f != file.Name))
{
solutionFolder.Files.Add($"{path}{file.Name}");
}
}
var unwanted = solutionFolder.Files.Where(f => files.All(file => file.Name != f.SlnItemName())).ToList();
foreach (var file in unwanted)
{
solutionFolder.Files.Remove(file);
}
foreach (var subDirectory in directory.EnumerateDirectories())
{
SyncFolder(solutionFolder, subDirectory, $"{path}{subDirectory.Name}\\");
Expand Down Expand Up @@ -133,3 +140,13 @@ public interface IGuidGenerator
{
Guid Next();
}

public static class StringExtensions
{
/// <summary>
/// Get filename from path in solution items (hard-coded to backslash, so can't use Path.GetFileName)
/// </summary>
/// <param name="slnPath"></param>
/// <returns></returns>
public static string SlnItemName(this string slnPath) => slnPath.Split('\\').Last();
}
86 changes: 86 additions & 0 deletions tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,92 @@ public void IgnoresExistingItems()
ModifiedSln().Should().Be(expected);
}

[Fact]
public void RemovesMissingFiles()
{
// Arrange
SetupSln(@"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""SolutionItems"", ""SolutionItems"", ""{17591C35-3F90-4F4A-AA13-45CF8D824066}""
ProjectSection(SolutionItems) = preProject
root-file.txt = root-file.txt
EndProjectSection
EndProject
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""subfolder"", ""subfolder"", ""{CF942CDD-19AC-4E52-9C6E-B1381E0406D9}""
EndProject
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""nested_folder"", ""nested_folder"", ""{F5636E74-888A-4FBD-A8E2-9718A05D90BD}""
ProjectSection(SolutionItems) = preProject
subfolder\nested_folder\valid_file.txt = subfolder\nested_folder\valid_file.txt
subfolder\nested_folder\missing_file.txt = subfolder\nested_folder\missing_file.txt
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CF942CDD-19AC-4E52-9C6E-B1381E0406D9} = {17591C35-3F90-4F4A-AA13-45CF8D824066}
{F5636E74-888A-4FBD-A8E2-9718A05D90BD} = {CF942CDD-19AC-4E52-9C6E-B1381E0406D9}
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
");

SetupFilesystem(new[]
{
"root-file.txt",
"subfolder/nested_folder/valid_file.txt",
});

// Act
_cli.Run(["-s", TargetSlnFile, "root-file.txt", "subfolder"]);

// Assert
const string expected = @"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""SolutionItems"", ""SolutionItems"", ""{17591C35-3F90-4F4A-AA13-45CF8D824066}""
ProjectSection(SolutionItems) = preProject
root-file.txt = root-file.txt
EndProjectSection
EndProject
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""subfolder"", ""subfolder"", ""{CF942CDD-19AC-4E52-9C6E-B1381E0406D9}""
EndProject
Project(""{2150E333-8FDC-42A3-9474-1A3956D46DE8}"") = ""nested_folder"", ""nested_folder"", ""{F5636E74-888A-4FBD-A8E2-9718A05D90BD}""
ProjectSection(SolutionItems) = preProject
subfolder\nested_folder\valid_file.txt = subfolder\nested_folder\valid_file.txt
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CF942CDD-19AC-4E52-9C6E-B1381E0406D9} = {17591C35-3F90-4F4A-AA13-45CF8D824066}
{F5636E74-888A-4FBD-A8E2-9718A05D90BD} = {CF942CDD-19AC-4E52-9C6E-B1381E0406D9}
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
";

ModifiedSln().Should().Be(expected);
}

private string ModifiedSln() => File.ReadAllText(Path.Combine(_testFolder, TargetSlnFile));

private void SetupFilesystem(IEnumerable<string> paths)
Expand Down

0 comments on commit a247f1e

Please sign in to comment.