diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.sln b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.sln
new file mode 100644
index 000000000..c8573d702
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/App.sln
@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26006.2
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "src\App\App.csproj", "{DDF3765C-59FB-4AA6-BE83-779ED13AA64A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Src", "Src", "{72BFCA87-B033-4721-8712-4D12166B4A39}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|x64.ActiveCfg = Debug|x64
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|x64.Build.0 = Debug|x64
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|x86.ActiveCfg = Debug|x86
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Debug|x86.Build.0 = Debug|x86
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|x64.ActiveCfg = Release|x64
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|x64.Build.0 = Release|x64
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|x86.ActiveCfg = Release|x86
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {DDF3765C-59FB-4AA6-BE83-779ED13AA64A} = {72BFCA87-B033-4721-8712-4D12166B4A39}
+ EndGlobalSection
+EndGlobal
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/App.csproj b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/App.csproj
new file mode 100644
index 000000000..b38669c62
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/App.csproj
@@ -0,0 +1,15 @@
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/Program.cs b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/Program.cs
new file mode 100644
index 000000000..abb853a4a
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/App/Program.cs
@@ -0,0 +1,10 @@
+using System;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from the main app");
+ Console.WriteLine(Lib.Library.GetMessage());
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Lib.csproj b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Lib.csproj
new file mode 100644
index 000000000..9f8bcbb51
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Lib.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Library.cs b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Library.cs
new file mode 100644
index 000000000..205c42a01
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndCaseSensitiveSolutionFolders/src/Lib/Library.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Lib
+{
+ public class Library
+ {
+ public static string GetMessage()
+ {
+ return "Message from Lib";
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.sln b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.sln
new file mode 100644
index 000000000..17cd062c5
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App.sln
@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26006.2
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "App\App.csproj", "{7072A694-548F-4CAE-A58F-12D257D5F486}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lib", "Lib\\Lib.csproj", "{B38B1FA5-B4C9-456A-8B71-8FCD62ACF400}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.ActiveCfg = Debug|x64
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x64.Build.0 = Debug|x64
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.ActiveCfg = Debug|x86
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Debug|x86.Build.0 = Debug|x86
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.ActiveCfg = Release|x64
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x64.Build.0 = Release|x64
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.ActiveCfg = Release|x86
+ {7072A694-548F-4CAE-A58F-12D257D5F486}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/App.csproj b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/App.csproj
new file mode 100644
index 000000000..27e43f08e
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/App.csproj
@@ -0,0 +1,19 @@
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/Program.cs b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/Program.cs
new file mode 100644
index 000000000..abb853a4a
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/App/Program.cs
@@ -0,0 +1,10 @@
+using System;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from the main app");
+ Console.WriteLine(Lib.Library.GetMessage());
+ }
+}
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Lib.csproj b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Lib.csproj
new file mode 100644
index 000000000..9f8bcbb51
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Lib.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard1.4
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Library.cs b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Library.cs
new file mode 100644
index 000000000..205c42a01
--- /dev/null
+++ b/TestAssets/TestProjects/TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep/Lib/Library.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Lib
+{
+ public class Library
+ {
+ public static string GetMessage()
+ {
+ return "Message from Lib";
+ }
+ }
+}
diff --git a/build/Microsoft.DotNet.Cli.Compile.targets b/build/Microsoft.DotNet.Cli.Compile.targets
index fe9359a2b..9f8802765 100644
--- a/build/Microsoft.DotNet.Cli.Compile.targets
+++ b/build/Microsoft.DotNet.Cli.Compile.targets
@@ -126,32 +126,6 @@
VersionSuffix="$(VersionSuffix)"
ProjectPath="$(SrcDirectory)/tool_roslyn/tool_roslyn.csproj" />
-
-
-
-
-
- u=rw,g=r,o=r
-
-
-
-
- u=rwx,g=rx,o=rx
-
-
-
-
- u=rwx,g=rx,o=rx
-
-
-
-
-
@@ -224,6 +198,32 @@
@(CompileStageSdkDirectories);
$(SharedFrameworkNameVersionPath)" />
+
+
+
+
+
+ u=rw,g=r,o=r
+
+
+
+
+ u=rwx,g=rx,o=rx
+
+
+
+
+ u=rwx,g=rx,o=rx
+
+
+
+
+
1.1.1
- 15.1.546
+ 15.1.548
2.0.0-rc4-61325-08
1.0.0-alpha-20170213-1
4.0.0-rtm-2283
1.0.0-alpha-20170130-3-281
- 15.0.0-preview-20170125-04
+ 15.0.0-preview-20170210-02
1.0.0-beta1-20170202-111
1.0.0-beta1-20170206-112
1.1.1
diff --git a/build/Microsoft.DotNet.Cli.Publish.targets b/build/Microsoft.DotNet.Cli.Publish.targets
index 8ebfcba7a..d9f4341d6 100644
--- a/build/Microsoft.DotNet.Cli.Publish.targets
+++ b/build/Microsoft.DotNet.Cli.Publish.targets
@@ -43,7 +43,7 @@
-
+
diff --git a/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs b/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
index 7eda0d91e..93df94b85 100644
--- a/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
+++ b/src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
@@ -274,7 +274,8 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
}
set
{
- _filePath = PathUtility.GetPathWithDirectorySeparator(value);
+ _filePath = PathUtility.RemoveExtraPathSeparators(
+ PathUtility.GetPathWithDirectorySeparator(value));
}
}
diff --git a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
index 2f2353cbe..895257d28 100644
--- a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
+++ b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
@@ -261,6 +261,32 @@ namespace Microsoft.DotNet.Tools.Common
}
}
+ public static string RemoveExtraPathSeparators(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ return path;
+ }
+
+ var components = path.Split(Path.DirectorySeparatorChar);
+ var result = string.Empty;
+
+ foreach (var component in components)
+ {
+ if (!string.IsNullOrEmpty(component))
+ {
+ result = Path.Combine(result, component);
+ }
+ }
+
+ if (path[path.Length-1] == Path.DirectorySeparatorChar)
+ {
+ result += Path.DirectorySeparatorChar;
+ }
+
+ return result;
+ }
+
public static bool HasExtension(string filePath, string extension)
{
var comparison = StringComparison.Ordinal;
diff --git a/src/dotnet/SlnFileExtensions.cs b/src/dotnet/SlnFileExtensions.cs
index 7fbf0fb70..39e34a806 100644
--- a/src/dotnet/SlnFileExtensions.cs
+++ b/src/dotnet/SlnFileExtensions.cs
@@ -172,7 +172,7 @@ namespace Microsoft.DotNet.Tools.Common
this SlnFile slnFile,
SlnPropertySet nestedProjects)
{
- var solutionFolderPaths = new Dictionary();
+ var solutionFolderPaths = new Dictionary(StringComparer.OrdinalIgnoreCase);
var solutionFolderProjects = slnFile.Projects.GetProjectsByType(ProjectTypeGuids.SolutionFolderGuid);
foreach (var slnProject in solutionFolderProjects)
diff --git a/test/dotnet-sln-add.Tests/GivenDotnetSlnAdd.cs b/test/dotnet-sln-add.Tests/GivenDotnetSlnAdd.cs
index cdf0efc91..740fd6d76 100644
--- a/test/dotnet-sln-add.Tests/GivenDotnetSlnAdd.cs
+++ b/test/dotnet-sln-add.Tests/GivenDotnetSlnAdd.cs
@@ -502,11 +502,13 @@ EndGlobal
.Count().Should().Be(1, $"Lib {reasonString}");
}
- [Fact]
- public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate()
+ [Theory]
+ [InlineData("TestAppWithSlnAndExistingCsprojReferences")]
+ [InlineData("TestAppWithSlnAndExistingCsprojReferencesWithEscapedDirSep")]
+ public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate(string testAsset)
{
var projectDirectory = TestAssets
- .Get("TestAppWithSlnAndExistingCsprojReferences")
+ .Get(testAsset)
.CreateInstance()
.WithSourceFiles()
.Root
@@ -606,6 +608,28 @@ EndGlobal
nonSolutionFolderProjects.Single().TypeGuid.Should().Be(expectedTypeGuid);
}
+ [Fact]
+ private void WhenSlnContainsSolutionFolderWithDifferentCasingItDoesNotCreateDuplicate()
+ {
+ var projectDirectory = TestAssets
+ .Get("TestAppWithSlnAndCaseSensitiveSolutionFolders")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root
+ .FullName;
+
+ var projectToAdd = Path.Combine("src", "Lib", "Lib.csproj");
+ var cmd = new DotnetCommand()
+ .WithWorkingDirectory(projectDirectory)
+ .Execute($"sln App.sln add {projectToAdd}");
+ cmd.Should().Pass();
+
+ var slnFile = SlnFile.Read(Path.Combine(projectDirectory, "App.sln"));
+ var solutionFolderProjects = slnFile.Projects.Where(
+ p => p.TypeGuid == ProjectTypeGuids.SolutionFolderGuid);
+ solutionFolderProjects.Count().Should().Be(1);
+ }
+
private string GetExpectedSlnContents(
string slnPath,
string slnTemplate,