dnx-watch -> dotnet-watch
This commit is contained in:
parent
4bef698f3b
commit
59cb4fe65a
|
|
@ -48,3 +48,5 @@
|
||||||
*.fsproj text=auto
|
*.fsproj text=auto
|
||||||
*.dbproj text=auto
|
*.dbproj text=auto
|
||||||
*.sln text=auto eol=crlf
|
*.sln text=auto eol=crlf
|
||||||
|
|
||||||
|
*.sh eol=lf
|
||||||
|
|
@ -25,3 +25,5 @@ nuget.exe
|
||||||
*.ipch
|
*.ipch
|
||||||
*.sln.ide
|
*.sln.ide
|
||||||
project.lock.json
|
project.lock.json
|
||||||
|
.testPublish/
|
||||||
|
.build/
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,11 @@ addons:
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- libunwind8
|
- libunwind8
|
||||||
- zlib1g
|
- zlib1g
|
||||||
before_install:
|
|
||||||
- if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install icu4c; fi
|
|
||||||
env:
|
|
||||||
- KOREBUILD_DNU_RESTORE_CORECLR=true MONO_THREADS_PER_CPU=2000
|
|
||||||
mono:
|
mono:
|
||||||
- 4.0.5
|
- 4.0.5
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
osx_image: xcode7.1
|
||||||
script:
|
script:
|
||||||
- ./build.sh --quiet verify
|
- ./build.sh --quiet verify
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<packageSources>
|
<packageSources>
|
||||||
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
||||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||||
</packageSources>
|
</packageSources>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
||||||
68
build.cmd
68
build.cmd
|
|
@ -1,40 +1,40 @@
|
||||||
@echo off
|
@ECHO off
|
||||||
cd %~dp0
|
|
||||||
|
|
||||||
SETLOCAL
|
SETLOCAL
|
||||||
|
|
||||||
|
SET REPO_FOLDER=%~dp0
|
||||||
|
CD "%REPO_FOLDER%"
|
||||||
|
|
||||||
|
SET BUILD_FOLDER=.build
|
||||||
|
SET KOREBUILD_FOLDER=%BUILD_FOLDER%\KoreBuild-dotnet
|
||||||
|
SET KOREBUILD_VERSION=
|
||||||
|
|
||||||
|
SET NUGET_PATH=%BUILD_FOLDER%\NuGet.exe
|
||||||
SET NUGET_VERSION=latest
|
SET NUGET_VERSION=latest
|
||||||
SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe
|
SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe
|
||||||
SET BUILDCMD_KOREBUILD_VERSION=
|
|
||||||
SET BUILDCMD_DNX_VERSION=
|
|
||||||
|
|
||||||
IF EXIST %CACHED_NUGET% goto copynuget
|
IF NOT EXIST %BUILD_FOLDER% (
|
||||||
echo Downloading latest version of NuGet.exe...
|
md %BUILD_FOLDER%
|
||||||
IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
|
|
||||||
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'"
|
|
||||||
|
|
||||||
:copynuget
|
|
||||||
IF EXIST .nuget\nuget.exe goto restore
|
|
||||||
md .nuget
|
|
||||||
copy %CACHED_NUGET% .nuget\nuget.exe > nul
|
|
||||||
|
|
||||||
:restore
|
|
||||||
IF EXIST packages\Sake goto getdnx
|
|
||||||
IF "%BUILDCMD_KOREBUILD_VERSION%"=="" (
|
|
||||||
.nuget\nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
|
||||||
) ELSE (
|
|
||||||
.nuget\nuget.exe install KoreBuild -version %BUILDCMD_KOREBUILD_VERSION% -ExcludeVersion -o packages -nocache -pre
|
|
||||||
)
|
|
||||||
.nuget\NuGet.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages
|
|
||||||
|
|
||||||
:getdnx
|
|
||||||
IF "%BUILDCMD_DNX_VERSION%"=="" (
|
|
||||||
SET BUILDCMD_DNX_VERSION=latest
|
|
||||||
)
|
|
||||||
IF "%SKIP_DNX_INSTALL%"=="" (
|
|
||||||
CALL packages\KoreBuild\build\dnvm install %BUILDCMD_DNX_VERSION% -runtime CoreCLR -arch x86 -alias default
|
|
||||||
CALL packages\KoreBuild\build\dnvm install default -runtime CLR -arch x86 -alias default
|
|
||||||
) ELSE (
|
|
||||||
CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86
|
|
||||||
)
|
)
|
||||||
|
|
||||||
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
IF NOT EXIST %NUGET_PATH% (
|
||||||
|
IF NOT EXIST %CACHED_NUGET% (
|
||||||
|
echo Downloading latest version of NuGet.exe...
|
||||||
|
IF NOT EXIST %LocalAppData%\NuGet (
|
||||||
|
md %LocalAppData%\NuGet
|
||||||
|
)
|
||||||
|
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'"
|
||||||
|
)
|
||||||
|
|
||||||
|
copy %CACHED_NUGET% %NUGET_PATH% > nul
|
||||||
|
)
|
||||||
|
|
||||||
|
IF NOT EXIST %KOREBUILD_FOLDER% (
|
||||||
|
SET KOREBUILD_DOWNLOAD_ARGS=
|
||||||
|
IF NOT "%KOREBUILD_VERSION%"=="" (
|
||||||
|
SET KOREBUILD_DOWNLOAD_ARGS=-version %KOREBUILD_VERSION%
|
||||||
|
)
|
||||||
|
|
||||||
|
%BUILD_FOLDER%\nuget.exe install KoreBuild-dotnet -ExcludeVersion -o %BUILD_FOLDER% -nocache -pre %KOREBUILD_DOWNLOAD_ARGS%
|
||||||
|
)
|
||||||
|
|
||||||
|
"%KOREBUILD_FOLDER%\build\KoreBuild.cmd" %*
|
||||||
|
|
|
||||||
42
build.sh
42
build.sh
|
|
@ -1,5 +1,10 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
buildFolder=.build
|
||||||
|
koreBuildFolder=$buildFolder/KoreBuild-dotnet
|
||||||
|
|
||||||
|
nugetPath=$buildFolder/nuget.exe
|
||||||
|
|
||||||
if test `uname` = Darwin; then
|
if test `uname` = Darwin; then
|
||||||
cachedir=~/Library/Caches/KBuild
|
cachedir=~/Library/Caches/KBuild
|
||||||
else
|
else
|
||||||
|
|
@ -11,33 +16,30 @@ else
|
||||||
fi
|
fi
|
||||||
mkdir -p $cachedir
|
mkdir -p $cachedir
|
||||||
nugetVersion=latest
|
nugetVersion=latest
|
||||||
cachePath=$cachedir/nuget.$nugetVersion.exe
|
cacheNuget=$cachedir/nuget.$nugetVersion.exe
|
||||||
|
|
||||||
url=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe
|
nugetUrl=https://dist.nuget.org/win-x86-commandline/$nugetVersion/nuget.exe
|
||||||
|
|
||||||
if test ! -f $cachePath; then
|
if test ! -d $buildFolder; then
|
||||||
wget -O $cachePath $url 2>/dev/null || curl -o $cachePath --location $url /dev/null
|
mkdir $buildFolder
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test ! -e .nuget; then
|
if test ! -f $nugetPath; then
|
||||||
mkdir .nuget
|
if test ! -f $cacheNuget; then
|
||||||
cp $cachePath .nuget/nuget.exe
|
wget -O $cacheNuget $nugetUrl 2>/dev/null || curl -o $cacheNuget --location $nugetUrl /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp $cacheNuget $nugetPath
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test ! -d packages/Sake; then
|
if test ! -d $koreBuildFolder; then
|
||||||
mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
mono $nugetPath install KoreBuild-dotnet -ExcludeVersion -o $buildFolder -nocache -pre
|
||||||
mono .nuget/nuget.exe install Sake -ExcludeVersion -Source https://www.nuget.org/api/v2/ -Out packages
|
chmod +x $koreBuildFolder/build/KoreBuild.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type dnvm > /dev/null 2>&1; then
|
makeFile=makefile.shade
|
||||||
source packages/KoreBuild/build/dnvm.sh
|
if [ ! -e $makeFile ]; then
|
||||||
|
makeFile=$koreBuildFolder/build/makefile.shade
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type dnx > /dev/null 2>&1 || [ -z "$SKIP_DNX_INSTALL" ]; then
|
./$koreBuildFolder/build/KoreBuild.sh -n $nugetPath -m $makeFile "$@"
|
||||||
dnvm install latest -runtime coreclr -alias default
|
|
||||||
dnvm install default -runtime mono -alias default
|
|
||||||
else
|
|
||||||
dnvm use default -runtime mono
|
|
||||||
fi
|
|
||||||
|
|
||||||
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ VisualStudioVersion = 14.0.23107.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66517987-2A5A-4330-B130-207039378FD4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher", "src\Microsoft.Dnx.Watcher\Microsoft.Dnx.Watcher.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-watch", "src\dotnet-watch\dotnet-watch.xproj", "{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Core", "src\Microsoft.Dnx.Watcher.Core\Microsoft.Dnx.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Watcher.Core", "src\Microsoft.DotNet.Watcher.Core\Microsoft.DotNet.Watcher.Core.xproj", "{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8321E0D1-9A47-4D2F-AED8-3AE636D44E35}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|
@ -15,10 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
NuGet.Config = NuGet.Config
|
NuGet.Config = NuGet.Config
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{442A6A17-4C5A-4E11-B547-A554063FD338}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Dnx.Watcher.Tests", "test\Microsoft.Dnx.Watcher.Tests\Microsoft.Dnx.Watcher.Tests.xproj", "{640D190B-26DB-4DDE-88EE-55814C86C43E}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -33,10 +29,6 @@ Global
|
||||||
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{640D190B-26DB-4DDE-88EE-55814C86C43E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{640D190B-26DB-4DDE-88EE-55814C86C43E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -44,6 +36,5 @@ Global
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4}
|
{8A8CEABC-AC47-43FF-A5DF-69224F7E1F46} = {66517987-2A5A-4330-B130-207039378FD4}
|
||||||
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4}
|
{D3DA3BBB-E206-404F-AEE6-17FB9B6F1221} = {66517987-2A5A-4330-B130-207039378FD4}
|
||||||
{640D190B-26DB-4DDE-88EE-55814C86C43E} = {442A6A17-4C5A-4E11-B547-A554063FD338}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal static class Constants
|
|
||||||
{
|
|
||||||
public const string BootstrapperExeName = "dnx";
|
|
||||||
public const string BootstrapperFullName = "Microsoft .NET Execution environment";
|
|
||||||
public const string DefaultLocalRuntimeHomeDir = ".dnx";
|
|
||||||
public const string RuntimeShortName = "dnx";
|
|
||||||
public const string RuntimeLongName = "Microsoft DNX";
|
|
||||||
public const string RuntimeNamePrefix = RuntimeShortName + "-";
|
|
||||||
public const string WebConfigRuntimeVersion = RuntimeNamePrefix + "version";
|
|
||||||
public const string WebConfigRuntimeFlavor = RuntimeNamePrefix + "clr";
|
|
||||||
public const string WebConfigRuntimeAppBase = RuntimeNamePrefix + "app-base";
|
|
||||||
public const string WebConfigBootstrapperVersion = "bootstrapper-version";
|
|
||||||
public const string WebConfigRuntimePath = "runtime-path";
|
|
||||||
public const string BootstrapperHostName = RuntimeShortName + ".host";
|
|
||||||
public const string BootstrapperClrName = RuntimeShortName + ".clr";
|
|
||||||
|
|
||||||
public const int LockFileVersion = 2;
|
|
||||||
|
|
||||||
public static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(10);
|
|
||||||
public static readonly string AppConfigurationFileName = "app.config";
|
|
||||||
|
|
||||||
public static readonly Version Version35 = new Version(3, 5);
|
|
||||||
public static readonly Version Version40 = new Version(4, 0);
|
|
||||||
public static readonly Version Version50 = new Version(5, 0);
|
|
||||||
public static readonly Version Version10_0 = new Version(10, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal sealed class FileFormatException : Exception
|
|
||||||
{
|
|
||||||
private FileFormatException(string message) :
|
|
||||||
base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileFormatException(string message, Exception innerException) :
|
|
||||||
base(message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Path { get; private set; }
|
|
||||||
public int Line { get; private set; }
|
|
||||||
public int Column { get; private set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Path}({Line},{Column}): Error: {base.ToString()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(Exception exception, string filePath)
|
|
||||||
{
|
|
||||||
if (exception is JsonDeserializerException)
|
|
||||||
{
|
|
||||||
return new FileFormatException(exception.Message, exception)
|
|
||||||
.WithFilePath(filePath)
|
|
||||||
.WithLineInfo((JsonDeserializerException)exception);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new FileFormatException(exception.Message, exception)
|
|
||||||
.WithFilePath(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(Exception exception, JsonValue jsonValue, string filePath)
|
|
||||||
{
|
|
||||||
var result = Create(exception, jsonValue)
|
|
||||||
.WithFilePath(filePath);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(Exception exception, JsonValue jsonValue)
|
|
||||||
{
|
|
||||||
var result = new FileFormatException(exception.Message, exception)
|
|
||||||
.WithLineInfo(jsonValue);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(string message, JsonValue jsonValue, string filePath)
|
|
||||||
{
|
|
||||||
var result = Create(message, jsonValue)
|
|
||||||
.WithFilePath(filePath);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(string message, string filePath)
|
|
||||||
{
|
|
||||||
var result = new FileFormatException(message)
|
|
||||||
.WithFilePath(filePath);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static FileFormatException Create(string message, JsonValue jsonValue)
|
|
||||||
{
|
|
||||||
var result = new FileFormatException(message)
|
|
||||||
.WithLineInfo(jsonValue);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal FileFormatException WithFilePath(string path)
|
|
||||||
{
|
|
||||||
if (path == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
Path = path;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileFormatException WithLineInfo(JsonValue value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
Line = value.Line;
|
|
||||||
Column = value.Column;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileFormatException WithLineInfo(JsonDeserializerException exception)
|
|
||||||
{
|
|
||||||
if (exception == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(exception));
|
|
||||||
}
|
|
||||||
|
|
||||||
Line = exception.Line;
|
|
||||||
Column = exception.Column;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class LockFile
|
|
||||||
{
|
|
||||||
public int Version { get; set; }
|
|
||||||
|
|
||||||
public IList<LockFileProjectLibrary> ProjectLibraries { get; set; } = new List<LockFileProjectLibrary>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class LockFileProjectLibrary
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string Path { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,218 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
using NuGet;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal class LockFileReader
|
|
||||||
{
|
|
||||||
public const string LockFileName = "project.lock.json";
|
|
||||||
|
|
||||||
public LockFile Read(string filePath)
|
|
||||||
{
|
|
||||||
using (var stream = OpenFileStream(filePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Read(stream);
|
|
||||||
}
|
|
||||||
catch (FileFormatException ex)
|
|
||||||
{
|
|
||||||
throw ex.WithFilePath(filePath);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create(ex, filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FileStream OpenFileStream(string filePath)
|
|
||||||
{
|
|
||||||
// Retry 3 times before re-throw the exception.
|
|
||||||
// It mitigates the race condition when DTH read lock file while VS is restoring projects.
|
|
||||||
|
|
||||||
int retry = 3;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
if (retry > 0)
|
|
||||||
{
|
|
||||||
retry--;
|
|
||||||
Thread.Sleep(100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal LockFile Read(Stream stream)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var reader = new StreamReader(stream);
|
|
||||||
var jobject = JsonDeserializer.Deserialize(reader) as JsonObject;
|
|
||||||
|
|
||||||
if (jobject != null)
|
|
||||||
{
|
|
||||||
return ReadLockFile(jobject);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidDataException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ran into parsing errors, mark it as unlocked and out-of-date
|
|
||||||
return new LockFile
|
|
||||||
{
|
|
||||||
Version = int.MinValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LockFile ReadLockFile(JsonObject cursor)
|
|
||||||
{
|
|
||||||
var lockFile = new LockFile();
|
|
||||||
lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue);
|
|
||||||
ReadLibrary(cursor.ValueAsJsonObject("libraries"), lockFile);
|
|
||||||
|
|
||||||
return lockFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReadLibrary(JsonObject json, LockFile lockFile)
|
|
||||||
{
|
|
||||||
if (json == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var key in json.Keys)
|
|
||||||
{
|
|
||||||
var value = json.ValueAsJsonObject(key);
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("The value type is not object.", json.Value(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
var parts = key.Split(new[] { '/' }, 2);
|
|
||||||
var name = parts[0];
|
|
||||||
var version = parts.Length == 2 ? SemanticVersion.Parse(parts[1]) : null;
|
|
||||||
|
|
||||||
var type = value.ValueAsString("type")?.Value;
|
|
||||||
|
|
||||||
if (type == "project")
|
|
||||||
{
|
|
||||||
lockFile.ProjectLibraries.Add(new LockFileProjectLibrary
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Path = ReadString(value.Value("path"))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ReadFrameworkAssemblyReference(JsonValue json)
|
|
||||||
{
|
|
||||||
return ReadString(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IList<TItem> ReadArray<TItem>(JsonValue json, Func<JsonValue, TItem> readItem)
|
|
||||||
{
|
|
||||||
if (json == null)
|
|
||||||
{
|
|
||||||
return new List<TItem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var jarray = json as JsonArray;
|
|
||||||
if (jarray == null)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("The value type is not array.", json);
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = new List<TItem>();
|
|
||||||
for (int i = 0; i < jarray.Length; ++i)
|
|
||||||
{
|
|
||||||
items.Add(readItem(jarray[i]));
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IList<TItem> ReadObject<TItem>(JsonObject json, Func<string, JsonValue, TItem> readItem)
|
|
||||||
{
|
|
||||||
if (json == null)
|
|
||||||
{
|
|
||||||
return new List<TItem>();
|
|
||||||
}
|
|
||||||
var items = new List<TItem>();
|
|
||||||
foreach (var childKey in json.Keys)
|
|
||||||
{
|
|
||||||
items.Add(readItem(childKey, json.Value(childKey)));
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ReadBool(JsonObject cursor, string property, bool defaultValue)
|
|
||||||
{
|
|
||||||
var valueToken = cursor.Value(property) as JsonBoolean;
|
|
||||||
if (valueToken == null)
|
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return valueToken.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int ReadInt(JsonObject cursor, string property, int defaultValue)
|
|
||||||
{
|
|
||||||
var number = cursor.Value(property) as JsonNumber;
|
|
||||||
if (number == null)
|
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var resultInInt = Convert.ToInt32(number.Raw);
|
|
||||||
return resultInInt;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// FormatException or OverflowException
|
|
||||||
throw FileFormatException.Create(ex, cursor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ReadString(JsonValue json)
|
|
||||||
{
|
|
||||||
if (json is JsonString)
|
|
||||||
{
|
|
||||||
return (json as JsonString).Value;
|
|
||||||
}
|
|
||||||
else if (json is JsonNull)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("The value type is not string.", json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal static class NamedResourceReader
|
|
||||||
{
|
|
||||||
public static IDictionary<string, string> ReadNamedResources(JsonObject rawProject, string projectFilePath)
|
|
||||||
{
|
|
||||||
if (!rawProject.Keys.Contains("namedResource"))
|
|
||||||
{
|
|
||||||
return new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var namedResourceToken = rawProject.ValueAsJsonObject("namedResource");
|
|
||||||
if (namedResourceToken == null)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("Value must be object.", rawProject.Value("namedResource"), projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var namedResources = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (var namedResourceKey in namedResourceToken.Keys)
|
|
||||||
{
|
|
||||||
var resourcePath = namedResourceToken.ValueAsString(namedResourceKey);
|
|
||||||
if (resourcePath == null)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("Value must be string.", namedResourceToken.Value(namedResourceKey), projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resourcePath.Value.Contains("*"))
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create("Value cannot contain wildcards.", resourcePath, projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var resourceFileFullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath));
|
|
||||||
|
|
||||||
if (namedResources.ContainsKey(namedResourceKey))
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create(
|
|
||||||
string.Format("The named resource {0} already exists.", namedResourceKey),
|
|
||||||
resourcePath,
|
|
||||||
projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
namedResources.Add(
|
|
||||||
namedResourceKey,
|
|
||||||
resourceFileFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return namedResources;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ApplyNamedResources(IDictionary<string, string> namedResources, IDictionary<string, string> resources)
|
|
||||||
{
|
|
||||||
foreach (var namedResource in namedResources)
|
|
||||||
{
|
|
||||||
// The named resources dictionary is like the project file
|
|
||||||
// key = name, value = path to resource
|
|
||||||
if (resources.ContainsKey(namedResource.Value))
|
|
||||||
{
|
|
||||||
resources[namedResource.Value] = namedResource.Key;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resources.Add(namedResource.Value, namedResource.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class PackIncludeEntry
|
|
||||||
{
|
|
||||||
public string Target { get; }
|
|
||||||
public string[] SourceGlobs { get; }
|
|
||||||
public int Line { get; }
|
|
||||||
public int Column { get; }
|
|
||||||
|
|
||||||
internal PackIncludeEntry(string target, JsonValue json)
|
|
||||||
: this(target, ExtractValues(json), json.Line, json.Column)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public PackIncludeEntry(string target, string[] sourceGlobs, int line, int column)
|
|
||||||
{
|
|
||||||
Target = target;
|
|
||||||
SourceGlobs = sourceGlobs;
|
|
||||||
Line = line;
|
|
||||||
Column = column;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] ExtractValues(JsonValue json)
|
|
||||||
{
|
|
||||||
var valueAsString = json as JsonString;
|
|
||||||
if (valueAsString != null)
|
|
||||||
{
|
|
||||||
return new string[] { valueAsString.Value };
|
|
||||||
}
|
|
||||||
|
|
||||||
var valueAsArray = json as JsonArray;
|
|
||||||
if(valueAsArray != null)
|
|
||||||
{
|
|
||||||
return valueAsArray.Values.Select(v => v.ToString()).ToArray();
|
|
||||||
}
|
|
||||||
return new string[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,196 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace NuGet
|
|
||||||
{
|
|
||||||
internal static class PathUtility
|
|
||||||
{
|
|
||||||
public static bool IsChildOfDirectory(string dir, string candidate)
|
|
||||||
{
|
|
||||||
if (dir == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(dir));
|
|
||||||
}
|
|
||||||
if (candidate == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(candidate));
|
|
||||||
}
|
|
||||||
dir = Path.GetFullPath(dir);
|
|
||||||
dir = EnsureTrailingSlash(dir);
|
|
||||||
candidate = Path.GetFullPath(candidate);
|
|
||||||
return candidate.StartsWith(dir, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string EnsureTrailingSlash(string path)
|
|
||||||
{
|
|
||||||
return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string EnsureTrailingForwardSlash(string path)
|
|
||||||
{
|
|
||||||
return EnsureTrailingCharacter(path, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string EnsureTrailingCharacter(string path, char trailingCharacter)
|
|
||||||
{
|
|
||||||
if (path == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the path is empty, we want to return the original string instead of a single trailing character.
|
|
||||||
if (path.Length == 0 || path[path.Length - 1] == trailingCharacter)
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path + trailingCharacter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EnsureParentDirectory(string filePath)
|
|
||||||
{
|
|
||||||
string directory = Path.GetDirectoryName(filePath);
|
|
||||||
if (!Directory.Exists(directory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns path2 relative to path1, with Path.DirectorySeparatorChar as separator
|
|
||||||
/// </summary>
|
|
||||||
public static string GetRelativePath(string path1, string path2)
|
|
||||||
{
|
|
||||||
return GetRelativePath(path1, path2, Path.DirectorySeparatorChar);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns path2 relative to path1, with given path separator
|
|
||||||
/// </summary>
|
|
||||||
public static string GetRelativePath(string path1, string path2, char separator)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path1))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Path must have a value", nameof(path1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(path2))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Path must have a value", nameof(path2));
|
|
||||||
}
|
|
||||||
|
|
||||||
StringComparison compare;
|
|
||||||
if (Microsoft.Dnx.Runtime.RuntimeEnvironmentHelper.IsWindows)
|
|
||||||
{
|
|
||||||
compare = StringComparison.OrdinalIgnoreCase;
|
|
||||||
// check if paths are on the same volume
|
|
||||||
if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2)))
|
|
||||||
{
|
|
||||||
// on different volumes, "relative" path is just path2
|
|
||||||
return path2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compare = StringComparison.Ordinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
var index = 0;
|
|
||||||
var path1Segments = path1.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
||||||
var path2Segments = path2.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
||||||
// if path1 does not end with / it is assumed the end is not a directory
|
|
||||||
// we will assume that is isn't a directory by ignoring the last split
|
|
||||||
var len1 = path1Segments.Length - 1;
|
|
||||||
var len2 = path2Segments.Length;
|
|
||||||
|
|
||||||
// find largest common absolute path between both paths
|
|
||||||
var min = Math.Min(len1, len2);
|
|
||||||
while (min > index)
|
|
||||||
{
|
|
||||||
if (!string.Equals(path1Segments[index], path2Segments[index], compare))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Handle scenarios where folder and file have same name (only if os supports same name for file and directory)
|
|
||||||
// e.g. /file/name /file/name/app
|
|
||||||
else if ((len1 == index && len2 > index + 1) || (len1 > index && len2 == index + 1))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
|
|
||||||
var path = "";
|
|
||||||
|
|
||||||
// check if path2 ends with a non-directory separator and if path1 has the same non-directory at the end
|
|
||||||
if (len1 + 1 == len2 && !string.IsNullOrEmpty(path1Segments[index]) &&
|
|
||||||
string.Equals(path1Segments[index], path2Segments[index], compare))
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = index; len1 > i; ++i)
|
|
||||||
{
|
|
||||||
path += ".." + separator;
|
|
||||||
}
|
|
||||||
for (var i = index; len2 - 1 > i; ++i)
|
|
||||||
{
|
|
||||||
path += path2Segments[i] + separator;
|
|
||||||
}
|
|
||||||
// if path2 doesn't end with an empty string it means it ended with a non-directory name, so we add it back
|
|
||||||
if (!string.IsNullOrEmpty(path2Segments[len2 - 1]))
|
|
||||||
{
|
|
||||||
path += path2Segments[len2 - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetAbsolutePath(string basePath, string relativePath)
|
|
||||||
{
|
|
||||||
if (basePath == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(basePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (relativePath == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(relativePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri resultUri = new Uri(new Uri(basePath), new Uri(relativePath, UriKind.Relative));
|
|
||||||
return resultUri.LocalPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDirectoryName(string path)
|
|
||||||
{
|
|
||||||
path = path.TrimEnd(Path.DirectorySeparatorChar);
|
|
||||||
return path.Substring(Path.GetDirectoryName(path).Length).Trim(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetPathWithForwardSlashes(string path)
|
|
||||||
{
|
|
||||||
return path.Replace('\\', '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetPathWithBackSlashes(string path)
|
|
||||||
{
|
|
||||||
return path.Replace('/', '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetPathWithDirectorySeparator(string path)
|
|
||||||
{
|
|
||||||
if (Path.DirectorySeparatorChar == '/')
|
|
||||||
{
|
|
||||||
return GetPathWithForwardSlashes(path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return GetPathWithBackSlashes(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
|
||||||
using Microsoft.Extensions.FileSystemGlobbing;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class PatternGroup
|
|
||||||
{
|
|
||||||
private readonly List<PatternGroup> _excludeGroups = new List<PatternGroup>();
|
|
||||||
private readonly Matcher _matcher = new Matcher();
|
|
||||||
|
|
||||||
internal PatternGroup(IEnumerable<string> includePatterns)
|
|
||||||
{
|
|
||||||
IncludeLiterals = Enumerable.Empty<string>();
|
|
||||||
IncludePatterns = includePatterns;
|
|
||||||
ExcludePatterns = Enumerable.Empty<string>();
|
|
||||||
_matcher.AddIncludePatterns(IncludePatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup(IEnumerable<string> includePatterns, IEnumerable<string> excludePatterns, IEnumerable<string> includeLiterals)
|
|
||||||
{
|
|
||||||
IncludeLiterals = includeLiterals;
|
|
||||||
IncludePatterns = includePatterns;
|
|
||||||
ExcludePatterns = excludePatterns;
|
|
||||||
|
|
||||||
_matcher.AddIncludePatterns(IncludePatterns);
|
|
||||||
_matcher.AddExcludePatterns(ExcludePatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static PatternGroup Build(
|
|
||||||
JsonObject rawProject,
|
|
||||||
string projectDirectory,
|
|
||||||
string projectFilePath,
|
|
||||||
string name,
|
|
||||||
IEnumerable<string> fallbackIncluding = null,
|
|
||||||
IEnumerable<string> additionalIncluding = null,
|
|
||||||
IEnumerable<string> additionalExcluding = null,
|
|
||||||
bool includePatternsOnly = false,
|
|
||||||
ICollection<DiagnosticMessage> warnings = null)
|
|
||||||
{
|
|
||||||
string includePropertyName = name;
|
|
||||||
additionalIncluding = additionalIncluding ?? Enumerable.Empty<string>();
|
|
||||||
var includePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, includePropertyName, defaultPatterns: fallbackIncluding)
|
|
||||||
.Concat(additionalIncluding)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
if (includePatternsOnly)
|
|
||||||
{
|
|
||||||
return new PatternGroup(includePatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
additionalExcluding = additionalExcluding ?? Enumerable.Empty<string>();
|
|
||||||
var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Exclude")
|
|
||||||
.Concat(additionalExcluding)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
var includeLiterals = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Files", literalPath: true)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
return new PatternGroup(includePatterns, excludePatterns, includeLiterals);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> IncludeLiterals { get; }
|
|
||||||
|
|
||||||
public IEnumerable<string> IncludePatterns { get; }
|
|
||||||
|
|
||||||
public IEnumerable<string> ExcludePatterns { get; }
|
|
||||||
|
|
||||||
public IEnumerable<PatternGroup> ExcludePatternsGroup { get { return _excludeGroups; } }
|
|
||||||
|
|
||||||
public PatternGroup ExcludeGroup(PatternGroup group)
|
|
||||||
{
|
|
||||||
_excludeGroups.Add(group);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> SearchFiles(string rootPath)
|
|
||||||
{
|
|
||||||
// literal included files are added at the last, but the search happens early
|
|
||||||
// so as to make the process fail early in case there is missing file. fail early
|
|
||||||
// helps to avoid unnecessary globing for performance optimization
|
|
||||||
var literalIncludedFiles = new List<string>();
|
|
||||||
foreach (var literalRelativePath in IncludeLiterals)
|
|
||||||
{
|
|
||||||
var fullPath = Path.GetFullPath(Path.Combine(rootPath, literalRelativePath));
|
|
||||||
|
|
||||||
if (!File.Exists(fullPath))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: extract utility like NuGet.PathUtility.GetPathWithForwardSlashes()
|
|
||||||
literalIncludedFiles.Add(fullPath.Replace('\\', '/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// globing files
|
|
||||||
var globbingResults = _matcher.GetResultsInFullPath(rootPath);
|
|
||||||
|
|
||||||
// if there is no results generated in globing, skip excluding other groups
|
|
||||||
// for performance optimization.
|
|
||||||
if (globbingResults.Any())
|
|
||||||
{
|
|
||||||
foreach (var group in _excludeGroups)
|
|
||||||
{
|
|
||||||
globbingResults = globbingResults.Except(group.SearchFiles(rootPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return globbingResults.Concat(literalIncludedFiles).Distinct();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format("Pattern group: Literals [{0}] Includes [{1}] Excludes [{2}]", string.Join(", ", IncludeLiterals), string.Join(", ", IncludePatterns), string.Join(", ", ExcludePatterns));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal static class PatternsCollectionHelper
|
|
||||||
{
|
|
||||||
private static readonly char[] PatternSeparator = new[] { ';' };
|
|
||||||
|
|
||||||
public static IEnumerable<string> GetPatternsCollection(
|
|
||||||
JsonObject rawProject,
|
|
||||||
string projectDirectory,
|
|
||||||
string projectFilePath,
|
|
||||||
string propertyName,
|
|
||||||
IEnumerable<string> defaultPatterns = null,
|
|
||||||
bool literalPath = false)
|
|
||||||
{
|
|
||||||
defaultPatterns = defaultPatterns ?? Enumerable.Empty<string>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!rawProject.Keys.Contains(propertyName))
|
|
||||||
{
|
|
||||||
return CreateCollection(projectDirectory, propertyName, defaultPatterns, literalPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var valueInString = rawProject.ValueAsString(propertyName);
|
|
||||||
if (valueInString != null)
|
|
||||||
{
|
|
||||||
return CreateCollection(projectDirectory, propertyName, new string[] { valueInString }, literalPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var valuesInArray = rawProject.ValueAsStringArray(propertyName);
|
|
||||||
if (valuesInArray != null)
|
|
||||||
{
|
|
||||||
return CreateCollection(projectDirectory, propertyName, valuesInArray.Select(s => s.ToString()), literalPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create(ex, rawProject.Value(propertyName), projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw FileFormatException.Create("Value must be either string or array.", rawProject.Value(propertyName), projectFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> CreateCollection(string projectDirectory, string propertyName, IEnumerable<string> patternsStrings, bool literalPath)
|
|
||||||
{
|
|
||||||
var patterns = patternsStrings.SelectMany(patternsString => GetSourcesSplit(patternsString))
|
|
||||||
.Select(patternString => patternString.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar));
|
|
||||||
|
|
||||||
foreach (var pattern in patterns)
|
|
||||||
{
|
|
||||||
if (Path.IsPathRooted(pattern))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The '{propertyName}' property cannot be a rooted path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (literalPath && pattern.Contains('*'))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The '{propertyName}' property cannot contain wildcard characters.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new List<string>(patterns.Select(pattern => FolderToPattern(pattern, projectDirectory)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GetSourcesSplit(string sourceDescription)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(sourceDescription))
|
|
||||||
{
|
|
||||||
return Enumerable.Empty<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sourceDescription.Split(PatternSeparator, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string FolderToPattern(string candidate, string projectDir)
|
|
||||||
{
|
|
||||||
// This conversion is needed to support current template
|
|
||||||
|
|
||||||
// If it's already a pattern, no change is needed
|
|
||||||
if (candidate.Contains('*'))
|
|
||||||
{
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the given string ends with a path separator, or it is an existing directory
|
|
||||||
// we convert this folder name to a pattern matching all files in the folder
|
|
||||||
if (candidate.EndsWith(@"\") ||
|
|
||||||
candidate.EndsWith("/") ||
|
|
||||||
Directory.Exists(Path.Combine(projectDir, candidate)))
|
|
||||||
{
|
|
||||||
return Path.Combine(candidate, "**", "*");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, it represents a single file
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
|
||||||
using NuGet;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class Project
|
|
||||||
{
|
|
||||||
public const string ProjectFileName = "project.json";
|
|
||||||
|
|
||||||
public Project()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ProjectFilePath { get; set; }
|
|
||||||
|
|
||||||
public string ProjectDirectory
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Path.GetDirectoryName(ProjectFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
public string Copyright { get; set; }
|
|
||||||
|
|
||||||
public string Summary { get; set; }
|
|
||||||
|
|
||||||
public string Language { get; set; }
|
|
||||||
|
|
||||||
public string ReleaseNotes { get; set; }
|
|
||||||
|
|
||||||
public string[] Authors { get; set; }
|
|
||||||
|
|
||||||
public string[] Owners { get; set; }
|
|
||||||
|
|
||||||
public bool EmbedInteropTypes { get; set; }
|
|
||||||
|
|
||||||
public Version AssemblyFileVersion { get; set; }
|
|
||||||
public string WebRoot { get; set; }
|
|
||||||
|
|
||||||
public string EntryPoint { get; set; }
|
|
||||||
|
|
||||||
public string ProjectUrl { get; set; }
|
|
||||||
|
|
||||||
public string LicenseUrl { get; set; }
|
|
||||||
|
|
||||||
public string IconUrl { get; set; }
|
|
||||||
|
|
||||||
public bool RequireLicenseAcceptance { get; set; }
|
|
||||||
|
|
||||||
public string[] Tags { get; set; }
|
|
||||||
|
|
||||||
public bool IsLoadable { get; set; }
|
|
||||||
|
|
||||||
public ProjectFilesCollection Files { get; set; }
|
|
||||||
|
|
||||||
public IDictionary<string, string> Commands { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public IDictionary<string, IEnumerable<string>> Scripts { get; } = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public static bool HasProjectFile(string path)
|
|
||||||
{
|
|
||||||
string projectPath = Path.Combine(path, ProjectFileName);
|
|
||||||
|
|
||||||
return File.Exists(projectPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetProject(string path, out Project project, ICollection<DiagnosticMessage> diagnostics = null)
|
|
||||||
{
|
|
||||||
project = null;
|
|
||||||
|
|
||||||
string projectPath = null;
|
|
||||||
|
|
||||||
if (string.Equals(Path.GetFileName(path), ProjectFileName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
projectPath = path;
|
|
||||||
path = Path.GetDirectoryName(path);
|
|
||||||
}
|
|
||||||
else if (!HasProjectFile(path))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
projectPath = Path.Combine(path, ProjectFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assume the directory name is the project name if none was specified
|
|
||||||
var projectName = PathUtility.GetDirectoryName(path);
|
|
||||||
projectPath = Path.GetFullPath(projectPath);
|
|
||||||
|
|
||||||
if (!File.Exists(projectPath))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var stream = File.OpenRead(projectPath))
|
|
||||||
{
|
|
||||||
var reader = new ProjectReader();
|
|
||||||
project = reader.ReadProject(stream, projectName, projectPath, diagnostics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create(ex, projectPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class ProjectFilesCollection
|
|
||||||
{
|
|
||||||
public static readonly string[] DefaultCompileBuiltInPatterns = new[] { @"**/*.cs" };
|
|
||||||
public static readonly string[] DefaultPublishExcludePatterns = new[] { @"obj/**/*.*", @"bin/**/*.*", @"**/.*/**", @"**/global.json" };
|
|
||||||
public static readonly string[] DefaultPreprocessPatterns = new[] { @"compiler/preprocess/**/*.cs" };
|
|
||||||
public static readonly string[] DefaultSharedPatterns = new[] { @"compiler/shared/**/*.cs" };
|
|
||||||
public static readonly string[] DefaultResourcesBuiltInPatterns = new[] { @"compiler/resources/**/*", "**/*.resx" };
|
|
||||||
public static readonly string[] DefaultContentsBuiltInPatterns = new[] { @"**/*" };
|
|
||||||
|
|
||||||
public static readonly string[] DefaultBuiltInExcludePatterns = new[] { "bin/**", "obj/**", "**/*.xproj" };
|
|
||||||
|
|
||||||
public static readonly string PackIncludePropertyName = "packInclude";
|
|
||||||
|
|
||||||
private PatternGroup _sharedPatternsGroup;
|
|
||||||
private PatternGroup _resourcePatternsGroup;
|
|
||||||
private PatternGroup _preprocessPatternsGroup;
|
|
||||||
private PatternGroup _compilePatternsGroup;
|
|
||||||
private PatternGroup _contentPatternsGroup;
|
|
||||||
private IDictionary<string, string> _namedResources;
|
|
||||||
private IEnumerable<string> _publishExcludePatterns;
|
|
||||||
private IEnumerable<PackIncludeEntry> _packInclude;
|
|
||||||
|
|
||||||
private readonly string _projectDirectory;
|
|
||||||
private readonly string _projectFilePath;
|
|
||||||
|
|
||||||
private JsonObject _rawProject;
|
|
||||||
private bool _initialized;
|
|
||||||
|
|
||||||
internal ProjectFilesCollection(JsonObject rawProject, string projectDirectory, string projectFilePath)
|
|
||||||
{
|
|
||||||
_projectDirectory = projectDirectory;
|
|
||||||
_projectFilePath = projectFilePath;
|
|
||||||
_rawProject = rawProject;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void EnsureInitialized()
|
|
||||||
{
|
|
||||||
if (_initialized)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var excludeBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "excludeBuiltIn", DefaultBuiltInExcludePatterns);
|
|
||||||
var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "exclude")
|
|
||||||
.Concat(excludeBuiltIns);
|
|
||||||
var contentBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "contentBuiltIn", DefaultContentsBuiltInPatterns);
|
|
||||||
var compileBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "compileBuiltIn", DefaultCompileBuiltInPatterns);
|
|
||||||
var resourceBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "resourceBuiltIn", DefaultResourcesBuiltInPatterns);
|
|
||||||
|
|
||||||
_publishExcludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "publishExclude", DefaultPublishExcludePatterns);
|
|
||||||
|
|
||||||
_sharedPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "shared", fallbackIncluding: DefaultSharedPatterns, additionalExcluding: excludePatterns);
|
|
||||||
|
|
||||||
_resourcePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "resource", additionalIncluding: resourceBuiltIns, additionalExcluding: excludePatterns);
|
|
||||||
|
|
||||||
_preprocessPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "preprocess", fallbackIncluding: DefaultPreprocessPatterns, additionalExcluding: excludePatterns)
|
|
||||||
.ExcludeGroup(_sharedPatternsGroup)
|
|
||||||
.ExcludeGroup(_resourcePatternsGroup);
|
|
||||||
|
|
||||||
_compilePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "compile", additionalIncluding: compileBuiltIns, additionalExcluding: excludePatterns)
|
|
||||||
.ExcludeGroup(_sharedPatternsGroup)
|
|
||||||
.ExcludeGroup(_preprocessPatternsGroup)
|
|
||||||
.ExcludeGroup(_resourcePatternsGroup);
|
|
||||||
|
|
||||||
_contentPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "content", additionalIncluding: contentBuiltIns, additionalExcluding: excludePatterns.Concat(_publishExcludePatterns))
|
|
||||||
.ExcludeGroup(_compilePatternsGroup)
|
|
||||||
.ExcludeGroup(_preprocessPatternsGroup)
|
|
||||||
.ExcludeGroup(_sharedPatternsGroup)
|
|
||||||
.ExcludeGroup(_resourcePatternsGroup);
|
|
||||||
|
|
||||||
_namedResources = NamedResourceReader.ReadNamedResources(_rawProject, _projectFilePath);
|
|
||||||
|
|
||||||
// Files to be packed along with the project
|
|
||||||
var packIncludeJson = _rawProject.ValueAsJsonObject(PackIncludePropertyName);
|
|
||||||
if (packIncludeJson != null)
|
|
||||||
{
|
|
||||||
_packInclude = packIncludeJson
|
|
||||||
.Keys
|
|
||||||
.Select(k => new PackIncludeEntry(k, packIncludeJson.Value(k)))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_packInclude = new List<PackIncludeEntry>();
|
|
||||||
}
|
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
_rawProject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<PackIncludeEntry> PackInclude
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _packInclude;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> SourceFiles
|
|
||||||
{
|
|
||||||
get { return CompilePatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> PreprocessSourceFiles
|
|
||||||
{
|
|
||||||
get { return PreprocessPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDictionary<string, string> ResourceFiles
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var resources = ResourcePatternsGroup
|
|
||||||
.SearchFiles(_projectDirectory)
|
|
||||||
.Distinct()
|
|
||||||
.ToDictionary(res => res, res => (string)null);
|
|
||||||
|
|
||||||
NamedResourceReader.ApplyNamedResources(_namedResources, resources);
|
|
||||||
|
|
||||||
return resources;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> SharedFiles
|
|
||||||
{
|
|
||||||
get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> GetFilesForBundling(bool includeSource, IEnumerable<string> additionalExcludePatterns)
|
|
||||||
{
|
|
||||||
var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns,
|
|
||||||
ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns),
|
|
||||||
ContentPatternsGroup.IncludeLiterals);
|
|
||||||
if (!includeSource)
|
|
||||||
{
|
|
||||||
foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup)
|
|
||||||
{
|
|
||||||
patternGroup.ExcludeGroup(excludedGroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return patternGroup.SearchFiles(_projectDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup CompilePatternsGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _compilePatternsGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup SharedPatternsGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _sharedPatternsGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup ResourcePatternsGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _resourcePatternsGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup PreprocessPatternsGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _preprocessPatternsGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PatternGroup ContentPatternsGroup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureInitialized();
|
|
||||||
return _contentPatternsGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
|
||||||
using Microsoft.Extensions.JsonParser.Sources;
|
|
||||||
using NuGet;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
public class ProjectReader
|
|
||||||
{
|
|
||||||
public Project ReadProject(Stream stream, string projectName, string projectPath, ICollection<DiagnosticMessage> diagnostics)
|
|
||||||
{
|
|
||||||
var project = new Project();
|
|
||||||
|
|
||||||
var reader = new StreamReader(stream);
|
|
||||||
var rawProject = JsonDeserializer.Deserialize(reader) as JsonObject;
|
|
||||||
if (rawProject == null)
|
|
||||||
{
|
|
||||||
throw FileFormatException.Create(
|
|
||||||
"The JSON file can't be deserialized to a JSON object.",
|
|
||||||
projectPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Meta-data properties
|
|
||||||
project.Name = projectName;
|
|
||||||
project.ProjectFilePath = Path.GetFullPath(projectPath);
|
|
||||||
|
|
||||||
var version = rawProject.Value("version") as JsonString;
|
|
||||||
|
|
||||||
project.Description = rawProject.ValueAsString("description");
|
|
||||||
project.Summary = rawProject.ValueAsString("summary");
|
|
||||||
project.Copyright = rawProject.ValueAsString("copyright");
|
|
||||||
project.Title = rawProject.ValueAsString("title");
|
|
||||||
project.WebRoot = rawProject.ValueAsString("webroot");
|
|
||||||
project.EntryPoint = rawProject.ValueAsString("entryPoint");
|
|
||||||
project.ProjectUrl = rawProject.ValueAsString("projectUrl");
|
|
||||||
project.LicenseUrl = rawProject.ValueAsString("licenseUrl");
|
|
||||||
project.IconUrl = rawProject.ValueAsString("iconUrl");
|
|
||||||
|
|
||||||
project.Authors = rawProject.ValueAsStringArray("authors") ?? new string[] { };
|
|
||||||
project.Owners = rawProject.ValueAsStringArray("owners") ?? new string[] { };
|
|
||||||
project.Tags = rawProject.ValueAsStringArray("tags") ?? new string[] { };
|
|
||||||
|
|
||||||
project.Language = rawProject.ValueAsString("language");
|
|
||||||
project.ReleaseNotes = rawProject.ValueAsString("releaseNotes");
|
|
||||||
|
|
||||||
project.RequireLicenseAcceptance = rawProject.ValueAsBoolean("requireLicenseAcceptance", defaultValue: false);
|
|
||||||
project.IsLoadable = rawProject.ValueAsBoolean("loadable", defaultValue: true);
|
|
||||||
// TODO: Move this to the dependencies node
|
|
||||||
project.EmbedInteropTypes = rawProject.ValueAsBoolean("embedInteropTypes", defaultValue: false);
|
|
||||||
|
|
||||||
// Project files
|
|
||||||
project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath);
|
|
||||||
|
|
||||||
var commands = rawProject.Value("commands") as JsonObject;
|
|
||||||
if (commands != null)
|
|
||||||
{
|
|
||||||
foreach (var key in commands.Keys)
|
|
||||||
{
|
|
||||||
var value = commands.ValueAsString(key);
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
project.Commands[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var scripts = rawProject.Value("scripts") as JsonObject;
|
|
||||||
if (scripts != null)
|
|
||||||
{
|
|
||||||
foreach (var key in scripts.Keys)
|
|
||||||
{
|
|
||||||
var stringValue = scripts.ValueAsString(key);
|
|
||||||
if (stringValue != null)
|
|
||||||
{
|
|
||||||
project.Scripts[key] = new string[] { stringValue };
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var arrayValue = scripts.ValueAsStringArray(key);
|
|
||||||
if (arrayValue != null)
|
|
||||||
{
|
|
||||||
project.Scripts[key] = arrayValue;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw FileFormatException.Create(
|
|
||||||
string.Format("The value of a script in {0} can only be a string or an array of strings", Project.ProjectFileName),
|
|
||||||
scripts.Value(key),
|
|
||||||
project.ProjectFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return project;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SemanticVersion SpecifySnapshot(string version, string snapshotValue)
|
|
||||||
{
|
|
||||||
if (version.EndsWith("-*"))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(snapshotValue))
|
|
||||||
{
|
|
||||||
version = version.Substring(0, version.Length - 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
version = version.Substring(0, version.Length - 1) + snapshotValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SemanticVersion(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryGetStringEnumerable(JsonObject parent, string property, out IEnumerable<string> result)
|
|
||||||
{
|
|
||||||
var collection = new List<string>();
|
|
||||||
var valueInString = parent.ValueAsString(property);
|
|
||||||
if (valueInString != null)
|
|
||||||
{
|
|
||||||
collection.Add(valueInString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var valueInArray = parent.ValueAsStringArray(property);
|
|
||||||
if (valueInArray != null)
|
|
||||||
{
|
|
||||||
collection.AddRange(valueInArray);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = collection.SelectMany(value => value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Runtime
|
|
||||||
{
|
|
||||||
internal static class RuntimeEnvironmentHelper
|
|
||||||
{
|
|
||||||
private static Lazy<bool> _isMono = new Lazy<bool>(() =>
|
|
||||||
_runtimeEnv.Value.RuntimeType == "Mono");
|
|
||||||
|
|
||||||
private static Lazy<bool> _isWindows = new Lazy<bool>(() =>
|
|
||||||
_runtimeEnv.Value.OperatingSystem == "Windows");
|
|
||||||
|
|
||||||
private static Lazy<IRuntimeEnvironment> _runtimeEnv = new Lazy<IRuntimeEnvironment>(() =>
|
|
||||||
GetRuntimeEnvironment());
|
|
||||||
|
|
||||||
private static IRuntimeEnvironment GetRuntimeEnvironment()
|
|
||||||
{
|
|
||||||
var environment = PlatformServices.Default.Runtime;
|
|
||||||
|
|
||||||
if (environment == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Failed to resolve IRuntimeEnvironment");
|
|
||||||
}
|
|
||||||
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IRuntimeEnvironment RuntimeEnvironment
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _runtimeEnv.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsWindows
|
|
||||||
{
|
|
||||||
get { return _isWindows.Value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsMono
|
|
||||||
{
|
|
||||||
get { return _isMono.Value; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,330 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NuGet
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A hybrid implementation of SemVer that supports semantic versioning as described at http://semver.org while not strictly enforcing it to
|
|
||||||
/// allow older 4-digit versioning schemes to continue working.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class SemanticVersion : IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>
|
|
||||||
{
|
|
||||||
private string _normalizedVersionString;
|
|
||||||
|
|
||||||
public SemanticVersion(string version)
|
|
||||||
: this(Parse(version))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, int revision)
|
|
||||||
: this(new Version(major, minor, build, revision))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(int major, int minor, int build, string specialVersion)
|
|
||||||
: this(new Version(major, minor, build), specialVersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version)
|
|
||||||
: this(version, string.Empty)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SemanticVersion(Version version, string specialVersion)
|
|
||||||
{
|
|
||||||
if (version == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(version));
|
|
||||||
}
|
|
||||||
Version = NormalizeVersionValue(version);
|
|
||||||
SpecialVersion = specialVersion ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SemanticVersion(SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
Version = semVer.Version;
|
|
||||||
SpecialVersion = semVer.SpecialVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the normalized version portion.
|
|
||||||
/// </summary>
|
|
||||||
public Version Version
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public string SpecialVersion
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] SplitAndPadVersionString(string version)
|
|
||||||
{
|
|
||||||
string[] a = version.Split('.');
|
|
||||||
if (a.Length == 4)
|
|
||||||
{
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if 'a' has less than 4 elements, we pad the '0' at the end
|
|
||||||
// to make it 4.
|
|
||||||
var b = new string[4] { "0", "0", "0", "0" };
|
|
||||||
Array.Copy(a, 0, b, 0, a.Length);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static SemanticVersion Parse(string version)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(version));
|
|
||||||
}
|
|
||||||
|
|
||||||
SemanticVersion semVer;
|
|
||||||
if (!TryParse(version, out semVer))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(nameof(version));
|
|
||||||
}
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParse(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, strict: false, semVer: out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a version string using strict semantic versioning rules that allows exactly 3 components and an optional special version.
|
|
||||||
/// </summary>
|
|
||||||
public static bool TryParseStrict(string version, out SemanticVersion value)
|
|
||||||
{
|
|
||||||
return TryParseInternal(version, strict: true, semVer: out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryParseInternal(string version, bool strict, out SemanticVersion semVer)
|
|
||||||
{
|
|
||||||
semVer = null;
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
version = version.Trim();
|
|
||||||
var versionPart = version;
|
|
||||||
|
|
||||||
string specialVersion = string.Empty;
|
|
||||||
if (version.IndexOf('-') != -1)
|
|
||||||
{
|
|
||||||
var parts = version.Split(new char[] { '-' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (parts.Length != 2)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
versionPart = parts[0];
|
|
||||||
specialVersion = parts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Version versionValue;
|
|
||||||
if (!Version.TryParse(versionPart, out versionValue))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strict)
|
|
||||||
{
|
|
||||||
// Must have major, minor and build only.
|
|
||||||
if (versionValue.Major == -1 ||
|
|
||||||
versionValue.Minor == -1 ||
|
|
||||||
versionValue.Build == -1 ||
|
|
||||||
versionValue.Revision != -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
semVer = new SemanticVersion(NormalizeVersionValue(versionValue), specialVersion);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to parse the version token as a SemanticVersion.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An instance of SemanticVersion if it parses correctly, null otherwise.</returns>
|
|
||||||
public static SemanticVersion ParseOptionalVersion(string version)
|
|
||||||
{
|
|
||||||
SemanticVersion semVer;
|
|
||||||
TryParse(version, out semVer);
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Version NormalizeVersionValue(Version version)
|
|
||||||
{
|
|
||||||
return new Version(version.Major,
|
|
||||||
version.Minor,
|
|
||||||
Math.Max(version.Build, 0),
|
|
||||||
Math.Max(version.Revision, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(object obj)
|
|
||||||
{
|
|
||||||
if (Object.ReferenceEquals(obj, null))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
SemanticVersion other = obj as SemanticVersion;
|
|
||||||
if (other == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(nameof(obj));
|
|
||||||
}
|
|
||||||
return CompareTo(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(SemanticVersion other)
|
|
||||||
{
|
|
||||||
if (Object.ReferenceEquals(other, null))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = Version.CompareTo(other.Version);
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty = string.IsNullOrEmpty(SpecialVersion);
|
|
||||||
bool otherEmpty = string.IsNullOrEmpty(other.SpecialVersion);
|
|
||||||
if (empty && otherEmpty)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (empty)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (otherEmpty)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return StringComparer.OrdinalIgnoreCase.Compare(SpecialVersion, other.SpecialVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (Object.ReferenceEquals(version1, null))
|
|
||||||
{
|
|
||||||
return Object.ReferenceEquals(version2, null);
|
|
||||||
}
|
|
||||||
return version1.Equals(version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return !(version1 == version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
}
|
|
||||||
return version1.CompareTo(version2) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return (version1 == version2) || (version1 < version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
if (version1 == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(version1));
|
|
||||||
}
|
|
||||||
return version2 < version1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(SemanticVersion version1, SemanticVersion version2)
|
|
||||||
{
|
|
||||||
return (version1 == version2) || (version1 > version2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (_normalizedVersionString == null)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
builder
|
|
||||||
.Append(Version.Major)
|
|
||||||
.Append('.')
|
|
||||||
.Append(Version.Minor)
|
|
||||||
.Append('.')
|
|
||||||
.Append(Math.Max(0, Version.Build));
|
|
||||||
|
|
||||||
if (Version.Revision > 0)
|
|
||||||
{
|
|
||||||
builder
|
|
||||||
.Append('.')
|
|
||||||
.Append(Version.Revision);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(SpecialVersion))
|
|
||||||
{
|
|
||||||
builder
|
|
||||||
.Append('-')
|
|
||||||
.Append(SpecialVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
_normalizedVersionString = builder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _normalizedVersionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(SemanticVersion other)
|
|
||||||
{
|
|
||||||
return !Object.ReferenceEquals(null, other) &&
|
|
||||||
Version.Equals(other.Version) &&
|
|
||||||
SpecialVersion.Equals(other.SpecialVersion, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
SemanticVersion semVer = obj as SemanticVersion;
|
|
||||||
return !Object.ReferenceEquals(null, semVer) && Equals(semVer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
int hashCode = Version.GetHashCode();
|
|
||||||
if (SpecialVersion != null)
|
|
||||||
{
|
|
||||||
hashCode = hashCode * 4567 + SpecialVersion.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
|
||||||
using Microsoft.Dnx.Watcher.Core;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
private const string DnxWatchArgumentSeparator = "--dnx-args";
|
|
||||||
|
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
|
||||||
|
|
||||||
public Program()
|
|
||||||
{
|
|
||||||
_loggerFactory = new LoggerFactory();
|
|
||||||
|
|
||||||
var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime);
|
|
||||||
_loggerFactory.AddProvider(commandProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
|
||||||
using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource())
|
|
||||||
{
|
|
||||||
Console.CancelKeyPress += (sender, ev) =>
|
|
||||||
{
|
|
||||||
ctrlCTokenSource.Cancel();
|
|
||||||
ev.Cancel = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
string[] watchArgs, dnxArgs;
|
|
||||||
SeparateWatchArguments(args, out watchArgs, out dnxArgs);
|
|
||||||
|
|
||||||
return new Program().MainInternal(watchArgs, dnxArgs, ctrlCTokenSource.Token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] dnxArgs)
|
|
||||||
{
|
|
||||||
int argsIndex = -1;
|
|
||||||
watchArgs = args.TakeWhile((arg, idx) =>
|
|
||||||
{
|
|
||||||
argsIndex = idx;
|
|
||||||
return !string.Equals(arg, DnxWatchArgumentSeparator, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}).ToArray();
|
|
||||||
|
|
||||||
dnxArgs = args.Skip(argsIndex + 1).ToArray();
|
|
||||||
|
|
||||||
if (dnxArgs.Length == 0)
|
|
||||||
{
|
|
||||||
// If no explicit dnx arguments then all arguments get passed to dnx
|
|
||||||
dnxArgs = watchArgs;
|
|
||||||
watchArgs = new string[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int MainInternal(string[] watchArgs, string[] dnxArgs, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var app = new CommandLineApplication();
|
|
||||||
app.Name = "dnx-watch";
|
|
||||||
app.FullName = "Microsoft .NET DNX File Watcher";
|
|
||||||
|
|
||||||
app.HelpOption("-?|-h|--help");
|
|
||||||
|
|
||||||
var projectArg = app.Option(
|
|
||||||
"--project <PATH>",
|
|
||||||
"Path to the project.json file or the application folder. Defaults to the current folder if not provided. Will be passed to DNX.",
|
|
||||||
CommandOptionType.SingleValue);
|
|
||||||
|
|
||||||
var workingDirArg = app.Option(
|
|
||||||
"--working-dir <DIR>",
|
|
||||||
"The working directory for DNX. Defaults to the current directory.",
|
|
||||||
CommandOptionType.SingleValue);
|
|
||||||
|
|
||||||
var exitOnChangeArg = app.Option(
|
|
||||||
"--exit-on-change",
|
|
||||||
"The watcher will exit when a file change is detected instead of restarting the process.",
|
|
||||||
CommandOptionType.NoValue);
|
|
||||||
|
|
||||||
// This option is here just to be displayed in help
|
|
||||||
// it will not be parsed because it is removed before the code is executed
|
|
||||||
app.Option(
|
|
||||||
$"{DnxWatchArgumentSeparator} <ARGS>",
|
|
||||||
"Marks the arguments that will be passed to DNX. Anything following this option is passed. If not specified, all the arguments are passed to DNX.",
|
|
||||||
CommandOptionType.SingleValue);
|
|
||||||
|
|
||||||
app.OnExecute(() =>
|
|
||||||
{
|
|
||||||
var projectToRun = projectArg.HasValue() ?
|
|
||||||
projectArg.Value() :
|
|
||||||
Directory.GetCurrentDirectory();
|
|
||||||
|
|
||||||
if (!projectToRun.EndsWith("project.json", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
projectToRun = Path.Combine(projectToRun, "project.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
var workingDir = workingDirArg.HasValue() ?
|
|
||||||
workingDirArg.Value() :
|
|
||||||
Directory.GetCurrentDirectory();
|
|
||||||
|
|
||||||
var watcher = DnxWatcher.CreateDefault(_loggerFactory);
|
|
||||||
watcher.ExitOnChange = exitOnChangeArg.HasValue();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
watcher.WatchAsync(projectToRun, dnxArgs, workingDir, cancellationToken).Wait();
|
|
||||||
}
|
|
||||||
catch (AggregateException ex)
|
|
||||||
{
|
|
||||||
if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException))
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
return app.Execute(watchArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Resources;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
[assembly:InternalsVisibleTo("Microsoft.Dnx.Watcher.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
|
||||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
|
||||||
[assembly: NeutralResourcesLanguage("en-US")]
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public interface IFileWatcher : IDisposable
|
public interface IFileWatcher : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public interface IProcessWatcher
|
public interface IProcessWatcher
|
||||||
{
|
{
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public interface IProject
|
public interface IProject
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public interface IProjectProvider
|
public interface IProjectProvider
|
||||||
{
|
{
|
||||||
|
|
@ -8,9 +8,9 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public class DnxWatcher
|
public class DotNetWatcher
|
||||||
{
|
{
|
||||||
private readonly Func<string, IFileWatcher> _fileWatcherFactory;
|
private readonly Func<string, IFileWatcher> _fileWatcherFactory;
|
||||||
private readonly Func<IProcessWatcher> _processWatcherFactory;
|
private readonly Func<IProcessWatcher> _processWatcherFactory;
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
|
|
||||||
public bool ExitOnChange { get; set; }
|
public bool ExitOnChange { get; set; }
|
||||||
|
|
||||||
public DnxWatcher(
|
public DotNetWatcher(
|
||||||
Func<string, IFileWatcher> fileWatcherFactory,
|
Func<string, IFileWatcher> fileWatcherFactory,
|
||||||
Func<IProcessWatcher> processWatcherFactory,
|
Func<IProcessWatcher> processWatcherFactory,
|
||||||
IProjectProvider projectProvider,
|
IProjectProvider projectProvider,
|
||||||
|
|
@ -32,12 +32,44 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
_projectProvider = projectProvider;
|
_projectProvider = projectProvider;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
|
|
||||||
_logger = _loggerFactory.CreateLogger(nameof(DnxWatcher));
|
_logger = _loggerFactory.CreateLogger(nameof(DotNetWatcher));
|
||||||
}
|
}
|
||||||
public async Task WatchAsync(string projectFile, string[] dnxArguments, string workingDir, CancellationToken cancellationToken)
|
|
||||||
|
public async Task WatchAsync(string projectFile, string command, string[] dotnetArguments, string workingDir, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
dnxArguments = new string[] { "--project", projectFile }
|
if (string.IsNullOrEmpty(projectFile))
|
||||||
.Concat(dnxArguments)
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectFile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(command))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(command));
|
||||||
|
}
|
||||||
|
if (dotnetArguments == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(dotnetArguments));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(workingDir))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(workingDir));
|
||||||
|
}
|
||||||
|
if (cancellationToken == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dotnetArguments.Length > 0)
|
||||||
|
{
|
||||||
|
dotnetArguments = new string[] { command, "--" }
|
||||||
|
.Concat(dotnetArguments)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dotnetArguments = new string[] { command };
|
||||||
|
}
|
||||||
|
|
||||||
|
dotnetArguments = dotnetArguments
|
||||||
.Select(arg =>
|
.Select(arg =>
|
||||||
{
|
{
|
||||||
// If the argument has spaces, make sure we quote it
|
// If the argument has spaces, make sure we quote it
|
||||||
|
|
@ -50,7 +82,7 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var dnxArgumentsAsString = string.Join(" ", dnxArguments);
|
var dotnetArgumentsAsString = string.Join(" ", dotnetArguments);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
@ -63,14 +95,14 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
currentRunCancellationSource.Token))
|
currentRunCancellationSource.Token))
|
||||||
{
|
{
|
||||||
var fileWatchingTask = WaitForProjectFileToChangeAsync(project, combinedCancellationSource.Token);
|
var fileWatchingTask = WaitForProjectFileToChangeAsync(project, combinedCancellationSource.Token);
|
||||||
var dnxTask = WaitForDnxToExitAsync(dnxArgumentsAsString, workingDir, combinedCancellationSource.Token);
|
var dotnetTask = WaitForDotnetToExitAsync(dotnetArgumentsAsString, workingDir, combinedCancellationSource.Token);
|
||||||
|
|
||||||
var tasksToWait = new Task[] { dnxTask, fileWatchingTask };
|
var tasksToWait = new Task[] { dotnetTask, fileWatchingTask };
|
||||||
|
|
||||||
int finishedTaskIndex = Task.WaitAny(tasksToWait, cancellationToken);
|
int finishedTaskIndex = Task.WaitAny(tasksToWait, cancellationToken);
|
||||||
|
|
||||||
// Regardless of the outcome, make sure everything is cancelled
|
// Regardless of the outcome, make sure everything is cancelled
|
||||||
// and wait for dnx to exit. We don't want orphan processes
|
// and wait for dotnet to exit. We don't want orphan processes
|
||||||
currentRunCancellationSource.Cancel();
|
currentRunCancellationSource.Cancel();
|
||||||
Task.WaitAll(tasksToWait);
|
Task.WaitAll(tasksToWait);
|
||||||
|
|
||||||
|
|
@ -78,16 +110,16 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
|
|
||||||
if (finishedTaskIndex == 0)
|
if (finishedTaskIndex == 0)
|
||||||
{
|
{
|
||||||
// This is the dnx task
|
// This is the dotnet task
|
||||||
var dnxExitCode = dnxTask.Result;
|
var dotnetExitCode = dotnetTask.Result;
|
||||||
|
|
||||||
if (dnxExitCode == 0)
|
if (dotnetExitCode == 0)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"dnx exit code: {dnxExitCode}");
|
_logger.LogInformation($"dotnet exit code: {dotnetExitCode}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError($"dnx exit code: {dnxExitCode}");
|
_logger.LogError($"dotnet exit code: {dotnetExitCode}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExitOnChange)
|
if (ExitOnChange)
|
||||||
|
|
@ -95,8 +127,8 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Waiting for a file to change before restarting dnx...");
|
_logger.LogInformation("Waiting for a file to change before restarting dotnet...");
|
||||||
// Now wait for a file to change before restarting dnx
|
// Now wait for a file to change before restarting dotnet
|
||||||
await WaitForProjectFileToChangeAsync(project, cancellationToken);
|
await WaitForProjectFileToChangeAsync(project, cancellationToken);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -123,15 +155,15 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<int> WaitForDnxToExitAsync(string dnxArguments, string workingDir, CancellationToken cancellationToken)
|
private Task<int> WaitForDotnetToExitAsync(string dotnetArguments, string workingDir, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Running dnx with the following arguments: {dnxArguments}");
|
_logger.LogInformation($"Running dotnet with the following arguments: {dotnetArguments}");
|
||||||
|
|
||||||
var dnxWatcher = _processWatcherFactory();
|
var dotnetWatcher = _processWatcherFactory();
|
||||||
int dnxProcessId = dnxWatcher.Start("dnx", dnxArguments, workingDir);
|
int dotnetProcessId = dotnetWatcher.Start("dotnet", dotnetArguments, workingDir);
|
||||||
_logger.LogInformation($"dnx process id: {dnxProcessId}");
|
_logger.LogInformation($"dotnet run process id: {dotnetProcessId}");
|
||||||
|
|
||||||
return dnxWatcher.WaitForExitAsync(cancellationToken);
|
return dotnetWatcher.WaitForExitAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IProject> WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken)
|
private async Task<IProject> WaitForValidProjectJsonAsync(string projectFile, CancellationToken cancellationToken)
|
||||||
|
|
@ -219,9 +251,9 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
return changedPath;
|
return changedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DnxWatcher CreateDefault(ILoggerFactory loggerFactory)
|
public static DotNetWatcher CreateDefault(ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
return new DnxWatcher(
|
return new DotNetWatcher(
|
||||||
fileWatcherFactory: root => new FileWatcher(root),
|
fileWatcherFactory: root => new FileWatcher(root),
|
||||||
processWatcherFactory: () => new ProcessWatcher(),
|
processWatcherFactory: () => new ProcessWatcher(),
|
||||||
projectProvider: new ProjectProvider(),
|
projectProvider: new ProjectProvider(),
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
internal class FileSystemWatcherRoot : IWatcherRoot
|
internal class FileSystemWatcherRoot : IWatcherRoot
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public class FileWatcher : IFileWatcher
|
public class FileWatcher : IFileWatcher
|
||||||
{
|
{
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
internal interface IWatcherRoot : IDisposable
|
internal interface IWatcherRoot : IDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -3,14 +3,16 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public class ProcessWatcher : IProcessWatcher
|
public class ProcessWatcher : IProcessWatcher
|
||||||
{
|
{
|
||||||
|
private static readonly bool _isWindows = PlatformServices.Default.Runtime.OperatingSystem.Equals("Windows", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private Process _runningProcess;
|
private Process _runningProcess;
|
||||||
|
|
||||||
public int Start(string executable, string arguments, string workingDir)
|
public int Start(string executable, string arguments, string workingDir)
|
||||||
|
|
@ -30,8 +32,6 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
WorkingDirectory = workingDir
|
WorkingDirectory = workingDir
|
||||||
};
|
};
|
||||||
|
|
||||||
RemoveCompilationPortEnvironmentVariable(_runningProcess.StartInfo);
|
|
||||||
|
|
||||||
_runningProcess.Start();
|
_runningProcess.Start();
|
||||||
|
|
||||||
return _runningProcess.Id;
|
return _runningProcess.Id;
|
||||||
|
|
@ -39,9 +39,9 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
|
|
||||||
public Task<int> WaitForExitAsync(CancellationToken cancellationToken)
|
public Task<int> WaitForExitAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
cancellationToken.Register(() => _runningProcess?.Kill());
|
cancellationToken.Register(() => KillProcess(_runningProcess?.Id));
|
||||||
|
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
_runningProcess.WaitForExit();
|
_runningProcess.WaitForExit();
|
||||||
|
|
||||||
|
|
@ -52,32 +52,33 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RemoveCompilationPortEnvironmentVariable(ProcessStartInfo procStartInfo)
|
private void KillProcess(int? processId)
|
||||||
{
|
{
|
||||||
string[] _environmentVariablesToRemove = new string[]
|
if (processId == null)
|
||||||
{
|
{
|
||||||
"DNX_COMPILATION_SERVER_PORT",
|
return;
|
||||||
};
|
|
||||||
|
|
||||||
#if DNX451
|
|
||||||
var environmentVariables = procStartInfo.EnvironmentVariables.Keys.Cast<string>();
|
|
||||||
#else
|
|
||||||
var environmentVariables = procStartInfo.Environment.Keys;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var envVarsToRemove = environmentVariables
|
|
||||||
.Where(envVar => _environmentVariablesToRemove.Contains(envVar, StringComparer.OrdinalIgnoreCase))
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
// Workaround for the DNX start issue (it passes some environment variables that it shouldn't)
|
|
||||||
foreach (var envVar in envVarsToRemove)
|
|
||||||
{
|
|
||||||
#if DNX451
|
|
||||||
procStartInfo.EnvironmentVariables.Remove(envVar);
|
|
||||||
#else
|
|
||||||
procStartInfo.Environment.Remove(envVar);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessStartInfo startInfo;
|
||||||
|
|
||||||
|
if (_isWindows)
|
||||||
|
{
|
||||||
|
startInfo = new ProcessStartInfo()
|
||||||
|
{
|
||||||
|
FileName = "taskkill",
|
||||||
|
Arguments = $"/T /F /PID {processId}",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startInfo = new ProcessStartInfo()
|
||||||
|
{
|
||||||
|
FileName = "pkill",
|
||||||
|
Arguments = $"-TERM -P {processId}",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var killProcess = Process.Start(startInfo);
|
||||||
|
killProcess.WaitForExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,14 +4,13 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Dnx.Runtime;
|
using Microsoft.DotNet.ProjectModel.Graph;
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
internal class Project : IProject
|
internal class Project : IProject
|
||||||
{
|
{
|
||||||
public Project(Runtime.Project runtimeProject)
|
public Project(ProjectModel.Project runtimeProject)
|
||||||
{
|
{
|
||||||
ProjectFile = runtimeProject.ProjectFilePath;
|
ProjectFile = runtimeProject.ProjectFilePath;
|
||||||
ProjectDirectory = runtimeProject.ProjectDirectory;
|
ProjectDirectory = runtimeProject.ProjectDirectory;
|
||||||
|
|
@ -23,12 +22,11 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
new string[] { runtimeProject.ProjectFilePath })
|
new string[] { runtimeProject.ProjectFilePath })
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, LockFileReader.LockFileName);
|
var projectLockJsonPath = Path.Combine(runtimeProject.ProjectDirectory, "project.lock.json");
|
||||||
var lockFileReader = new LockFileReader();
|
|
||||||
|
|
||||||
if (File.Exists(projectLockJsonPath))
|
if (File.Exists(projectLockJsonPath))
|
||||||
{
|
{
|
||||||
var lockFile = lockFileReader.Read(projectLockJsonPath);
|
var lockFile = LockFileReader.Read(projectLockJsonPath);
|
||||||
ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList();
|
ProjectDependencies = lockFile.ProjectLibraries.Select(dep => GetProjectRelativeFullPath(dep.Path)).ToList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -5,9 +5,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Extensions.CompilationAbstractions;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Core
|
namespace Microsoft.DotNet.Watcher.Core
|
||||||
{
|
{
|
||||||
public class ProjectProvider : IProjectProvider
|
public class ProjectProvider : IProjectProvider
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
errors = null;
|
errors = null;
|
||||||
project = null;
|
project = null;
|
||||||
|
|
||||||
Runtime.Project runtimeProject;
|
ProjectModel.Project runtimeProject;
|
||||||
if (!TryGetProject(projectFile, out runtimeProject, out errors))
|
if (!TryGetProject(projectFile, out runtimeProject, out errors))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -36,12 +36,12 @@ namespace Microsoft.Dnx.Watcher.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as TryGetProject but it doesn't throw
|
// Same as TryGetProject but it doesn't throw
|
||||||
private bool TryGetProject(string projectFile, out Runtime.Project project, out string errorMessage)
|
private bool TryGetProject(string projectFile, out ProjectModel.Project project, out string errorMessage)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var errors = new List<DiagnosticMessage>();
|
var errors = new List<DiagnosticMessage>();
|
||||||
if (!Runtime.Project.TryGetProject(projectFile, out project, errors))
|
if (!ProjectReader.TryGetProject(projectFile, out project, errors))
|
||||||
{
|
{
|
||||||
errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ToString()));
|
errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ToString()));
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
"keyFile": "../../tools/Key.snk"
|
"keyFile": "../../tools/Key.snk"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
|
||||||
"Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*",
|
"Microsoft.Extensions.FileProviders.Abstractions": "1.0.0-*",
|
||||||
"Microsoft.Extensions.FileProviders.Physical": "1.0.0-*",
|
"Microsoft.Extensions.FileProviders.Physical": "1.0.0-*",
|
||||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
||||||
|
|
@ -18,18 +19,8 @@
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnx451": {
|
|
||||||
"frameworkAssemblies": {
|
|
||||||
"System.Collections": "",
|
|
||||||
"System.Runtime": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dnxcore50": {
|
"dnxcore50": {
|
||||||
"dependencies": {
|
"imports": "portable-net451+win8"
|
||||||
"System.Diagnostics.Process": "4.1.0-*",
|
|
||||||
"System.Linq": "4.0.2-*",
|
|
||||||
"System.Threading.Thread": "4.0.0-*"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher
|
namespace Microsoft.DotNet.Watcher
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logger to print formatted command output.
|
/// Logger to print formatted command output.
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher
|
namespace Microsoft.DotNet.Watcher
|
||||||
{
|
{
|
||||||
public class CommandOutputProvider : ILoggerProvider
|
public class CommandOutputProvider : ILoggerProvider
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
|
using Microsoft.DotNet.Watcher.Core;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Watcher
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
private const string AppArgumentSeparator = "--";
|
||||||
|
|
||||||
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
|
||||||
|
public Program()
|
||||||
|
{
|
||||||
|
_loggerFactory = new LoggerFactory();
|
||||||
|
|
||||||
|
var commandProvider = new CommandOutputProvider(PlatformServices.Default.Runtime);
|
||||||
|
_loggerFactory.AddProvider(commandProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
using (CancellationTokenSource ctrlCTokenSource = new CancellationTokenSource())
|
||||||
|
{
|
||||||
|
Console.CancelKeyPress += (sender, ev) =>
|
||||||
|
{
|
||||||
|
ctrlCTokenSource.Cancel();
|
||||||
|
ev.Cancel = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
string[] watchArgs, appArgs;
|
||||||
|
SeparateWatchArguments(args, out watchArgs, out appArgs);
|
||||||
|
|
||||||
|
return new Program().MainInternal(watchArgs, appArgs, ctrlCTokenSource.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The argument separation rules are: if no "--" is encountered, all arguments are passed to the app being watched.
|
||||||
|
// Unless, the argument is "--help", in which case the help for the watcher is being invoked and everything else is discarded.
|
||||||
|
// To pass arguments to both the watcher and the app use "--" as separator.
|
||||||
|
// To pass "--help" to the app being watched, you must use "--": dotnet watch -- --help
|
||||||
|
internal static void SeparateWatchArguments(string[] args, out string[] watchArgs, out string[] appArgs)
|
||||||
|
{
|
||||||
|
// Special case "--help"
|
||||||
|
if (args.Length > 0 && (
|
||||||
|
args[0].Equals("--help", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
args[0].Equals("-h", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
args[0].Equals("-?", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
watchArgs = new string[] { args[0] };
|
||||||
|
appArgs = new string[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argsIndex = -1;
|
||||||
|
watchArgs = args.TakeWhile((arg, idx) =>
|
||||||
|
{
|
||||||
|
argsIndex = idx;
|
||||||
|
return !string.Equals(arg, AppArgumentSeparator, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
appArgs = args.Skip(argsIndex + 1).ToArray();
|
||||||
|
|
||||||
|
if (appArgs.Length == 0)
|
||||||
|
{
|
||||||
|
// If no explicit watcher arguments then all arguments get passed to the app being watched
|
||||||
|
appArgs = watchArgs;
|
||||||
|
watchArgs = new string[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int MainInternal(string[] watchArgs, string[] appArgs, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var app = new CommandLineApplication();
|
||||||
|
app.Name = "dotnet-watch";
|
||||||
|
app.FullName = "Microsoft dotnet File Watcher";
|
||||||
|
|
||||||
|
app.HelpOption("-?|-h|--help");
|
||||||
|
|
||||||
|
var commandArg = app.Option(
|
||||||
|
"--command <COMMAND>",
|
||||||
|
"Optional. The dotnet command to run. Default: 'run'.",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var workingDirArg = app.Option(
|
||||||
|
"--working-dir <DIR>",
|
||||||
|
"Optional. The working directory. Default: project's directory.",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var exitOnChangeArg = app.Option(
|
||||||
|
"--exit-on-change",
|
||||||
|
"Optional. The watcher will exit when a file change is detected instead of restarting the process. Default: not set.",
|
||||||
|
CommandOptionType.NoValue);
|
||||||
|
|
||||||
|
|
||||||
|
app.OnExecute(() =>
|
||||||
|
{
|
||||||
|
var projectToWatch = Path.Combine(Directory.GetCurrentDirectory(), ProjectModel.Project.FileName);
|
||||||
|
|
||||||
|
var workingDir = workingDirArg.HasValue() ?
|
||||||
|
workingDirArg.Value() :
|
||||||
|
Path.GetDirectoryName(projectToWatch);
|
||||||
|
|
||||||
|
var command = commandArg.HasValue() ?
|
||||||
|
commandArg.Value() :
|
||||||
|
"run";
|
||||||
|
|
||||||
|
var watcher = DotNetWatcher.CreateDefault(_loggerFactory);
|
||||||
|
watcher.ExitOnChange = exitOnChangeArg.HasValue();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
watcher.WatchAsync(projectToWatch, command, appArgs, workingDir, cancellationToken).Wait();
|
||||||
|
}
|
||||||
|
catch (AggregateException ex)
|
||||||
|
{
|
||||||
|
if (ex.InnerExceptions.Count != 1 || !(ex.InnerException is TaskCanceledException))
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Execute(watchArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly:InternalsVisibleTo("dotnet-watch.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||||
|
[assembly: NeutralResourcesLanguage("en-US")]
|
||||||
|
|
@ -6,23 +6,15 @@
|
||||||
"keyFile": "../../tools/Key.snk"
|
"keyFile": "../../tools/Key.snk"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.Dnx.Watcher.Core": "1.0.0-*",
|
"Microsoft.DotNet.Watcher.Core": "1.0.0-*",
|
||||||
"Microsoft.Extensions.CommandLineUtils": "1.0.0-*",
|
"Microsoft.Extensions.CommandLineUtils": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Logging": "1.0.0-*",
|
"Microsoft.Extensions.Logging": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
|
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
"Microsoft.NETCore.Platforms": "1.0.1-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"dnx451": { },
|
"dnxcore50": {
|
||||||
"dnxcore50": { }
|
"imports": "portable-net451+win8"
|
||||||
},
|
}
|
||||||
|
|
||||||
"commands": {
|
|
||||||
"dnx-watch": "Microsoft.Dnx.Watcher"
|
|
||||||
},
|
|
||||||
|
|
||||||
"scripts": {
|
|
||||||
"postbuild": [
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.Dnx.Watcher.Tests
|
|
||||||
{
|
|
||||||
// This project can output the Class library as a NuGet Package.
|
|
||||||
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
|
|
||||||
public class CommandLineParsingTests
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void NoWatcherArgs()
|
|
||||||
{
|
|
||||||
var args = "--arg1 v1 --arg2 v2".Split(' ');
|
|
||||||
|
|
||||||
string[] watcherArgs, dnxArgs;
|
|
||||||
Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs);
|
|
||||||
|
|
||||||
Assert.Empty(watcherArgs);
|
|
||||||
Assert.Equal(args, dnxArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void ArgsForBothDnxAndWatcher()
|
|
||||||
{
|
|
||||||
var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --arg4 v4".Split(' ');
|
|
||||||
|
|
||||||
string[] watcherArgs, dnxArgs;
|
|
||||||
Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs);
|
|
||||||
|
|
||||||
Assert.Equal(new string[] {"--arg1", "v1", "--arg2", "v2" }, watcherArgs);
|
|
||||||
Assert.Equal(new string[] { "--arg3", "--arg4", "v4" }, dnxArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MultipleSeparators()
|
|
||||||
{
|
|
||||||
var args = "--arg1 v1 --arg2 v2 --dnx-args --arg3 --dnxArgs --arg4 v4".Split(' ');
|
|
||||||
|
|
||||||
string[] watcherArgs, dnxArgs;
|
|
||||||
Program.SeparateWatchArguments(args, out watcherArgs, out dnxArgs);
|
|
||||||
|
|
||||||
Assert.Equal(new string[] { "--arg1", "v1", "--arg2", "v2" }, watcherArgs);
|
|
||||||
Assert.Equal(new string[] { "--arg3", "--dnxArgs", "--arg4", "v4" }, dnxArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>640d190b-26db-4dde-88ee-55814c86c43e</ProjectGuid>
|
|
||||||
<RootNamespace>Microsoft.Dnx.Watcher.Tests</RootNamespace>
|
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"compilationOptions": {
|
|
||||||
"warningsAsErrors": true,
|
|
||||||
"keyFile": "../../tools/Key.snk"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
|
|
||||||
"Microsoft.Dnx.Watcher": "1.0.0-*",
|
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
|
||||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"dnx451": { },
|
|
||||||
"dnxcore50": { }
|
|
||||||
},
|
|
||||||
"commands": {
|
|
||||||
"test": "xunit.runner.aspnet"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue