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:
parent
14152207f6
commit
8afb8ebf31
12 changed files with 2395 additions and 1 deletions
File diff suppressed because it is too large
Load diff
|
@ -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.
|
||||
|
|
12
TestAssets/TestProjects/TestAppWithSln/Program.cs
Normal file
12
TestAssets/TestProjects/TestAppWithSln/Program.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace ConsoleApplication
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello World!");
|
||||
}
|
||||
}
|
||||
}
|
22
TestAssets/TestProjects/TestAppWithSln/TestAppWithSln.sln
Normal file
22
TestAssets/TestProjects/TestAppWithSln/TestAppWithSln.sln
Normal 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
|
18
TestAssets/TestProjects/TestAppWithSln/TestAppWithSln.xproj
Normal file
18
TestAssets/TestProjects/TestAppWithSln/TestAppWithSln.xproj
Normal 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>
|
25
TestAssets/TestProjects/TestAppWithSln/project.json
Normal file
25
TestAssets/TestProjects/TestAppWithSln/project.json
Normal 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": {}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
1071
src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
Normal file
1071
src/Microsoft.DotNet.Cli.Sln.Internal/SlnFile.cs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
Loading…
Reference in a new issue