sln reader/writer (#4870)

* Snap of sln reader/writer from https://github.com/mono/monodevelop

* Remove unnecessary code

* Create a new test asset with an sln file because adding an sln to an existing one broke other tests

* Remove commented out line

* Removing unneeded PropertyGroup per PR comments

* Update the license

* Fixing the license
This commit is contained in:
Justin Goshi 2016-11-30 14:08:28 -10:00 committed by GitHub
parent 14152207f6
commit 8afb8ebf31
12 changed files with 2395 additions and 1 deletions

File diff suppressed because it is too large Load diff

View file

@ -46,3 +46,46 @@ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
License notice for MonoDevelop
------------------------------
Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Copyright (c) 2011 Novell, Inc (http://www.novell.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,12 @@
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

View file

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithSln", "TestAppWithSln.xproj", "{0138CB8F-4AA9-4029-A21E-C07C30F425BA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.23107" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.23107</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>0138cb8f-4aa9-4029-a21e-c07c30f425ba</ProjectGuid>
<RootNamespace>TestAppWithContents</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -0,0 +1,25 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": "1.0.1"
},
"frameworks": {
"netcoreapp1.0": {}
},
"runtimes": {
"win7-x64": {},
"win7-x86": {},
"osx.10.10-x64": {},
"osx.10.11-x64": {},
"ubuntu.14.04-x64": {},
"ubuntu.16.04-x64": {},
"centos.7-x64": {},
"rhel.7.2-x64": {},
"debian.8-x64": {},
"fedora.23-x64": {},
"opensuse.13.2-x64": {}
}
}

View file

@ -0,0 +1,400 @@
//
// FilePath.cs
//
// Author:
// Lluis Sanchez Gual <lluis@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Linq;
namespace Microsoft.DotNet.Cli.Sln.Internal.FileManipulation
{
public struct FilePath : IComparable<FilePath>, IComparable, IEquatable<FilePath>
{
public static readonly StringComparer PathComparer = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
public static readonly StringComparison PathComparison = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
readonly string fileName;
public static readonly FilePath Null = new FilePath(null);
public static readonly FilePath Empty = new FilePath(string.Empty);
public FilePath(string name)
{
if (name != null && name.Length > 6 && name[0] == 'f' && name.StartsWith("file://", StringComparison.Ordinal))
name = new Uri(name).LocalPath;
fileName = name;
}
public bool IsNull
{
get { return fileName == null; }
}
public bool IsNullOrEmpty
{
get { return string.IsNullOrEmpty(fileName); }
}
public bool IsNotNull
{
get { return fileName != null; }
}
public bool IsEmpty
{
get { return fileName != null && fileName.Length == 0; }
}
const int PATHMAX = 4096 + 1;
static readonly char[] invalidPathChars = Path.GetInvalidPathChars();
public static char[] GetInvalidPathChars()
{
return (char[])invalidPathChars.Clone();
}
static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
public static char[] GetInvalidFileNameChars()
{
return (char[])invalidFileNameChars.Clone();
}
public FilePath FullPath
{
get
{
return new FilePath(!string.IsNullOrEmpty(fileName) ? Path.GetFullPath(fileName) : "");
}
}
public bool IsDirectory
{
get
{
return Directory.Exists(FullPath);
}
}
/// <summary>
/// Returns a path in standard form, which can be used to be compared
/// for equality with other canonical paths. It is similar to FullPath,
/// but unlike FullPath, the directory "/a/b" is considered equal to "/a/b/"
/// </summary>
public FilePath CanonicalPath
{
get
{
if (fileName == null)
return FilePath.Null;
if (fileName.Length == 0)
return FilePath.Empty;
string fp = Path.GetFullPath(fileName);
if (fp.Length > 0)
{
if (fp[fp.Length - 1] == Path.DirectorySeparatorChar)
return fp.TrimEnd(Path.DirectorySeparatorChar);
if (fp[fp.Length - 1] == Path.AltDirectorySeparatorChar)
return fp.TrimEnd(Path.AltDirectorySeparatorChar);
}
return fp;
}
}
public string FileName
{
get
{
return Path.GetFileName(fileName);
}
}
public string Extension
{
get
{
return Path.GetExtension(fileName);
}
}
public bool HasExtension(string extension)
{
return fileName.Length > extension.Length
&& fileName.EndsWith(extension, StringComparison.OrdinalIgnoreCase)
&& fileName[fileName.Length - extension.Length - 1] != Path.PathSeparator;
}
public string FileNameWithoutExtension
{
get
{
return Path.GetFileNameWithoutExtension(fileName);
}
}
public FilePath ParentDirectory
{
get
{
return new FilePath(Path.GetDirectoryName(fileName));
}
}
public bool IsAbsolute
{
get { return Path.IsPathRooted(fileName); }
}
public bool IsChildPathOf(FilePath basePath)
{
if (basePath.fileName[basePath.fileName.Length - 1] != Path.DirectorySeparatorChar)
return fileName.StartsWith(basePath.fileName + Path.DirectorySeparatorChar, PathComparison);
else
return fileName.StartsWith(basePath.fileName, PathComparison);
}
public FilePath ChangeExtension(string ext)
{
return Path.ChangeExtension(fileName, ext);
}
/// <summary>
/// Returns a file path with the name changed to the provided name, but keeping the extension
/// </summary>
/// <returns>The new file path</returns>
/// <param name="newName">New file name</param>
public FilePath ChangeName(string newName)
{
return ParentDirectory.Combine(newName) + Extension;
}
public FilePath Combine(params FilePath[] paths)
{
string path = fileName;
foreach (FilePath p in paths)
path = Path.Combine(path, p.fileName);
return new FilePath(path);
}
public FilePath Combine(params string[] paths)
{
return new FilePath(Path.Combine(fileName, Path.Combine(paths)));
}
public Task DeleteAsync()
{
return Task.Run((System.Action)Delete);
}
public void Delete()
{
// Ensure that this file/directory and all children are writable
MakeWritable(true);
// Also ensure the directory containing this file/directory is writable,
// otherwise we will not be able to delete it
ParentDirectory.MakeWritable(false);
if (Directory.Exists(this))
{
Directory.Delete(this, true);
}
else if (File.Exists(this))
{
File.Delete(this);
}
}
public void MakeWritable()
{
MakeWritable(false);
}
public void MakeWritable(bool recurse)
{
if (Directory.Exists(this))
{
try
{
var info = new DirectoryInfo(this);
info.Attributes &= ~FileAttributes.ReadOnly;
}
catch
{
}
if (recurse)
{
foreach (var sub in Directory.GetFileSystemEntries(this))
{
((FilePath)sub).MakeWritable(recurse);
}
}
}
else if (File.Exists(this))
{
try
{
// Try/catch is to work around a mono bug where dangling symlinks
// blow up when you call SetFileAttributes. Just ignore this case
// until mono 2.10.7/8 is released which fixes it.
var info = new FileInfo(this);
info.Attributes &= ~FileAttributes.ReadOnly;
}
catch
{
}
}
}
/// <summary>
/// Builds a path by combining all provided path sections
/// </summary>
public static FilePath Build(params string[] paths)
{
return Empty.Combine(paths);
}
public static FilePath GetCommonRootPath(IEnumerable<FilePath> paths)
{
FilePath root = FilePath.Null;
foreach (FilePath p in paths)
{
if (root.IsNull)
root = p;
else if (root == p)
continue;
else if (root.IsChildPathOf(p))
root = p;
else
{
while (!root.IsNullOrEmpty && !p.IsChildPathOf(root))
root = root.ParentDirectory;
}
}
return root;
}
public FilePath ToAbsolute(FilePath basePath)
{
if (IsAbsolute)
return FullPath;
else
return Combine(basePath, this).FullPath;
}
public static implicit operator FilePath(string name)
{
return new FilePath(name);
}
public static implicit operator string(FilePath filePath)
{
return filePath.fileName;
}
public static bool operator ==(FilePath name1, FilePath name2)
{
return PathComparer.Equals(name1.fileName, name2.fileName);
}
public static bool operator !=(FilePath name1, FilePath name2)
{
return !(name1 == name2);
}
public override bool Equals(object obj)
{
if (!(obj is FilePath))
return false;
FilePath fn = (FilePath)obj;
return this == fn;
}
public override int GetHashCode()
{
if (fileName == null)
return 0;
return PathComparer.GetHashCode(fileName);
}
public override string ToString()
{
return fileName;
}
public int CompareTo(FilePath filePath)
{
return PathComparer.Compare(fileName, filePath.fileName);
}
int IComparable.CompareTo(object obj)
{
if (!(obj is FilePath))
return -1;
return CompareTo((FilePath)obj);
}
#region IEquatable<FilePath> Members
bool IEquatable<FilePath>.Equals(FilePath other)
{
return this == other;
}
#endregion
}
public static class FilePathUtil
{
public static string[] ToStringArray(this FilePath[] paths)
{
string[] array = new string[paths.Length];
for (int n = 0; n < paths.Length; n++)
array[n] = paths[n].ToString();
return array;
}
public static FilePath[] ToFilePathArray(this string[] paths)
{
var array = new FilePath[paths.Length];
for (int n = 0; n < paths.Length; n++)
array[n] = paths[n];
return array;
}
public static IEnumerable<string> ToPathStrings(this IEnumerable<FilePath> paths)
{
foreach (FilePath p in paths)
yield return p.ToString();
}
}
}

View file

@ -0,0 +1,147 @@
//
// FileUtil.cs
//
// Author:
// Lluis Sanchez Gual <lluis@xamarin.com>
//
// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.IO;
using System.Text;
namespace Microsoft.DotNet.Cli.Sln.Internal.FileManipulation
{
static class FileUtil
{
public static TextFormatInfo GetTextFormatInfo(string file)
{
var info = new TextFormatInfo();
string newLine = null;
Encoding encoding;
using (FileStream fs = File.OpenRead(file))
{
byte[] buf = new byte[1024];
int nread, i;
if ((nread = fs.Read(buf, 0, buf.Length)) <= 0)
return info;
if (TryParse(buf, nread, out encoding))
i = encoding.GetPreamble().Length;
else
i = 0;
do
{
// Read to the first newline to figure out which line endings this file is using
while (i < nread)
{
if (buf[i] == '\r')
{
newLine = "\r\n";
break;
}
else if (buf[i] == '\n')
{
newLine = "\n";
break;
}
i++;
}
if (newLine == null)
{
if ((nread = fs.Read(buf, 0, buf.Length)) <= 0)
{
newLine = "\n";
break;
}
i = 0;
}
} while (newLine == null);
// Check for a blank line at the end
info.EndsWithEmptyLine = fs.Seek(-1, SeekOrigin.End) > 0 && fs.ReadByte() == (int)'\n';
info.NewLine = newLine;
info.Encoding = encoding;
return info;
}
}
private static bool TryParse(byte[] buffer, int available, out Encoding encoding)
{
if (buffer.Length >= 2)
{
for (int i = 0; i < table.Length; i++)
{
bool matched = true;
if (available < table[i].GetPreamble().Length)
continue;
for (int j = 0; j < table[i].GetPreamble().Length; j++)
{
if (buffer[j] != table[i].GetPreamble()[j])
{
matched = false;
break;
}
}
if (matched)
{
encoding = table[i];
return true;
}
}
}
encoding = null;
return false;
}
private static readonly Encoding[] table = new[] {
Encoding.UTF7,
Encoding.UTF8,
Encoding.UTF32,
Encoding.ASCII,
};
}
class TextFormatInfo
{
public TextFormatInfo()
{
NewLine = Environment.NewLine;
}
public string NewLine { get; set; }
public Encoding Encoding { get; set; }
public bool EndsWithEmptyLine { get; set; }
}
}

View file

@ -0,0 +1,36 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<Description>SLN file reader/writer</Description>
<VersionPrefix>1.0.0-preview4</VersionPrefix>
<TargetFramework>netstandard1.6</TargetFramework>
<DebugType>portable</DebugType>
<AssemblyName>Microsoft.DotNet.Cli.Sln.Internal</AssemblyName>
<AssemblyOriginatorKeyFile>../../tools/Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161104-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Collections.Specialized">
<Version>4.0.1</Version>
</PackageReference>
<PackageReference Include="System.Text.RegularExpressions">
<Version>4.1.0</Version>
</PackageReference>
<PackageReference Include="NETStandard.Library">
<Version>1.6.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using FluentAssertions;
using Xunit;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
namespace Microsoft.DotNet.Cli.Sln.Internal.Tests
{
public class GivenAnSlnFile : TestBase
{
[Fact]
public void It_reads_an_sln_file()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("TestAppWithSln", callingMethod: "p").Path;
var solutionFullPath = Path.Combine(solutionDirectory, "TestAppWithSln.sln");
var slnFile = new SlnFile();
slnFile.Read(solutionFullPath);
slnFile.FormatVersion.Should().Be("12.00");
slnFile.ProductDescription.Should().Be("Visual Studio 14");
slnFile.VisualStudioVersion.Should().Be("14.0.25420.1");
slnFile.MinimumVisualStudioVersion.Should().Be("10.0.40219.1");
slnFile.BaseDirectory.Should().Be(solutionDirectory);
slnFile.FileName.FileName.Should().Be("TestAppWithSln.sln");
SlnFile.GetFileVersion(solutionFullPath).Should().Be("12.00");
slnFile.Projects.Count.Should().Be(1);
var project = slnFile.Projects[0];
project.Id.Should().Be("{0138CB8F-4AA9-4029-A21E-C07C30F425BA}");
project.TypeGuid.Should().Be("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}");
project.Name.Should().Be("TestAppWithSln");
project.FilePath.Should().Be("TestAppWithSln.xproj");
}
[Fact]
public void It_writes_an_sln_file()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("TestAppWithSln", callingMethod: "p").Path;
var solutionFullPath = Path.Combine(solutionDirectory, "TestAppWithSln.sln");
var slnFile = new SlnFile();
slnFile.Read(solutionFullPath);
slnFile.Projects.Count.Should().Be(1);
var project = slnFile.Projects[0];
project.Name.Should().Be("TestAppWithSln");
project.Name = "New Project Name";
project.FilePath.Should().Be("TestAppWithSln.xproj");
project.FilePath = "New File Path";
var newSolutionFullPath = Path.Combine(solutionDirectory, "TestAppWithSln_modified.sln");
slnFile.Write(newSolutionFullPath);
slnFile = new SlnFile();
slnFile.Read(newSolutionFullPath);
slnFile.FormatVersion.Should().Be("12.00");
slnFile.ProductDescription.Should().Be("Visual Studio 14");
slnFile.VisualStudioVersion.Should().Be("14.0.25420.1");
slnFile.MinimumVisualStudioVersion.Should().Be("10.0.40219.1");
slnFile.BaseDirectory.Should().Be(solutionDirectory);
slnFile.FileName.FileName.Should().Be("TestAppWithSln_modified.sln");
SlnFile.GetFileVersion(solutionFullPath).Should().Be("12.00");
slnFile.Projects.Count.Should().Be(1);
project = slnFile.Projects[0];
project.Id.Should().Be("{0138CB8F-4AA9-4029-A21E-C07C30F425BA}");
project.TypeGuid.Should().Be("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}");
project.Name.Should().Be("New Project Name");
project.FilePath.Should().Be("New File Path");
slnFile.Projects.Count.Should().Be(1);
project = slnFile.Projects[0];
}
}
}

View file

@ -0,0 +1,50 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>Microsoft.DotNet.Cli.Sln.Internal.Tests</AssemblyName>
<AssemblyOriginatorKeyFile>../../tools/test_key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);netstandardapp1.5;dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Sln.Internal\Microsoft.DotNet.Cli.Sln.Internal.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161104-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk">
<Version>15.0.0-preview-20161123-03</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.2.0-beta4-build3444</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.2.0-beta4-build1194</Version>
</PackageReference>
<PackageReference Include="FluentAssertions">
<Version>4.0.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>