Merge branch 'rel/1.0.0' into clitest3verb

This commit is contained in:
Faizan Ahmad 2016-10-06 17:50:59 +05:30
commit 3f271e1215
116 changed files with 2571 additions and 469 deletions

View file

@ -21,5 +21,11 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-portable">
<Version>1.0.0</Version>
</DotNetCliToolReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,17 @@
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" Exclude="$(GlobalExclude)" />
<EmbeddedResource Include="**\*.resx" Exclude="$(GlobalExclude)" />
<None Include="project.json" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace TestLibrary
{
public static class ProjectC
{
public static string GetMessage()
{
return "This string came from CsprojLibrary1";
}
}
}

View file

@ -0,0 +1,11 @@
{
"dependencies": {},
"frameworks": {
"netstandard1.5": {
"dependencies": {
"Microsoft.NETCore.Sdk": "1.0.0-alpha-20160923-4",
"NETStandard.Library": "1.6.0"
}
}
}
}

View file

@ -0,0 +1,17 @@
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" Exclude="$(GlobalExclude)" />
<EmbeddedResource Include="**\*.resx" Exclude="$(GlobalExclude)" />
<None Include="project.json" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace TestLibrary
{
public static class ProjectC
{
public static string GetMessage()
{
return "This string came from CsprojLibrary2";
}
}
}

View file

@ -0,0 +1,11 @@
{
"dependencies": {},
"frameworks": {
"netstandard1.5": {
"dependencies": {
"Microsoft.NETCore.Sdk": "1.0.0-alpha-20160923-4",
"NETStandard.Library": "1.6.0"
}
}
}
}

View file

@ -0,0 +1,17 @@
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" Exclude="$(GlobalExclude)" />
<EmbeddedResource Include="**\*.resx" Exclude="$(GlobalExclude)" />
<None Include="project.json" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace TestLibrary
{
public static class ProjectC
{
public static string GetMessage()
{
return "This string came from CsprojLibrary3";
}
}
}

View file

@ -0,0 +1,11 @@
{
"dependencies": {},
"frameworks": {
"netstandard1.5": {
"dependencies": {
"Microsoft.NETCore.Sdk": "1.0.0-alpha-20160923-4",
"NETStandard.Library": "1.6.0"
}
}
}
}

View file

@ -11,7 +11,7 @@ namespace TestApp
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectA");
return 100;
return 0;
}
}
}

View file

@ -16,8 +16,8 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ClassLibrary1\ClassLibrary1.csproj" />
<ProjectReference Include="..\..\ClassLibrary2\ClassLibrary2.csproj" />
<ProjectReference Include="..\CsprojLibrary1\CsprojLibrary1.csproj" />
<ProjectReference Include="..\CsprojLibrary2\CsprojLibrary2.csproj" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -18,10 +18,10 @@
"target": "project",
"version": "1.0.0-*"
},
"ClassLibrary1": {
"CsprojLibrary1": {
"target": "project"
},
"ClassLibrary2": {
"CsprojLibrary2": {
"target": "project"
},
"NETStandard.Library": "1.6.0"

View file

@ -16,8 +16,8 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ClassLibrary2\ClassLibrary2.csproj" />
<ProjectReference Include="..\..\ClassLibrary3\ClassLibrary3.csproj" />
<ProjectReference Include="..\CsprojLibrary2\CsprojLibrary2.csproj" />
<ProjectReference Include="..\CsprojLibrary3\CsprojLibrary3.csproj" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -10,10 +10,10 @@
]
},
"dependencies": {
"ClassLibrary2": {
"CsprojLibrary2": {
"target": "project"
},
"ClassLibrary3": {
"CsprojLibrary3": {
"target": "project"
},
"NETStandard.Library": "1.6.0"

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectF");
string helperStr = TestLibrary.ProjectG.GetMessage();
Console.WriteLine(helperStr);
return 0;
}
}
}

View file

@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ProjectG": {
"target": "project",
"version": "1.0.0-*"
},
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -5,7 +5,7 @@ using System;
namespace TestLibrary
{
public static class ProjectE
public static class ProjectG
{
public static string GetMessage()
{

View file

@ -0,0 +1,4 @@
{
"projects": [ "src", "src with spaces", "src without projects" ]
}

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectJ");
string helperStr = TestLibrary.ProjectI.GetMessage();
Console.WriteLine(helperStr);
return 0;
}
}
}

View file

@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ProjectI": {
"target": "project",
"version": "1.0.0-*"
},
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectH");
string helperStr = TestLibrary.ProjectI.GetMessage();
Console.WriteLine(helperStr);
return 0;
}
}
}

View file

@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ProjectI": {
"target": "project",
"version": "1.0.0-*"
},
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -5,11 +5,11 @@ using System;
namespace TestLibrary
{
public static class ProjectE
public static class ProjectI
{
public static string GetMessage()
{
return "This string came from ProjectF";
return "This string came from ProjectI";
}
}
}

View file

@ -10,10 +10,6 @@
]
},
"dependencies": {
"ProjectG": {
"target": "project",
"version": "1.0.0-*"
},
"NETStandard.Library": "1.6.0"
},
"frameworks": {

View file

@ -9,7 +9,7 @@
"include": "testcontentfile2.txt"
},
"out/": {
"include": ["project.json", "Program.cs"],
"include": ["Program.cs"],
"exclude": ["Program.cs"],
"includeFiles": ["Program.cs"],
"excludeFiles": ["Program.cs"]

View file

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

Binary file not shown.

View file

@ -0,0 +1,16 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"keyFile": "./key.snk"
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.1",
"type": "platform"
},
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -202,7 +202,7 @@
<!-- Generate .version file -->
<WriteLinesToFile File="$(SdkOutputDirectory)/.version"
Lines="$(CommitHash);$(SdkVersion)"
Lines="$(CommitHash);$(SdkVersion);$(Rid)"
Overwrite="true" />
<ItemGroup>

View file

@ -97,11 +97,13 @@
AccountKey="$(CloudDropAccessToken)"
AccountName="$(CloudDropAccountName)"
ContainerName="$(ContainerName)"
Items="@(CliVersionBadgeToUpload)" />
Items="@(CliVersionBadgeToUpload)"
Overwrite="$(OverwriteOnPublish)" />
<SetBlobPropertiesBasedOnFileType
AccountKey="$(CloudDropAccessToken)"
AccountName="$(CloudDropAccountName)"
ContainerName="$(ContainerName)"
Items="@(CliVersionBadgeToUpload)" />
</Target>
</Project>

View file

@ -18,9 +18,12 @@
<SdkGenerateMsiPowershellScript>$(RepoRoot)/packaging/windows/clisdk/generatemsi.ps1</SdkGenerateMsiPowershellScript>
<SdkGenerateBundlePowershellScript>$(RepoRoot)/packaging/windows/clisdk/generatebundle.ps1</SdkGenerateBundlePowershellScript>
<SdkGenerateNupkgPowershellScript>$(RepoRoot)/packaging/windows/clisdk/generatenupkg.ps1</SdkGenerateNupkgPowershellScript>
<SdkInstallerFile>$(InstallerOutputDirectory)/$(ArtifactNameWithVersionSdk)$(InstallerExtension)</SdkInstallerFile>
<CombinedFrameworkSdkHostInstallerFile>$(InstallerOutputDirectory)/$(ArtifactNameWithVersionCombinedHostHostFxrFrameworkSdk)$(BundleExtension)</CombinedFrameworkSdkHostInstallerFile>
<SdkInstallerNuspecFile>$(RepoRoot)/packaging/windows/clisdk/VS.Redist.Common.Net.Core.SDK.$(Architecture).nuspec</SdkInstallerNuspecFile>
<SdkInstallerNupkgFile>$(InstallerOutputDirectory)/VS.Redist.Common.Net.Core.SDK.$(Architecture).$(NugetVersion).nupkg</SdkInstallerNupkgFile>
</PropertyGroup>
<!-- Consumed By Publish -->
@ -113,6 +116,21 @@
'$(Architecture)'" />
</Target>
<Target Name="GenerateSdkNupkg"
DependsOnTargets="Init;Layout;MsiTargetsSetupInputOutputs;GenerateSdkBundle"
Condition=" '$(OS)' == 'Windows_NT'"
Inputs="$(CombinedFrameworkSdkHostInstallerFile);
$(SdkInstallerNuspecFile);
$(SdkGenerateNupkgPowershellScript)"
Outputs="$(SdkInstallerNupkgFile)">
<Exec Command="powershell -NoProfile -NoLogo $(SdkGenerateNupkgPowershellScript)
'$(CombinedFrameworkSdkHostInstallerFile)'
'$(NugetVersion)'
'$(SdkInstallerNuspecFile)'
'$(SdkInstallerNupkgFile)'" />
</Target>
<Target Name="TestSdkMsi"
Inputs="$(SdkInstallerFile)"
Outputs="$(SdkMsiTestedSentinel)"
@ -137,6 +155,7 @@
AcquireWix;
GenerateSdkMsi;
GenerateSdkBundle;
GenerateSdkNupkg;
TestSdkMsi"
Condition=" '$(OS)' == 'Windows_NT'" />

View file

@ -18,6 +18,9 @@ namespace Microsoft.DotNet.Cli.Build
[Required]
public string AccountKey { get; set; }
[Required]
public string ContainerName { get; set; }
[Required]
public ITaskItem[] Items { get; set; }
@ -25,9 +28,9 @@ namespace Microsoft.DotNet.Cli.Build
{
get
{
if(_azurePublisher == null)
if (_azurePublisher == null)
{
_azurePublisher = new AzurePublisher(AccountName, AccountKey);
_azurePublisher = new AzurePublisher(AccountName, AccountKey, ContainerName);
}
return _azurePublisher;
@ -42,7 +45,7 @@ namespace Microsoft.DotNet.Cli.Build
return false;
}
foreach(var item in Items)
foreach (var item in Items)
{
string relativeBlobPath = item.GetMetadata("RelativeBlobPath");
if (string.IsNullOrEmpty(relativeBlobPath))
@ -53,7 +56,7 @@ namespace Microsoft.DotNet.Cli.Build
}
AzurePublisherTool.SetBlobPropertiesBasedOnFileType(relativeBlobPath);
}
}
return true;
}

View file

@ -22,42 +22,44 @@ namespace Microsoft.DotNet.Cli.Build
Sdk,
}
private const string s_dotnetBlobRootUrl = "https://dotnetcli.blob.core.windows.net/" + s_dotnetBlobContainerName;
private const string s_dotnetBlobContainerName = "dotnet";
private string _connectionString { get; set; }
private string _containerName { get; set; }
private CloudBlobContainer _blobContainer { get; set; }
public AzurePublisher()
public AzurePublisher(string containerName = s_dotnetBlobContainerName)
{
_connectionString = EnvVars.EnsureVariable("CONNECTION_STRING").Trim('"');
_blobContainer = GetDotnetBlobContainer(_connectionString);
_containerName = containerName;
_blobContainer = GetDotnetBlobContainer(_connectionString, containerName);
}
public AzurePublisher(string accountName, string accountKey)
public AzurePublisher(string accountName, string accountKey, string containerName = s_dotnetBlobContainerName)
{
_blobContainer = GetDotnetBlobContainer(accountName, accountKey);
_containerName = containerName;
_blobContainer = GetDotnetBlobContainer(accountName, accountKey, containerName);
}
private CloudBlobContainer GetDotnetBlobContainer(string connectionString)
private CloudBlobContainer GetDotnetBlobContainer(string connectionString, string containerName)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
return GetDotnetBlobContainer(storageAccount);
return GetDotnetBlobContainer(storageAccount, containerName);
}
private CloudBlobContainer GetDotnetBlobContainer(string accountName, string accountKey)
private CloudBlobContainer GetDotnetBlobContainer(string accountName, string accountKey, string containerName)
{
var storageCredentials = new StorageCredentials(accountName, accountKey);
var storageAccount = new CloudStorageAccount(storageCredentials, true);
return GetDotnetBlobContainer(storageAccount);
return GetDotnetBlobContainer(storageAccount, containerName);
}
private CloudBlobContainer GetDotnetBlobContainer(CloudStorageAccount storageAccount)
private CloudBlobContainer GetDotnetBlobContainer(CloudStorageAccount storageAccount, string containerName)
{
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
return blobClient.GetContainerReference(s_dotnetBlobContainerName);
return blobClient.GetContainerReference(containerName);
}
public string UploadFile(string file, Product product, string version)
@ -126,7 +128,7 @@ namespace Microsoft.DotNet.Cli.Build
BlobContinuationToken continuationToken = new BlobContinuationToken();
var blobFiles = blobDir.ListBlobsSegmentedAsync(continuationToken).Result;
return blobFiles.Results.Select(bf => bf.Uri.PathAndQuery.Replace($"/{s_dotnetBlobContainerName}/", string.Empty));
return blobFiles.Results.Select(bf => bf.Uri.PathAndQuery.Replace($"/{_containerName}/", string.Empty));
}
public string AcquireLeaseOnBlob(
@ -219,35 +221,9 @@ namespace Microsoft.DotNet.Cli.Build
_blobContainer.GetBlockBlobReference(path).DeleteAsync().Wait();
}
public static string CalculateFullUrlForFile(string file, Product product, string version)
{
return $"{s_dotnetBlobRootUrl}/{CalculateRelativePathForFile(file, product, version)}";
}
private static string CalculateRelativePathForFile(string file, Product product, string version)
{
return $"{product}/{version}/{Path.GetFileName(file)}";
}
public static async Task DownloadFile(string blobFilePath, string localDownloadPath)
{
var blobUrl = $"{s_dotnetBlobRootUrl}/{blobFilePath}";
using (var client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, blobUrl);
var sendTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
var response = sendTask.Result.EnsureSuccessStatusCode();
var httpStream = await response.Content.ReadAsStreamAsync();
using (var fileStream = File.Create(localDownloadPath))
using (var reader = new StreamReader(httpStream))
{
httpStream.CopyTo(fileStream);
fileStream.Flush();
}
}
}
}
}

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>VS.Redist.Common.Net.Core.SDK.x64</id>
<version>1.0.0</version>
<title>VS.Redist.Common.Net.Core.SDK.x64</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
<licenseUrl>https://www.microsoft.com/net/dotnet_library_license.htm</licenseUrl>
<projectUrl>https://github.com/dotnet/cli</projectUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<description>Windows Installers (x64) for .Net Core SDK</description>
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
</metadata>
<files>
<file src="[DOTNET_BUNDLE]" target="[DOTNET_BUNDLE]" />
</files>
</package>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>VS.Redist.Common.Net.Core.SDK.x86</id>
<version>1.0.0</version>
<title>VS.Redist.Common.Net.Core.SDK.x86</title>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
<licenseUrl>https://www.microsoft.com/net/dotnet_library_license.htm</licenseUrl>
<projectUrl>https://github.com/dotnet/cli</projectUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<description>Windows Installer (x86) for .Net Core SDK</description>
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
</metadata>
<files>
<file src="[DOTNET_BUNDLE]" target="[DOTNET_BUNDLE]" />
</files>
</package>

View file

@ -0,0 +1,74 @@
# Copyright (c) .NET Foundation and contributors. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
# This script is used to generate a nuget package with the windows installer bundle.
# The generated nupkg file is used to deliver the CLI payload to Visual Studio.
param(
[Parameter(Mandatory=$true)][string]$SdkBundlePath,
[Parameter(Mandatory=$true)][string]$NugetVersion,
[Parameter(Mandatory=$true)][string]$NuspecFile,
[Parameter(Mandatory=$true)][string]$NupkgFile
)
. "$PSScriptRoot\..\..\..\scripts\common\_common.ps1"
$RepoRoot = Convert-Path "$PSScriptRoot\..\..\.."
$NuGetDir = Join-Path $RepoRoot ".nuget"
$NuGetExe = Join-Path $NuGetDir "nuget.exe"
$OutputDirectory = [System.IO.Path]::GetDirectoryName($SdkBundlePath)
function DownloadNugetExe
{
if (-not (Test-Path $NuGetDir))
{
New-Item -ItemType Directory -Force -Path $NuGetDir | Out-Null
}
if (-not (Test-Path $NuGetExe)) {
Write-Host 'Downloading nuget.exe to ' + $NuGetExe
wget https://dist.nuget.org/win-x86-commandline/v3.5.0-rc1/NuGet.exe -OutFile $NuGetExe
}
}
function GenerateNupkg
{
if (-not (Test-Path $NuspecFile))
{
Write-Host 'Error nuspec not found - $NuspecFile'
}
$SdkBundleName = [System.IO.Path]::GetFileName($SdkBundlePath)
$NuspecFileName = [System.IO.Path]::GetFileName($NuspecFile)
$TempNuspecFile = [System.IO.Path]::Combine($OutputDirectory, $NuspecFileName)
(Get-Content $NuspecFile) -replace '\[DOTNET_BUNDLE\]', $SdkBundleName | Set-Content $TempNuspecFile
& $NuGetExe pack $TempNuspecFile -Version $NugetVersion -OutputDirectory $OutputDirectory
}
if(!(Test-Path $SdkBundlePath))
{
throw "$SdkBundlePath not found"
}
Write-Host "Creating nupkg for Sdk installer"
DownloadNugetExe
if(Test-Path $NupkgFile)
{
Remove-Item -Force $NupkgFile
}
if(-Not (GenerateNupkg))
{
Exit -1
}
if(!(Test-Path $NupkgFile))
{
throw "$NupkgFile not generated"
}
Write-Host -ForegroundColor Green "Successfully created installer nupkg - $NupkgFile"
exit $LastExitCode

View file

@ -1,23 +1,24 @@
<?xml version="1.0"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- These values were generated by running 'heat payload' against the CRTs downloaded from the fwlinks -->
<!-- These values were generated by running 'heat payload' against the CRTs downloaded from the download center links(DLC) -->
<!-- The DLC links are owned by the .Net Core team (contact leecow@microsoft.com) and CRTs that they point to should never be changed -->
<?define Crt_CertificatePublicKey="52868DFCA6E3AF2632389E6C1EE7D0468D3797D0"?>
<?define Crt_CertificateThumbprint="3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC"?>
<?define Crt_Description="Microsoft Visual C++ 2015 Redistributable ($(var.Platform)) - 14.0.23506"?>
<?define Crt_ProductName="Microsoft Visual C++ 2015 Redistributable ($(var.Platform)) - 14.0.23506"?>
<?define Crt_Version="14.0.23506.0"?>
<?define Crt_VersionRegistyKeyValue="v14.0.23506.00"?>
<?define Crt_CertificatePublicKey="371DD003A37769487A2A89A5A9DDB3026451B906"?>
<?define Crt_CertificateThumbprint="98ED99A67886D020C564923B7DF25E9AC019DF26"?>
<?define Crt_Description="Microsoft Visual C++ 2015 Redistributable ($(var.Platform)) - 14.0.24215"?>
<?define Crt_ProductName="Microsoft Visual C++ 2015 Redistributable ($(var.Platform)) - 14.0.24215"?>
<?define Crt_Version="14.0.24215.1"?>
<?define Crt_VersionRegistyKeyValue="v14.0.24215.01"?>
<?if $(var.Platform)=x86?>
<?define Crt_DownloadUrl="http://go.microsoft.com/fwlink/?LinkID=615459&amp;clcid=0x409"?>
<?define Crt_Hash="17B381D3ADB22F00E4AB47CBD91CE0A5B1CCBC70"?>
<?define Crt_Size="13977352"?>
<?define Crt_DownloadUrl="https://download.microsoft.com/download/1/F/0/1F01DD22-748C-41A7-89DE-54D64355CDA6/vc_redist.x86.exe"?>
<?define Crt_Hash="72211BD2E7DFC91EA7C8FAC549C49C0543BA791B"?>
<?define Crt_Size="14456872"?>
<?elseif $(var.Platform)=x64?>
<?define Crt_DownloadUrl="http://go.microsoft.com/fwlink/?LinkID=615460&amp;clcid=0x409"?>
<?define Crt_Hash="9A19A51D1F40CD5CD5ECB6E4E4F978F18DA8212A"?>
<?define Crt_Size="14773216"?>
<?define Crt_DownloadUrl="https://download.microsoft.com/download/1/F/0/1F01DD22-748C-41A7-89DE-54D64355CDA6/vc_redist.x64.exe"?>
<?define Crt_Hash="10B1683EA3FF5F36F225769244BF7E7813D54AD0"?>
<?define Crt_Size="15301888"?>
<?else?>
<?error Invalid Platform ($(var.Platform))?>
<?endif?>

View file

@ -63,7 +63,28 @@ namespace Microsoft.DotNet.Cli.Utils
string outputPath = null,
string applicationName = null)
{
var commandSpec = CommandResolver.TryResolveCommandSpec(commandName,
return Create(
new DefaultCommandResolverPolicy(),
commandName,
args,
framework,
configuration,
outputPath,
applicationName);
}
public static Command Create(
ICommandResolverPolicy commandResolverPolicy,
string commandName,
IEnumerable<string> args,
NuGetFramework framework = null,
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
var commandSpec = CommandResolver.TryResolveCommandSpec(
commandResolverPolicy,
commandName,
args,
framework,
configuration: configuration,

View file

@ -2,8 +2,13 @@ using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Cli.Utils
{
public class DefaultCommandResolverPolicy
public class DefaultCommandResolverPolicy : ICommandResolverPolicy
{
public CompositeCommandResolver CreateCommandResolver()
{
return Create();
}
public static CompositeCommandResolver Create()
{
var environment = new EnvironmentProvider();
@ -37,7 +42,6 @@ namespace Microsoft.DotNet.Cli.Utils
compositeCommandResolver.AddCommandResolver(new MuxerCommandResolver());
compositeCommandResolver.AddCommandResolver(new RootedCommandResolver());
compositeCommandResolver.AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory));
compositeCommandResolver.AddCommandResolver(new AppBaseDllCommandResolver());
compositeCommandResolver.AddCommandResolver(
new AppBaseCommandResolver(environment, platformCommandSpecFactory));

View file

@ -0,0 +1,7 @@
namespace Microsoft.DotNet.Cli.Utils
{
public interface ICommandResolverPolicy
{
CompositeCommandResolver CreateCommandResolver();
}
}

View file

@ -80,7 +80,7 @@ namespace Microsoft.DotNet.Cli.Utils
var projectContext = ProjectContext.Create(
projectRootPath,
framework,
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers());
DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers());
if (projectContext.RuntimeIdentifier == null)
{

View file

@ -142,7 +142,7 @@ namespace Microsoft.DotNet.Cli.Utils
return ProjectContext.Create(
projectRootPath,
framework,
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers());
DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers());
}

View file

@ -5,7 +5,7 @@ using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Utils
{
internal static class CommandResolver
internal class CommandResolver
{
public static CommandSpec TryResolveCommandSpec(
string commandName,
@ -14,6 +14,25 @@ namespace Microsoft.DotNet.Cli.Utils
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
return TryResolveCommandSpec(
new DefaultCommandResolverPolicy(),
commandName,
args,
framework,
configuration,
outputPath,
applicationName);
}
public static CommandSpec TryResolveCommandSpec(
ICommandResolverPolicy commandResolverPolicy,
string commandName,
IEnumerable<string> args,
NuGetFramework framework = null,
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
var commandResolverArgs = new CommandResolverArguments
{
@ -26,7 +45,7 @@ namespace Microsoft.DotNet.Cli.Utils
ApplicationName = applicationName
};
var defaultCommandResolver = DefaultCommandResolverPolicy.Create();
var defaultCommandResolver = commandResolverPolicy.CreateCommandResolver();
return defaultCommandResolver.Resolve(commandResolverArgs);
}

View file

@ -12,11 +12,19 @@ namespace Microsoft.DotNet.Cli.Utils
{
private static string SdkRootFolder => Path.Combine(typeof(DotnetFiles).GetTypeInfo().Assembly.Location, "..");
private static Lazy<DotnetVersionFile> s_versionFileObject =
new Lazy<DotnetVersionFile>(() => new DotnetVersionFile(VersionFile));
/// <summary>
/// The CLI ships with a .version file that stores the commit information and CLI version
/// </summary>
public static string VersionFile => Path.GetFullPath(Path.Combine(SdkRootFolder, ".version"));
internal static DotnetVersionFile VersionFileObject
{
get { return s_versionFileObject.Value; }
}
public static string NuGetPackagesArchive =>
Path.GetFullPath(Path.Combine(SdkRootFolder, "nuGetPackagesArchive.lzma"));

View file

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using Microsoft.DotNet.InternalAbstractions;
namespace Microsoft.DotNet.Cli.Utils
{
internal static class DotnetRuntimeIdentifiers
{
public static IEnumerable<string> InferCurrentRuntimeIdentifiers()
{
IEnumerable<string> fallbackIdentifiers = null;
// If the machine's RID isn't supported by the shared framework (i.e. the CLI
// is being used on a newer version of an OS), add the RID that the CLI was built
// with as a fallback. The RID the CLI was built with will have the correct
// runtime.* NuGet packages available.
// For example, when a user is using osx.10.12, but we only support osx.10.10 and
// osx.10.11, the project.json "runtimes" section cannot contain osx.10.12, since
// that RID isn't contained in the runtime graph - users will get a restore error.
FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile();
if (!fxDepsFile.SupportsCurrentRuntime())
{
string buildRid = DotnetFiles.VersionFileObject.BuildRid;
if (!string.IsNullOrEmpty(buildRid))
{
fallbackIdentifiers = new string[] { buildRid };
}
}
return RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers(fallbackIdentifiers);
}
}
}

View file

@ -0,0 +1,61 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNet.Cli.Utils
{
internal class DotnetVersionFile
{
public bool Exists { get; set; }
public string CommitSha { get; set; }
public string BuildNumber { get; set; }
/// <summary>
/// The runtime identifier (rid) that this CLI was built for.
/// </summary>
/// <remarks>
/// This is different than RuntimeEnvironment.GetRuntimeIdentifier() because the
/// BuildRid is a RID that is guaranteed to exist and works on the current machine. The
/// RuntimeEnvironment.GetRuntimeIdentifier() may be for a new version of the OS that
/// doesn't have full support yet.
/// </remarks>
public string BuildRid { get; set; }
public DotnetVersionFile(string versionFilePath)
{
Exists = File.Exists(versionFilePath);
if (Exists)
{
IEnumerable<string> lines = File.ReadLines(versionFilePath);
int index = 0;
foreach (string line in lines)
{
if (index == 0)
{
CommitSha = line.Substring(0, 10);
}
else if (index == 1)
{
BuildNumber = line;
}
else if (index == 2)
{
BuildRid = line;
}
else
{
break;
}
index++;
}
}
}
}
}

View file

@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
using System.Linq;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.Extensions.DependencyModel;
namespace Microsoft.DotNet.Cli.Utils
{
/// <summary>
/// Represents the .deps.json file in the shared framework
/// that the CLI is running against.
/// </summary>
internal class FrameworkDependencyFile
{
private readonly string _depsFilePath;
public FrameworkDependencyFile()
{
_depsFilePath = Muxer.GetDataFromAppDomain("FX_DEPS_FILE");
}
public bool SupportsCurrentRuntime()
{
return IsRuntimeSupported(RuntimeEnvironment.GetRuntimeIdentifier());
}
public bool IsRuntimeSupported(string runtimeIdentifier)
{
DependencyContext fxDependencyContext = CreateDependencyContext();
return fxDependencyContext.RuntimeGraph.Any(g => g.Runtime == runtimeIdentifier);
}
private DependencyContext CreateDependencyContext()
{
using (Stream depsFileStream = File.OpenRead(_depsFilePath))
using (DependencyContextJsonReader reader = new DependencyContextJsonReader())
{
return reader.Read(depsFileStream);
}
}
}
}

View file

@ -2,4 +2,6 @@ using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]
[assembly: InternalsVisibleTo("dotnet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Utils.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -8,7 +8,7 @@
<PropertyGroup Label="Globals">
<ProjectGuid>e5ed47ef-bf25-4da9-a7fe-290c642cbf0f</ProjectGuid>
<RootNamespace>Microsoft.DotNet.Configurer</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
</PropertyGroup>

View file

@ -12,14 +12,14 @@ namespace Microsoft.DotNet.ProjectJsonMigration
new MigrateRootOptionsRule(),
new MigrateTFMRule(),
new MigrateBuildOptionsRule(),
new MigrateJsonPropertiesRule(),
new MigratePackOptionsRule(),
new MigrateRuntimeOptionsRule(),
new MigratePublishOptionsRule(),
new MigrateProjectDependenciesRule(),
new MigratePackageDependenciesAndToolsRule(),
new MigrateConfigurationsRule(),
new MigrateScriptsRule(),
new TemporaryMutateProjectJsonRule(),
new WorkaroundOptionsRule(),
new SaveOutputProjectRule()
};

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NuGet.Frameworks;
namespace Microsoft.DotNet.ProjectJsonMigration
{
public static class MigrationNuGetFrameworkExtensions
{
public static string GetMSBuildCondition(this NuGetFramework framework)
{
return $" '$(TargetFramework)' == '{framework.GetTwoDigitShortFolderName()}' ";
}
}
}

View file

@ -18,7 +18,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
public ProjectPropertyGroupElement CommonPropertyGroup { get; }
public IEnumerable<ProjectContext> ProjectContexts { get; }
public List<ProjectContext> ProjectContexts { get; }
public ProjectContext DefaultProjectContext
{
@ -36,7 +36,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
ProjectRootElement projectXproj=null)
{
ProjectXproj = projectXproj;
ProjectContexts = projectContexts;
ProjectContexts = projectContexts.ToList();
OutputMSBuildProject = outputMSBuildProject;
CommonItemGroup = commonItemGroup;
CommonPropertyGroup = commonPropertyGroup;

View file

@ -23,7 +23,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
ProjectDirectory = projectDirectory;
OutputDirectory = outputDirectory;
SdkPackageVersion = sdkPackageVersion;
MSBuildProjectTemplate = msBuildProjectTemplate;
MSBuildProjectTemplate = msBuildProjectTemplate != null ? msBuildProjectTemplate.DeepClone() : null;
ProjectXProjFilePath = projectXprojFilePath;
}
}

View file

@ -11,7 +11,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
public ProjectDependency(string name, string projectFilePath)
{
Name = name;
ProjectFilePath = projectFilePath;
ProjectFilePath = System.IO.Path.GetFullPath(projectFilePath);
}
}
}

View file

@ -5,15 +5,17 @@ using System;
using System.Collections.Generic;
using Microsoft.Build.Construction;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph;
using System.Linq;
using System.IO;
using Newtonsoft.Json.Linq;
using Microsoft.DotNet.Tools.Common;
using NuGet.Frameworks;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.ProjectJsonMigration
{
public class ProjectDependencyFinder
internal class ProjectDependencyFinder
{
public IEnumerable<ProjectDependency> ResolveProjectDependencies(string projectDir, string xprojFile = null)
{
@ -31,25 +33,75 @@ namespace Microsoft.DotNet.ProjectJsonMigration
public IEnumerable<ProjectDependency> ResolveProjectDependencies(
IEnumerable<ProjectContext> projectContexts,
IEnumerable<string> preResolvedProjects=null)
IEnumerable<string> preResolvedProjects = null)
{
foreach(var projectContext in projectContexts)
foreach (var projectContext in projectContexts)
{
foreach(var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects))
foreach (var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects))
{
yield return projectDependency;
}
}
}
public IEnumerable<ProjectDependency> ResolveProjectDependencies(
ProjectContext projectContext,
public IEnumerable<ProjectDependency> ResolveProjectDependenciesForFramework(
Project project,
NuGetFramework framework,
IEnumerable<string> preResolvedProjects=null)
{
preResolvedProjects = preResolvedProjects ?? new HashSet<string>();
var projectExports = projectContext.CreateExporter("_").GetDependencies();
var possibleProjectDependencies =
FindPossibleProjectDependencies(project.ProjectFilePath);
var projectDependencies = new List<ProjectDependency>();
IEnumerable<ProjectLibraryDependency> projectFileDependenciesForFramework;
if (framework == null)
{
projectFileDependenciesForFramework = project.Dependencies;
}
else
{
projectFileDependenciesForFramework = project.GetTargetFramework(framework).Dependencies;
}
foreach (var projectFileDependency in projectFileDependenciesForFramework)
{
var dependencyName = projectFileDependency.Name;
ProjectDependency projectDependency;
if (preResolvedProjects.Contains(dependencyName))
{
continue;
}
if (!possibleProjectDependencies.TryGetValue(dependencyName, out projectDependency))
{
if (projectFileDependency.LibraryRange.TypeConstraint == LibraryDependencyTarget.Project)
{
MigrationErrorCodes
.MIGRATE1014($"Unresolved project dependency ({dependencyName})").Throw();
}
else
{
continue;
}
}
projectDependencies.Add(projectDependency);
}
return projectDependencies;
}
public IEnumerable<ProjectDependency> ResolveProjectDependencies(ProjectContext projectContext, IEnumerable<string> preResolvedProjects=null)
{
preResolvedProjects = preResolvedProjects ?? new HashSet<string>();
var projectExports = projectContext.CreateExporter("_").GetDependencies();
var possibleProjectDependencies =
FindPossibleProjectDependencies(projectContext.ProjectFile.ProjectFilePath);
var projectDependencies = new List<ProjectDependency>();
@ -58,10 +110,14 @@ namespace Microsoft.DotNet.ProjectJsonMigration
var projectExportName = projectExport.Library.Identity.Name;
ProjectDependency projectDependency;
if (preResolvedProjects.Contains(projectExportName))
{
continue;
}
if (!possibleProjectDependencies.TryGetValue(projectExportName, out projectDependency))
{
if (projectExport.Library.Identity.Type.Equals(LibraryType.Project)
&& !preResolvedProjects.Contains(projectExportName))
if (projectExport.Library.Identity.Type.Equals(LibraryType.Project))
{
MigrationErrorCodes
.MIGRATE1014($"Unresolved project dependency ({projectExportName})").Throw();
@ -218,7 +274,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
return projects;
}
private static List<string> GetGlobalPaths(string rootPath)
internal static List<string> GetGlobalPaths(string rootPath)
{
var paths = new List<string>();
@ -301,7 +357,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration
var projects = settings["projects"];
var dependencies = settings["dependencies"] as JObject;
globalSettings.ProjectPaths = projects == null ? new string[] { } : projects.Select(a => a.Value<string>()).ToArray();;
globalSettings.ProjectPaths = projects == null ? new string[] { } :
projects.Select(a => a.Value<string>()).ToArray();
globalSettings.PackagesPath = settings.Value<string>("packages");
globalSettings.FilePath = globalJsonPath;
}

View file

@ -16,13 +16,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{
public class ProjectMigrator
{
// TODO: Migrate PackOptions
// TODO: Migrate Multi-TFM projects
// TODO: Tests
// TODO: Out of Scope
// - Globs that resolve to directories: /some/path/**/somedir
// - Migrating Deprecated project.jsons
private readonly IMigrationRule _ruleSet;
private readonly ProjectDependencyFinder _projectDependencyFinder = new ProjectDependencyFinder();
@ -39,6 +32,28 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{
throw new ArgumentNullException();
}
Exception exc = null;
IEnumerable<ProjectDependency> projectDependencies = null;
var tempMSBuildProjectTemplate = rootSettings.MSBuildProjectTemplate.DeepClone();
try
{
projectDependencies = ResolveTransitiveClosureProjectDependencies(
rootSettings.ProjectDirectory,
rootSettings.ProjectXProjFilePath);
}
catch (Exception e)
{
exc = e;
}
// Verify up front so we can prefer these errors over an unresolved project dependency
VerifyInputs(ComputeMigrationRuleInputs(rootSettings), rootSettings);
if (exc != null)
{
throw exc;
}
MigrateProject(rootSettings);
@ -47,26 +62,40 @@ namespace Microsoft.DotNet.ProjectJsonMigration
return;
}
var projectDependencies = ResolveTransitiveClosureProjectDependencies(rootSettings.ProjectDirectory, rootSettings.ProjectXProjFilePath);
foreach(var project in projectDependencies)
{
var projectDir = Path.GetDirectoryName(project.ProjectFilePath);
var settings = new MigrationSettings(projectDir,
projectDir,
rootSettings.SdkPackageVersion,
rootSettings.MSBuildProjectTemplate);
tempMSBuildProjectTemplate);
MigrateProject(settings);
}
}
private void DeleteProjectJsons(MigrationSettings rootsettings, IEnumerable<ProjectDependency> projectDependencies)
{
try
{
File.Delete(Path.Combine(rootsettings.ProjectDirectory, "project.json"));
} catch {}
foreach (var projectDependency in projectDependencies)
{
try
{
File.Delete(projectDependency.ProjectFilePath);
} catch { }
}
}
private IEnumerable<ProjectDependency> ResolveTransitiveClosureProjectDependencies(string rootProject, string xprojFile)
{
HashSet<ProjectDependency> projectsMap = new HashSet<ProjectDependency>(new ProjectDependencyComparer());
var projectDependencies = _projectDependencyFinder.ResolveProjectDependencies(rootProject, xprojFile);
Queue<ProjectDependency> projectsQueue = new Queue<ProjectDependency>(projectDependencies);
while(projectsQueue.Count() != 0)
while (projectsQueue.Count() != 0)
{
var projectDependency = projectsQueue.Dequeue();
@ -80,7 +109,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
var projectDir = Path.GetDirectoryName(projectDependency.ProjectFilePath);
projectDependencies = _projectDependencyFinder.ResolveProjectDependencies(projectDir);
foreach(var project in projectDependencies)
foreach (var project in projectDependencies)
{
projectsQueue.Enqueue(project);
}
@ -111,7 +140,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{
var projectContexts = ProjectContext.CreateContextForEachFramework(migrationSettings.ProjectDirectory);
var xprojFile = migrationSettings.ProjectXProjFilePath ?? _projectDependencyFinder.FindXprojFile(migrationSettings.ProjectDirectory);
ProjectRootElement xproj = null;
if (xprojFile != null)
{

View file

@ -4,3 +4,4 @@
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")]
[assembly: InternalsVisibleTo("dotnet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -26,12 +26,17 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
private AddPropertyTransform<CommonCompilerOptions>[] KeyFileTransforms
=> new []
{
new AddPropertyTransform<CommonCompilerOptions>("AssemblyOriginatorKeyFile",
new AddPropertyTransform<CommonCompilerOptions>("KeyOriginatorFile",
compilerOptions => compilerOptions.KeyFile,
compilerOptions => !string.IsNullOrEmpty(compilerOptions.KeyFile)),
new AddPropertyTransform<CommonCompilerOptions>("SignAssembly",
"true",
compilerOptions => !string.IsNullOrEmpty(compilerOptions.KeyFile))
.WithMSBuildCondition(" '$(OS)' == 'Windows_NT' "),
new AddPropertyTransform<CommonCompilerOptions>("PublicSign",
"true",
compilerOptions => !string.IsNullOrEmpty(compilerOptions.KeyFile) && (compilerOptions.PublicSign == null))
.WithMSBuildCondition(" '$(OS)' != 'Windows_NT' ")
};
private AddPropertyTransform<CommonCompilerOptions> DefineTransform => new AddPropertyTransform<CommonCompilerOptions>(

View file

@ -0,0 +1,52 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.ProjectJsonMigration.Transforms;
using Microsoft.Build.Construction;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
public class MigrateJsonPropertiesRule : IMigrationRule
{
private Dictionary<string, ConditionalTransform<JToken, ProjectPropertyElement>> _propertyMappings
= new Dictionary<string, ConditionalTransform<JToken, ProjectPropertyElement>>
{
["userSecretsId"] = new AddPropertyTransform<JToken>("UserSecretsId",
j => j.Value<string>(),
j => !string.IsNullOrEmpty(j.Value<string>()))
};
private readonly ITransformApplicator _transformApplicator;
public MigrateJsonPropertiesRule(ITransformApplicator transformApplicator = null)
{
_transformApplicator = transformApplicator ?? new TransformApplicator();
}
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
var propertyGroup = migrationRuleInputs.CommonPropertyGroup;
var projectFile = migrationRuleInputs.DefaultProjectContext.ProjectFile.ProjectFilePath;
using (var stream = new FileStream(projectFile, FileMode.Open))
using (var streamReader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(streamReader))
{
var rawProject = JObject.Load(jsonReader);
foreach (var prop in _propertyMappings)
{
var token = rawProject.GetValue(prop.Key);
if (token != null)
{
_transformApplicator.Execute(prop.Value.Transform(token), propertyGroup);
}
}
}
}
}
}

View file

@ -0,0 +1,254 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Construction;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectJsonMigration.Transforms;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.Tools.Common;
using NuGet.Frameworks;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
public class MigratePackageDependenciesAndToolsRule : IMigrationRule
{
private readonly ITransformApplicator _transformApplicator;
private readonly ProjectDependencyFinder _projectDependencyFinder;
private string _projectDirectory;
public MigratePackageDependenciesAndToolsRule(ITransformApplicator transformApplicator = null)
{
_transformApplicator = transformApplicator ?? new TransformApplicator();
_projectDependencyFinder = new ProjectDependencyFinder();
}
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
CleanExistingPackageReferences(migrationRuleInputs.OutputMSBuildProject);
_projectDirectory = migrationSettings.ProjectDirectory;
var project = migrationRuleInputs.DefaultProjectContext.ProjectFile;
var tfmDependencyMap = new Dictionary<string, IEnumerable<ProjectLibraryDependency>>();
var targetFrameworks = project.GetTargetFrameworks();
// Inject Sdk dependency
_transformApplicator.Execute(
PackageDependencyInfoTransform.Transform(
new PackageDependencyInfo
{
Name = ConstantPackageNames.CSdkPackageName,
Version = migrationSettings.SdkPackageVersion
}), migrationRuleInputs.CommonItemGroup);
// Migrate Direct Deps first
MigrateDependencies(
project,
migrationRuleInputs.OutputMSBuildProject,
null,
project.Dependencies,
migrationRuleInputs.ProjectXproj);
MigrationTrace.Instance.WriteLine($"Migrating {targetFrameworks.Count()} target frameworks");
foreach (var targetFramework in targetFrameworks)
{
MigrationTrace.Instance.WriteLine($"Migrating framework {targetFramework.FrameworkName.GetShortFolderName()}");
MigrateImports(migrationRuleInputs.CommonItemGroup, targetFramework);
MigrateDependencies(
project,
migrationRuleInputs.OutputMSBuildProject,
targetFramework.FrameworkName,
targetFramework.Dependencies,
migrationRuleInputs.ProjectXproj);
}
// Tools
MigrateTools(project, migrationRuleInputs.OutputMSBuildProject);
}
private void MigrateImports(ProjectItemGroupElement commonItemGroup, TargetFrameworkInformation targetFramework)
{
var transform = ImportsTransformation.Transform(targetFramework);
if (transform != null)
{
transform.Condition = targetFramework.FrameworkName.GetMSBuildCondition();
_transformApplicator.Execute(transform, commonItemGroup);
}
}
private void CleanExistingPackageReferences(ProjectRootElement outputMSBuildProject)
{
var packageRefs = outputMSBuildProject.Items.Where(i => i.ItemType == "PackageReference").ToList();
foreach (var packageRef in packageRefs)
{
var parent = packageRef.Parent;
packageRef.Parent.RemoveChild(packageRef);
parent.RemoveIfEmpty();
}
}
private void MigrateTools(
Project project,
ProjectRootElement output)
{
if (project.Tools == null || !project.Tools.Any())
{
return;
}
var itemGroup = output.AddItemGroup();
foreach (var tool in project.Tools)
{
_transformApplicator.Execute(ToolTransform.Transform(tool), itemGroup);
}
}
private void MigrateDependencies(
Project project,
ProjectRootElement output,
NuGetFramework framework,
IEnumerable<ProjectLibraryDependency> dependencies,
ProjectRootElement xproj)
{
var projectDependencies = new HashSet<string>(GetAllProjectReferenceNames(project, framework, xproj));
var packageDependencies = dependencies.Where(d => !projectDependencies.Contains(d.Name));
string condition = framework?.GetMSBuildCondition() ?? "";
var itemGroup = output.ItemGroups.FirstOrDefault(i => i.Condition == condition)
?? output.AddItemGroup();
itemGroup.Condition = condition;
foreach (var packageDependency in packageDependencies)
{
MigrationTrace.Instance.WriteLine(packageDependency.Name);
AddItemTransform<ProjectLibraryDependency> transform;
if (packageDependency.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference)
{
transform = FrameworkDependencyTransform;
}
else
{
transform = PackageDependencyTransform();
if (packageDependency.Type == LibraryDependencyType.Build)
{
Console.WriteLine("Build type!!!");
transform = transform.WithMetadata("PrivateAssets", "all");
}
else if (packageDependency.SuppressParent != LibraryIncludeFlagUtils.DefaultSuppressParent)
{
var metadataValue = ReadLibraryIncludeFlags(packageDependency.SuppressParent);
transform = transform.WithMetadata("PrivateAssets", metadataValue);
}
if (packageDependency.IncludeType != LibraryIncludeFlags.All)
{
var metadataValue = ReadLibraryIncludeFlags(packageDependency.IncludeType);
transform = transform.WithMetadata("IncludeAssets", metadataValue);
}
}
_transformApplicator.Execute(transform.Transform(packageDependency), itemGroup);
}
}
private string ReadLibraryIncludeFlags(LibraryIncludeFlags includeFlags)
{
if ((includeFlags & LibraryIncludeFlags.All) == LibraryIncludeFlags.All)
{
return "All";
}
var flagString = "";
var allFlagsAndNames = new List<Tuple<string, LibraryIncludeFlags>>
{
Tuple.Create("Analyzers", LibraryIncludeFlags.Analyzers),
Tuple.Create("Build", LibraryIncludeFlags.Build),
Tuple.Create("Compile", LibraryIncludeFlags.Compile),
Tuple.Create("ContentFiles", LibraryIncludeFlags.ContentFiles),
Tuple.Create("Native", LibraryIncludeFlags.Native),
Tuple.Create("Runtime", LibraryIncludeFlags.Runtime)
};
foreach (var flagAndName in allFlagsAndNames)
{
var name = flagAndName.Item1;
var flag = flagAndName.Item2;
if ((includeFlags & flag) == flag)
{
if (!string.IsNullOrEmpty(flagString))
{
flagString += ";";
}
flagString += name;
}
}
return flagString;
}
private IEnumerable<string> GetAllProjectReferenceNames(Project project, NuGetFramework framework, ProjectRootElement xproj)
{
var csprojReferenceItems = _projectDependencyFinder.ResolveXProjProjectDependencies(xproj);
var migratedXProjDependencyPaths = csprojReferenceItems.SelectMany(p => p.Includes());
var migratedXProjDependencyNames = new HashSet<string>(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension(
PathUtility.GetPathWithDirectorySeparator(p))));
var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework(
project,
framework,
preResolvedProjects: migratedXProjDependencyNames);
return projectDependencies.Select(p => p.Name).Concat(migratedXProjDependencyNames);
}
private AddItemTransform<ProjectLibraryDependency> FrameworkDependencyTransform => new AddItemTransform<ProjectLibraryDependency>(
"Reference",
dep => dep.Name,
dep => "",
dep => true);
private Func<AddItemTransform<ProjectLibraryDependency>> PackageDependencyTransform => () => new AddItemTransform<ProjectLibraryDependency>(
"PackageReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.LibraryRange.VersionRange.OriginalString);
private AddItemTransform<PackageDependencyInfo> PackageDependencyInfoTransform => new AddItemTransform<PackageDependencyInfo>(
"PackageReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.Version);
private AddItemTransform<ProjectLibraryDependency> ToolTransform => new AddItemTransform<ProjectLibraryDependency>(
"DotNetCliToolReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.LibraryRange.VersionRange.OriginalString);
private AddItemTransform<TargetFrameworkInformation> ImportsTransformation => new AddItemTransform<TargetFrameworkInformation>(
"PackageTargetFallback",
t => $"$(PackageTargetFallback);{string.Join(";", t.Imports)}",
t => "",
t => t.Imports.OrEmptyIfNull().Any());
private class PackageDependencyInfo
{
public string Name {get; set;}
public string Version {get; set;}
}
}
}

View file

@ -1,93 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
/// <summary>
/// This rule is temporary while project.json still exists in the new project system.
/// It renames your existing project.json (if output directory is the current project directory),
/// creates a copy, then mutates that copy.
///
/// Mutations:
/// - inject a dependency on the Microsoft.SDK targets
/// - removing the "runtimes" node.
/// </summary>
public class TemporaryMutateProjectJsonRule : IMigrationRule
{
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
bool shouldRenameOldProject = PathsAreEqual(migrationSettings.OutputDirectory, migrationSettings.ProjectDirectory);
if (!shouldRenameOldProject && File.Exists(Path.Combine(migrationSettings.OutputDirectory, "project.json")))
{
// TODO: should there be a setting to overwrite anything in output directory?
throw new Exception("Existing project.json found in output directory.");
}
var sourceProjectFile = Path.Combine(migrationSettings.ProjectDirectory, "project.json");
var destinationProjectFile = Path.Combine(migrationSettings.OutputDirectory, "project.json");
if (shouldRenameOldProject)
{
var renamedProjectFile = Path.Combine(migrationSettings.ProjectDirectory, "project.migrated.json");
File.Move(sourceProjectFile, renamedProjectFile);
sourceProjectFile = renamedProjectFile;
}
var json = CreateDestinationProjectFile(sourceProjectFile, destinationProjectFile);
InjectSdkReference(json, ConstantPackageNames.CSdkPackageName, migrationSettings.SdkPackageVersion);
RemoveRuntimesNode(json);
File.WriteAllText(destinationProjectFile, json.ToString());
}
private JObject CreateDestinationProjectFile(string sourceProjectFile, string destinationProjectFile)
{
File.Copy(sourceProjectFile, destinationProjectFile);
return JObject.Parse(File.ReadAllText(destinationProjectFile));
}
private void InjectSdkReference(JObject json, string sdkPackageName, string sdkPackageVersion)
{
JToken dependenciesNode;
if (json.TryGetValue("dependencies", out dependenciesNode))
{
var dependenciesNodeObject = dependenciesNode.Value<JObject>();
dependenciesNodeObject.Add(sdkPackageName, sdkPackageVersion);
}
else
{
var dependenciesNodeObject = new JObject();
dependenciesNodeObject.Add(sdkPackageName, sdkPackageVersion);
json.Add("dependencies", dependenciesNodeObject);
}
}
private void RemoveRuntimesNode(JObject json)
{
json.Remove("runtimes");
}
private bool PathsAreEqual(params string[] paths)
{
var normalizedPaths = paths.Select(path => Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar)).ToList();
for (int i=1; i<normalizedPaths.Count(); ++i)
{
var path1 = normalizedPaths[i - 1];
var path2 = normalizedPaths[i];
if (!string.Equals(path1, path2, StringComparison.Ordinal))
{
return false;
}
}
return true;
}
}
}

View file

@ -1,29 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.ProjectJsonMigration.Transforms;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
public class WorkaroundOptionsRule : IMigrationRule
{
private readonly ITransformApplicator _transformApplicator;
private AddPropertyTransform<object> ProjectLockFileTransform =>
new AddPropertyTransform<object>("ProjectLockFile",
frameworks => "$(MSBuildProjectDirectory)/project.lock.json",
frameworks => true);
public WorkaroundOptionsRule(ITransformApplicator transformApplicator = null)
{
_transformApplicator = transformApplicator ?? new TransformApplicator();
}
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
var propertyGroup = migrationRuleInputs.CommonPropertyGroup;
_transformApplicator.Execute(ProjectLockFileTransform.Transform(string.Empty), propertyGroup);
}
}
}

View file

@ -14,6 +14,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
private readonly string _propertyValue;
private readonly Func<T,string> _propertyValueFunc;
private string _msbuildCondition = null;
public AddPropertyTransform(string propertyName, string propertyValue, Func<T,bool> condition)
: base(condition)
{
@ -28,13 +30,24 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Transforms
_propertyValueFunc = propertyValueFunc;
}
public AddPropertyTransform<T> WithMSBuildCondition(string condition)
{
_msbuildCondition = condition;
return this;
}
public override ProjectPropertyElement ConditionallyTransform(T source)
{
string propertyValue = GetPropertyValue(source);
var property = _propertyObjectGenerator.CreatePropertyElement(PropertyName);
property.Value = propertyValue;
if (!string.IsNullOrEmpty(_msbuildCondition))
{
property.Condition = _msbuildCondition;
}
return property;
}

View file

@ -278,6 +278,11 @@ namespace Microsoft.DotNet.ProjectModel
var dependencyValue = dependency.Value;
var dependencyTypeValue = LibraryDependencyType.Default;
var dependencyIncludeFlagsValue = LibraryIncludeFlags.All;
var dependencyExcludeFlagsValue = LibraryIncludeFlags.None;
var suppressParentFlagsValue = LibraryIncludeFlagUtils.DefaultSuppressParent;
var target = isGacOrFrameworkReference ? LibraryDependencyTarget.Reference : LibraryDependencyTarget.All;
string dependencyVersionAsString = null;
@ -298,6 +303,23 @@ namespace Microsoft.DotNet.ProjectModel
var targetStr = dependencyValue.Value<string>("target");
target = LibraryDependencyTargetUtils.Parse(targetStr);
}
IEnumerable<string> strings;
if (TryGetStringEnumerable(dependencyValue["include"], out strings))
{
dependencyIncludeFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings);
}
if (TryGetStringEnumerable(dependencyValue["exclude"], out strings))
{
dependencyExcludeFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings);
}
if (TryGetStringEnumerable(dependencyValue["suppressParent"], out strings))
{
// This overrides any settings that came from the type property.
suppressParentFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings);
}
}
else if (dependencyValue.Type == JTokenType.String)
{
@ -327,6 +349,9 @@ namespace Microsoft.DotNet.ProjectModel
}
}
// the dependency flags are: Include flags - Exclude flags
var includeFlags = dependencyIncludeFlagsValue & ~dependencyExcludeFlagsValue;
var lineInfo = (IJsonLineInfo)dependencyValue;
results.Add(new ProjectLibraryDependency
{
@ -335,6 +360,8 @@ namespace Microsoft.DotNet.ProjectModel
dependencyVersionRange,
target),
Type = dependencyTypeValue,
IncludeType = includeFlags,
SuppressParent = suppressParentFlagsValue,
SourceFilePath = projectPath,
SourceLine = lineInfo.LineNumber,
SourceColumn = lineInfo.LinePosition
@ -472,7 +499,8 @@ namespace Microsoft.DotNet.ProjectModel
Dependencies = new List<ProjectLibraryDependency>(),
CompilerOptions = compilerOptions,
Line = lineInfo.LineNumber,
Column = lineInfo.LinePosition
Column = lineInfo.LinePosition,
Imports = GetImports(frameworkValue)
};
var frameworkDependencies = new List<ProjectLibraryDependency>();
@ -508,6 +536,26 @@ namespace Microsoft.DotNet.ProjectModel
return true;
}
private IEnumerable<string> GetImports(JObject frameworkValue)
{
var prop = frameworkValue.Property("imports");
if (prop == null)
{
return Enumerable.Empty<string>();
}
if (prop.Type == JTokenType.Array)
{
return prop.Value<IEnumerable<string>>();
}
else if (prop.Type == JTokenType.String)
{
return new [] { prop.Value<string>() };
}
return null;
}
private static CommonCompilerOptions GetCompilationOptions(JObject rawObject, Project project)
{
var compilerName = rawObject.Value<string>("compilerName");
@ -819,5 +867,29 @@ namespace Microsoft.DotNet.ProjectModel
lineInfo.LineNumber,
lineInfo.LinePosition));
}
private static bool TryGetStringEnumerable(JToken token, out IEnumerable<string> result)
{
IEnumerable<string> values;
if (token == null)
{
result = null;
return false;
}
else if (token.Type == JTokenType.String)
{
values = new[]
{
token.Value<string>()
};
}
else
{
values = token.Value<string[]>();
}
result = values
.SelectMany(value => value.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries));
return true;
}
}
}

View file

@ -13,20 +13,6 @@ namespace Microsoft.DotNet.InternalAbstractions
// We should clean this up. Filed #619 to track.
public static class RuntimeEnvironmentRidExtensions
{
// Work around NuGet/Home#1941
public static IEnumerable<string> GetOverrideRestoreRuntimeIdentifiers()
{
if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows)
{
yield return RuntimeEnvironment.GetRuntimeIdentifier();
}
else
{
yield return "win7-x86";
yield return "win7-x64";
}
}
// Gets the identfier that is used for restore by default (this is different from the actual RID, but only on Windows)
public static string GetLegacyRestoreRuntimeIdentifier()
{
@ -43,36 +29,56 @@ namespace Microsoft.DotNet.InternalAbstractions
public static IEnumerable<string> GetAllCandidateRuntimeIdentifiers()
{
return GetAllCandidateRuntimeIdentifiers(null);
}
public static IEnumerable<string> GetAllCandidateRuntimeIdentifiers(IEnumerable<string> fallbackIdentifiers = null)
{
List<string> result = new List<string>();
if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Windows)
{
yield return RuntimeEnvironment.GetRuntimeIdentifier();
result.Add(RuntimeEnvironment.GetRuntimeIdentifier());
}
else
{
var arch = RuntimeEnvironment.RuntimeArchitecture.ToLowerInvariant();
if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.1", StringComparison.Ordinal))
{
yield return "win7-" + arch;
result.Add("win7-" + arch);
}
else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.2", StringComparison.Ordinal))
{
yield return "win8-" + arch;
yield return "win7-" + arch;
result.Add("win8-" + arch);
result.Add("win7-" + arch);
}
else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("6.3", StringComparison.Ordinal))
{
yield return "win81-" + arch;
yield return "win8-" + arch;
yield return "win7-" + arch;
result.Add("win81-" + arch);
result.Add("win8-" + arch);
result.Add("win7-" + arch);
}
else if (RuntimeEnvironment.OperatingSystemVersion.StartsWith("10.0", StringComparison.Ordinal))
{
yield return "win10-" + arch;
yield return "win81-" + arch;
yield return "win8-" + arch;
yield return "win7-" + arch;
result.Add("win10-" + arch);
result.Add("win81-" + arch);
result.Add("win8-" + arch);
result.Add("win7-" + arch);
}
}
if (fallbackIdentifiers != null)
{
foreach (string fallbackIdentifier in fallbackIdentifiers)
{
if (!result.Contains(fallbackIdentifier))
{
result.Add(fallbackIdentifier);
}
}
}
return result;
}
}
}

View file

@ -22,5 +22,7 @@ namespace Microsoft.DotNet.ProjectModel
public string WrappedProject { get; set; }
public string AssemblyPath { get; set; }
public IEnumerable<string> Imports { get; set; }
}
}

View file

@ -4,7 +4,6 @@
using System;
using System.IO;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using System.Linq;
using NuGet.Frameworks;
@ -28,7 +27,7 @@ namespace Microsoft.DotNet.Tools.Test
var projectPath = GetProjectPath(dotnetTestParams.ProjectOrAssemblyPath);
var runtimeIdentifiers = !string.IsNullOrEmpty(dotnetTestParams.Runtime)
? new[] {dotnetTestParams.Runtime}
: RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers();
: DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers();
var exitCode = 0;
// Create a workspace

View file

@ -0,0 +1,315 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.DependencyModel;
using NuGet.Frameworks;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class DepsJsonBuilder
{
private readonly VersionFolderPathResolver _versionFolderPathResolver;
public DepsJsonBuilder()
{
// This resolver is only used for building file names, so that base path is not required.
_versionFolderPathResolver = new VersionFolderPathResolver(path: null);
}
public DependencyContext Build(
SingleProjectInfo mainProjectInfo,
CompilationOptions compilationOptions,
LockFile lockFile,
NuGetFramework framework,
string runtime)
{
bool includeCompilationLibraries = compilationOptions != null;
LockFileTarget lockFileTarget = lockFile.GetTarget(framework, runtime);
IEnumerable<LockFileTargetLibrary> runtimeExports = lockFileTarget.GetRuntimeLibraries();
IEnumerable<LockFileTargetLibrary> compilationExports =
includeCompilationLibraries ?
lockFileTarget.GetCompileLibraries() :
Enumerable.Empty<LockFileTargetLibrary>();
var dependencyLookup = compilationExports
.Concat(runtimeExports)
.Distinct()
.Select(library => new Dependency(library.Name, library.Version.ToString()))
.ToDictionary(dependency => dependency.Name, StringComparer.OrdinalIgnoreCase);
var libraryLookup = lockFile.Libraries.ToDictionary(l => l.Name, StringComparer.OrdinalIgnoreCase);
var runtimeSignature = GenerateRuntimeSignature(runtimeExports);
IEnumerable<RuntimeLibrary> runtimeLibraries =
GetLibraries(runtimeExports, libraryLookup, dependencyLookup, runtime: true).Cast<RuntimeLibrary>();
IEnumerable<CompilationLibrary> compilationLibraries;
if (includeCompilationLibraries)
{
CompilationLibrary projectCompilationLibrary = GetProjectCompilationLibrary(
mainProjectInfo,
lockFile,
lockFileTarget,
dependencyLookup);
compilationLibraries = new[] { projectCompilationLibrary }
.Concat(
GetLibraries(compilationExports, libraryLookup, dependencyLookup, runtime: false)
.Cast<CompilationLibrary>());
}
else
{
compilationLibraries = Enumerable.Empty<CompilationLibrary>();
}
return new DependencyContext(
new TargetInfo(framework.DotNetFrameworkName, runtime, runtimeSignature, lockFileTarget.IsPortable()),
compilationOptions ?? CompilationOptions.Default,
compilationLibraries,
runtimeLibraries,
new RuntimeFallbacks[] { });
}
private static string GenerateRuntimeSignature(IEnumerable<LockFileTargetLibrary> runtimeExports)
{
var sha1 = SHA1.Create();
var builder = new StringBuilder();
var packages = runtimeExports
.Where(libraryExport => libraryExport.Type == "package");
var separator = "|";
foreach (var libraryExport in packages)
{
builder.Append(libraryExport.Name);
builder.Append(separator);
builder.Append(libraryExport.Version.ToString());
builder.Append(separator);
}
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString()));
builder.Clear();
foreach (var hashByte in hash)
{
builder.AppendFormat("{0:x2}", hashByte);
}
return builder.ToString();
}
private List<Dependency> GetProjectDependencies(
LockFile lockFile,
LockFileTarget lockFileTarget,
Dictionary<string, Dependency> dependencyLookup)
{
List<Dependency> dependencies = new List<Dependency>();
IEnumerable<ProjectFileDependencyGroup> projectFileDependencies = lockFile
.ProjectFileDependencyGroups
.Where(dg => dg.FrameworkName == string.Empty ||
dg.FrameworkName == lockFileTarget.TargetFramework.DotNetFrameworkName);
foreach (string projectFileDependency in projectFileDependencies.SelectMany(dg => dg.Dependencies))
{
int separatorIndex = projectFileDependency.IndexOf(' ');
string dependencyName = separatorIndex > 0 ?
projectFileDependency.Substring(0, separatorIndex) :
projectFileDependency;
Dependency dependency;
if (dependencyLookup.TryGetValue(dependencyName, out dependency))
{
dependencies.Add(dependency);
}
}
return dependencies;
}
private RuntimeLibrary GetProjectRuntimeLibrary(
SingleProjectInfo projectInfo,
LockFile lockFile,
LockFileTarget lockFileTarget,
Dictionary<string, Dependency> dependencyLookup)
{
RuntimeAssetGroup[] runtimeAssemblyGroups = new[] { new RuntimeAssetGroup(string.Empty, projectInfo.GetOutputName()) };
List<Dependency> dependencies = GetProjectDependencies(lockFile, lockFileTarget, dependencyLookup);
ResourceAssembly[] resourceAssemblies = projectInfo
.ResourceAssemblies
.Select(r => new ResourceAssembly(r.RelativePath, r.Culture))
.ToArray();
return new RuntimeLibrary(
type: "project",
name: projectInfo.Name,
version: projectInfo.Version,
hash: string.Empty,
runtimeAssemblyGroups: runtimeAssemblyGroups,
nativeLibraryGroups: new RuntimeAssetGroup[] { },
resourceAssemblies: resourceAssemblies,
dependencies: dependencies.ToArray(),
serviceable: false);
}
private CompilationLibrary GetProjectCompilationLibrary(
SingleProjectInfo projectInfo,
LockFile lockFile,
LockFileTarget lockFileTarget,
Dictionary<string, Dependency> dependencyLookup)
{
List<Dependency> dependencies = GetProjectDependencies(lockFile, lockFileTarget, dependencyLookup);
return new CompilationLibrary(
type: "project",
name: projectInfo.Name,
version: projectInfo.Version,
hash: string.Empty,
assemblies: new[] { projectInfo.GetOutputName() },
dependencies: dependencies.ToArray(),
serviceable: false);
}
private IEnumerable<Library> GetLibraries(
IEnumerable<LockFileTargetLibrary> exports,
IDictionary<string, LockFileLibrary> libraryLookup,
IDictionary<string, Dependency> dependencyLookup,
bool runtime)
{
return exports.Select(export => GetLibrary(export, libraryLookup, dependencyLookup, runtime));
}
private Library GetLibrary(
LockFileTargetLibrary export,
IDictionary<string, LockFileLibrary> libraryLookup,
IDictionary<string, Dependency> dependencyLookup,
bool runtime)
{
var type = export.Type;
// TEMPORARY: All packages are serviceable in RC2
// See https://github.com/dotnet/cli/issues/2569
var serviceable = export.Type == "package";
var libraryDependencies = new HashSet<Dependency>();
foreach (PackageDependency libraryDependency in export.Dependencies)
{
Dependency dependency;
if (dependencyLookup.TryGetValue(libraryDependency.Id, out dependency))
{
libraryDependencies.Add(dependency);
}
}
string hash = string.Empty;
string path = null;
string hashPath = null;
LockFileLibrary library;
if (libraryLookup.TryGetValue(export.Name, out library))
{
if (!string.IsNullOrEmpty(library.Sha512))
{
hash = "sha512-" + library.Sha512;
hashPath = _versionFolderPathResolver.GetHashFileName(export.Name, export.Version);
}
path = library.Path;
}
if (runtime)
{
return new RuntimeLibrary(
type.ToLowerInvariant(),
export.Name,
export.Version.ToString(),
hash,
CreateRuntimeAssemblyGroups(export),
CreateNativeLibraryGroups(export),
export.ResourceAssemblies.FilterPlaceHolderFiles().Select(CreateResourceAssembly),
libraryDependencies,
serviceable,
path,
hashPath);
}
else
{
IEnumerable<string> assemblies = export
.CompileTimeAssemblies
.FilterPlaceHolderFiles()
.Select(libraryAsset => libraryAsset.Path);
return new CompilationLibrary(
type.ToString().ToLowerInvariant(),
export.Name,
export.Version.ToString(),
hash,
assemblies,
libraryDependencies,
serviceable,
path,
hashPath);
}
}
private IReadOnlyList<RuntimeAssetGroup> CreateRuntimeAssemblyGroups(LockFileTargetLibrary export)
{
List<RuntimeAssetGroup> assemblyGroups = new List<RuntimeAssetGroup>();
assemblyGroups.Add(
new RuntimeAssetGroup(
string.Empty,
export.RuntimeAssemblies.FilterPlaceHolderFiles().Select(a => a.Path)));
foreach (var runtimeTargetsGroup in export.GetRuntimeTargetsGroups("runtime"))
{
assemblyGroups.Add(
new RuntimeAssetGroup(
runtimeTargetsGroup.Key,
runtimeTargetsGroup.Select(t => t.Path)));
}
return assemblyGroups;
}
private IReadOnlyList<RuntimeAssetGroup> CreateNativeLibraryGroups(LockFileTargetLibrary export)
{
List<RuntimeAssetGroup> nativeGroups = new List<RuntimeAssetGroup>();
nativeGroups.Add(
new RuntimeAssetGroup(
string.Empty,
export.NativeLibraries.FilterPlaceHolderFiles().Select(a => a.Path)));
foreach (var runtimeTargetsGroup in export.GetRuntimeTargetsGroups("native"))
{
nativeGroups.Add(
new RuntimeAssetGroup(
runtimeTargetsGroup.Key,
runtimeTargetsGroup.Select(t => t.Path)));
}
return nativeGroups;
}
private ResourceAssembly CreateResourceAssembly(LockFileItem resourceAssembly)
{
string locale;
if (!resourceAssembly.Properties.TryGetValue("locale", out locale))
{
locale = null;
}
return new ResourceAssembly(resourceAssembly.Path, locale);
}
}
}

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal interface IProject
{
LockFile GetLockFile();
IEnumerable<SingleProjectInfo> GetTools();
}
}

View file

@ -0,0 +1,101 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal static class LockFileTargetExtensions
{
public static bool IsPortable(this LockFileTarget lockFileTarget)
{
return string.IsNullOrEmpty(lockFileTarget.RuntimeIdentifier) &&
lockFileTarget.GetPlatformLibrary() != null;
}
public static LockFileTargetLibrary GetPlatformLibrary(this LockFileTarget lockFileTarget)
{
// TODO: https://github.com/dotnet/sdk/issues/17 get this from the lock file
var platformPackageName = "Microsoft.NETCore.App";
var platformLibrary = lockFileTarget
.Libraries
.FirstOrDefault(e => e.Name.Equals(platformPackageName, StringComparison.OrdinalIgnoreCase));
return platformLibrary;
}
public static HashSet<string> GetPlatformExclusionList(
this LockFileTarget lockFileTarget,
IDictionary<string, LockFileTargetLibrary> libraryLookup)
{
var platformLibrary = lockFileTarget.GetPlatformLibrary();
var exclusionList = new HashSet<string>();
exclusionList.Add(platformLibrary.Name);
CollectDependencies(libraryLookup, platformLibrary.Dependencies, exclusionList);
return exclusionList;
}
public static IEnumerable<LockFileTargetLibrary> GetRuntimeLibraries(this LockFileTarget lockFileTarget)
{
IEnumerable<LockFileTargetLibrary> runtimeLibraries = lockFileTarget.Libraries;
Dictionary<string, LockFileTargetLibrary> libraryLookup =
runtimeLibraries.ToDictionary(e => e.Name, StringComparer.OrdinalIgnoreCase);
HashSet<string> allExclusionList = new HashSet<string>();
if (lockFileTarget.IsPortable())
{
allExclusionList.UnionWith(lockFileTarget.GetPlatformExclusionList(libraryLookup));
}
return runtimeLibraries.Filter(allExclusionList).ToArray();
}
public static IEnumerable<LockFileTargetLibrary> GetCompileLibraries(this LockFileTarget lockFileTarget)
{
return lockFileTarget.Libraries;
}
public static IEnumerable<LockFileTargetLibrary> Filter(
this IEnumerable<LockFileTargetLibrary> libraries,
HashSet<string> exclusionList)
{
return libraries.Where(e => !exclusionList.Contains(e.Name));
}
public static IEnumerable<IGrouping<string, LockFileRuntimeTarget>> GetRuntimeTargetsGroups(
this LockFileTargetLibrary library,
string assetType)
{
return library.RuntimeTargets
.FilterPlaceHolderFiles()
.Cast<LockFileRuntimeTarget>()
.Where(t => string.Equals(t.AssetType, assetType, StringComparison.OrdinalIgnoreCase))
.GroupBy(t => t.Runtime);
}
private static void CollectDependencies(
IDictionary<string, LockFileTargetLibrary> libraryLookup,
IEnumerable<PackageDependency> dependencies,
HashSet<string> exclusionList)
{
foreach (PackageDependency dependency in dependencies)
{
LockFileTargetLibrary library = libraryLookup[dependency.Id];
if (library.Version.Equals(dependency.VersionRange.MinVersion))
{
if (exclusionList.Add(library.Name))
{
CollectDependencies(libraryLookup, library.Dependencies, exclusionList);
}
}
}
}
}
}

View file

@ -0,0 +1,48 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Evaluation;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class MSBuildProject : IProject
{
private Project _project;
public MSBuildProject(string msBuildProjectPath)
{
var globalProperties = new Dictionary<string, string>()
{
{ "MSBuildExtensionsPath", AppContext.BaseDirectory }
};
_project = new Project(msBuildProjectPath, globalProperties, null);
}
public LockFile GetLockFile()
{
var intermediateOutputPath = _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("BaseIntermediateOutputPath"))
.EvaluatedValue;
var lockFilePath = Path.Combine(intermediateOutputPath, "project.assets.json");
return new LockFileFormat().Read(lockFilePath);
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var toolsReferences = _project.AllEvaluatedItems.Where(i => i.ItemType.Equals("DotNetCliToolReference"));
var tools = toolsReferences.Select(t => new SingleProjectInfo(
t.EvaluatedInclude,
t.GetMetadataValue("Version"),
Enumerable.Empty<ResourceAssemblyInfo>()));
return tools;
}
}
}

View file

@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal static class NuGetUtils
{
public static bool IsPlaceholderFile(string path)
{
return string.Equals(Path.GetFileName(path), PackagingCoreConstants.EmptyFolder, StringComparison.Ordinal);
}
public static IEnumerable<LockFileItem> FilterPlaceHolderFiles(this IEnumerable<LockFileItem> files)
{
return files.Where(f => !IsPlaceholderFile(f.Path));
}
}
}

View file

@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ProjectFactory
{
public IProject GetProject(string projectDirectory)
{
return GetMSBuildProj(projectDirectory) ??
GetProjectJsonProject(projectDirectory);
}
private IProject GetMSBuildProj(string projectDirectory)
{
string msBuildProjectPath = GetMSBuildProjPath(projectDirectory);
if(msBuildProjectPath == null)
{
return null;
}
return new MSBuildProject(msBuildProjectPath);
}
private IProject GetProjectJsonProject(string projectDirectory)
{
return new ProjectJsonProject(projectDirectory);
}
private string GetMSBuildProjPath(string projectDirectory)
{
string[] projectFiles = Directory.GetFiles(projectDirectory, "*.*proj");
if (projectFiles.Length == 0)
{
return null;
}
else if (projectFiles.Length > 1)
{
throw new InvalidOperationException(
$"Specify which project file to use because this '{projectDirectory}' contains more than one project file.");
}
return projectFiles[0];
}
}
}

View file

@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ProjectJsonProject : IProject
{
private LockFile _lockFile;
public ProjectJsonProject(string projectDirectory)
{
var lockFilePath = Path.Combine(projectDirectory, LockFileFormat.LockFileName);
_lockFile = new LockFileFormat().Read(lockFilePath);
}
public LockFile GetLockFile()
{
return _lockFile;
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var tools = _lockFile.Tools.Where(t => t.Name.Contains(".NETCoreApp")).SelectMany(t => t.Libraries);
return tools.Select(t => new SingleProjectInfo(
t.Name,
t.Version.ToFullString(),
Enumerable.Empty<ResourceAssemblyInfo>()));
}
}
}

View file

@ -1,17 +1,21 @@
using System;
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Common;
using Microsoft.Extensions.DependencyModel;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
using NuGet.Versioning;
using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
public class ProjectToolsCommandResolver : ICommandResolver
{
@ -20,9 +24,6 @@ namespace Microsoft.DotNet.Cli.Utils
private static readonly CommandResolutionStrategy s_commandResolutionStrategy =
CommandResolutionStrategy.ProjectToolsPackage;
private static readonly string s_currentRuntimeIdentifier = RuntimeEnvironmentRidExtensions.GetLegacyRestoreRuntimeIdentifier();
private List<string> _allowedCommandExtensions;
private IPackagedCommandSpecFactory _packagedCommandSpecFactory;
@ -55,31 +56,26 @@ namespace Microsoft.DotNet.Cli.Utils
IEnumerable<string> args,
string projectDirectory)
{
var projectContext = GetProjectContextFromDirectoryForFirstTarget(projectDirectory);
if (projectContext == null)
{
return null;
}
var toolsLibraries = projectContext.ProjectFile.Tools.OrEmptyIfNull();
var projectFactory = new ProjectFactory();
var project = projectFactory.GetProject(projectDirectory);
var tools = project.GetTools();
return ResolveCommandSpecFromAllToolLibraries(
toolsLibraries,
tools,
commandName,
args,
projectContext);
project.GetLockFile());
}
private CommandSpec ResolveCommandSpecFromAllToolLibraries(
IEnumerable<LibraryDependency> toolsLibraries,
IEnumerable<SingleProjectInfo> toolsLibraries,
string commandName,
IEnumerable<string> args,
ProjectContext projectContext)
LockFile lockFile)
{
foreach (var toolLibrary in toolsLibraries)
{
var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary.LibraryRange, commandName, args, projectContext);
var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, lockFile);
if (commandSpec != null)
{
@ -91,17 +87,18 @@ namespace Microsoft.DotNet.Cli.Utils
}
private CommandSpec ResolveCommandSpecFromToolLibrary(
LibraryRange toolLibraryRange,
SingleProjectInfo toolLibraryRange,
string commandName,
IEnumerable<string> args,
ProjectContext projectContext)
LockFile lockFile)
{
var nugetPackagesRoot = projectContext.PackagesDirectory;
var nugetPackagesRoot = lockFile.PackageFolders.First().Path;
var lockFile = GetToolLockFile(toolLibraryRange, nugetPackagesRoot);
var toolLockFile = GetToolLockFile(toolLibraryRange, nugetPackagesRoot);
var toolLibrary = lockFile.Targets
.FirstOrDefault(t => t.TargetFramework.GetShortFolderName().Equals(s_toolPackageFramework.GetShortFolderName()))
var toolLibrary = toolLockFile.Targets
.FirstOrDefault(
t => t.TargetFramework.GetShortFolderName().Equals(s_toolPackageFramework.GetShortFolderName()))
?.Libraries.FirstOrDefault(l => l.Name == toolLibraryRange.Name);
if (toolLibrary == null)
@ -109,8 +106,8 @@ namespace Microsoft.DotNet.Cli.Utils
return null;
}
var depsFileRoot = Path.GetDirectoryName(lockFile.Path);
var depsFilePath = GetToolDepsFilePath(toolLibraryRange, lockFile, depsFileRoot);
var depsFileRoot = Path.GetDirectoryName(toolLockFile.Path);
var depsFilePath = GetToolDepsFilePath(toolLibraryRange, toolLockFile, depsFileRoot);
var normalizedNugetPackagesRoot = PathUtility.EnsureNoTrailingDirectorySeparator(nugetPackagesRoot);
@ -126,7 +123,7 @@ namespace Microsoft.DotNet.Cli.Utils
}
private LockFile GetToolLockFile(
LibraryRange toolLibrary,
SingleProjectInfo toolLibrary,
string nugetPackagesRoot)
{
var lockFilePath = GetToolLockFilePath(toolLibrary, nugetPackagesRoot);
@ -151,36 +148,19 @@ namespace Microsoft.DotNet.Cli.Utils
}
private string GetToolLockFilePath(
LibraryRange toolLibrary,
SingleProjectInfo toolLibrary,
string nugetPackagesRoot)
{
var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot);
return toolPathCalculator.GetBestLockFilePath(
toolLibrary.Name,
toolLibrary.VersionRange,
new VersionRange(new NuGetVersion(toolLibrary.Version)),
s_toolPackageFramework);
}
private ProjectContext GetProjectContextFromDirectoryForFirstTarget(string projectRootPath)
{
if (projectRootPath == null)
{
return null;
}
if (!File.Exists(Path.Combine(projectRootPath, Project.FileName)))
{
return null;
}
var projectContext = ProjectContext.CreateContextForEachTarget(projectRootPath).FirstOrDefault();
return projectContext;
}
private string GetToolDepsFilePath(
LibraryRange toolLibrary,
SingleProjectInfo toolLibrary,
LockFile toolLockFile,
string depsPathRoot)
{
@ -188,42 +168,32 @@ namespace Microsoft.DotNet.Cli.Utils
depsPathRoot,
toolLibrary.Name + FileNameSuffixes.DepsJson);
EnsureToolJsonDepsFileExists(toolLockFile, depsJsonPath);
EnsureToolJsonDepsFileExists(toolLockFile, depsJsonPath, toolLibrary);
return depsJsonPath;
}
private void EnsureToolJsonDepsFileExists(
LockFile toolLockFile,
string depsPath)
string depsPath,
SingleProjectInfo toolLibrary)
{
if (!File.Exists(depsPath))
{
GenerateDepsJsonFile(toolLockFile, depsPath);
GenerateDepsJsonFile(toolLockFile, depsPath, toolLibrary);
}
}
// Need to unit test this, so public
public void GenerateDepsJsonFile(
internal void GenerateDepsJsonFile(
LockFile toolLockFile,
string depsPath)
string depsPath,
SingleProjectInfo toolLibrary)
{
Reporter.Verbose.WriteLine($"Generating deps.json at: {depsPath}");
var projectContext = new ProjectContextBuilder()
.WithLockFile(toolLockFile)
.WithTargetFramework(s_toolPackageFramework.ToString())
.Build();
var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration);
var dependencyContext = new DependencyContextBuilder()
.Build(null,
null,
exporter.GetAllExports(),
true,
s_toolPackageFramework,
string.Empty);
var dependencyContext = new DepsJsonBuilder()
.Build(toolLibrary, null, toolLockFile, s_toolPackageFramework, null);
var tempDepsFile = Path.GetTempFileName();
using (var fileStream = File.Open(tempDepsFile, FileMode.Open, FileAccess.Write))

View file

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Cli.CommandResolution
{
public class ProjectToolsCommandResolverPolicy : ICommandResolverPolicy
{
public CompositeCommandResolver CreateCommandResolver()
{
var defaultCommandResolverPolicy = new DefaultCommandResolverPolicy();
var compositeCommandResolver = defaultCommandResolverPolicy.CreateCommandResolver();
var packagedCommandSpecFactory = new PackagedCommandSpecFactory();
compositeCommandResolver.AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory));
return compositeCommandResolver;
}
}
}

View file

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ResourceAssemblyInfo
{
public string Culture { get; }
public string RelativePath { get; }
public ResourceAssemblyInfo(string culture, string relativePath)
{
Culture = culture;
RelativePath = relativePath;
}
}
}

View file

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class SingleProjectInfo
{
public string Name { get; }
public string Version { get; }
public IEnumerable<ResourceAssemblyInfo> ResourceAssemblies { get; }
public SingleProjectInfo(string name, string version, IEnumerable<ResourceAssemblyInfo> resourceAssemblies)
{
Name = name;
Version = version;
ResourceAssemblies = resourceAssemblies;
}
public string GetOutputName()
{
return $"{Name}.dll";
}
}
}

View file

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.DotNet.Cli.CommandResolution;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.PlatformAbstractions;
@ -190,7 +191,12 @@ namespace Microsoft.DotNet.Cli
}
else
{
CommandResult result = Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.NetStandardApp15)
var projectToolsCommandResolver = new ProjectToolsCommandResolverPolicy();
CommandResult result = Command.Create(
projectToolsCommandResolver,
"dotnet-" + command,
appArgs,
FrameworkConstants.CommonFrameworks.NetStandardApp15)
.Execute();
exitCode = result.ExitCode;
}
@ -240,7 +246,8 @@ namespace Microsoft.DotNet.Cli
{
HelpCommand.PrintVersionHeader();
var commitSha = GetCommitSha() ?? "N/A";
DotnetVersionFile versionFile = DotnetFiles.VersionFileObject;
var commitSha = versionFile.CommitSha ?? "N/A";
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("Product Information:");
Reporter.Output.WriteLine($" Version: {Product.Version}");
@ -250,7 +257,7 @@ namespace Microsoft.DotNet.Cli
Reporter.Output.WriteLine($" OS Name: {RuntimeEnvironment.OperatingSystem}");
Reporter.Output.WriteLine($" OS Version: {RuntimeEnvironment.OperatingSystemVersion}");
Reporter.Output.WriteLine($" OS Platform: {RuntimeEnvironment.OperatingSystemPlatform}");
Reporter.Output.WriteLine($" RID: {RuntimeEnvironment.GetRuntimeIdentifier()}");
Reporter.Output.WriteLine($" RID: {GetDisplayRid(versionFile)}");
}
private static bool IsArg(string candidate, string longName)
@ -263,16 +270,17 @@ namespace Microsoft.DotNet.Cli
return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName));
}
private static string GetCommitSha()
private static string GetDisplayRid(DotnetVersionFile versionFile)
{
var versionFile = DotnetFiles.VersionFile;
FrameworkDependencyFile fxDepsFile = new FrameworkDependencyFile();
if (File.Exists(versionFile))
{
return File.ReadLines(versionFile).FirstOrDefault()?.Substring(0, 10);
}
string currentRid = RuntimeEnvironment.GetRuntimeIdentifier();
return null;
// if the current RID isn't supported by the shared framework, display the RID the CLI was
// built with instead, so the user knows which RID they should put in their "runtimes" section.
return fxDepsFile.IsRuntimeSupported(currentRid) ?
currentRid :
versionFile.BuildRid;
}
}
}

View file

@ -2,4 +2,4 @@ using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]
[assembly: InternalsVisibleTo("dotnet.Tests")]
[assembly: InternalsVisibleTo("dotnet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View file

@ -131,7 +131,7 @@ namespace Microsoft.DotNet.Tools.Compiler
var rids = new List<string>();
if (string.IsNullOrEmpty(RuntimeValue))
{
return RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers();
return DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers();
}
else
{

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Construction;
using Microsoft.DotNet.ProjectJsonMigration;
using Microsoft.DotNet.ProjectModel;
@ -55,22 +56,33 @@ namespace Microsoft.DotNet.Tools.Migrate
private IEnumerable<string> GetProjectsToMigrate(string projectArg)
{
if (projectArg.EndsWith(Project.FileName))
IEnumerable<string> projects = null;
if (projectArg.EndsWith(Project.FileName, StringComparison.OrdinalIgnoreCase))
{
yield return GetProjectJsonPath(projectArg);
projects = Enumerable.Repeat(projectArg, 1);
}
else if (projectArg.EndsWith(GlobalSettings.FileName, StringComparison.OrdinalIgnoreCase))
{
projects = GetProjectsFromGlobalJson(projectArg);
}
else if (Directory.Exists(projectArg))
{
var projects = Directory.EnumerateFiles(projectArg, Project.FileName, SearchOption.AllDirectories);
foreach(var project in projects)
{
yield return GetProjectJsonPath(project);
}
projects = Directory.EnumerateFiles(projectArg, Project.FileName, SearchOption.AllDirectories);
}
else
{
throw new Exception($"Invalid project argument - '{projectArg}' is not a project.json file and a directory named '{projectArg}' doesn't exist.");
throw new Exception($"Invalid project argument - '{projectArg}' is not a project.json or a global.json file and a directory named '{projectArg}' doesn't exist.");
}
if (!projects.Any())
{
throw new Exception($"Invalid project argument - Unable to find any projects in global.json or directory '{projectArg}'");
}
foreach(var project in projects)
{
yield return GetProjectJsonPath(project);
}
}
@ -93,5 +105,35 @@ namespace Microsoft.DotNet.Tools.Migrate
throw new Exception($"Unable to find project file at {projectJson}");
}
private IEnumerable<string> GetProjectsFromGlobalJson(string globalJson)
{
if (!File.Exists(globalJson))
{
throw new Exception($"Unable to find global settings file at {globalJson}");
}
var searchPaths = ProjectDependencyFinder.GetGlobalPaths(Path.GetDirectoryName(globalJson));
foreach (var searchPath in searchPaths)
{
var directory = new DirectoryInfo(searchPath);
if (!directory.Exists)
{
continue;
}
foreach (var projectDirectory in directory.EnumerateDirectories())
{
var projectFilePath = Path.Combine(projectDirectory.FullName, "project.json");
if (File.Exists(projectFilePath))
{
yield return projectFilePath;
}
}
}
}
}
}

View file

@ -11,6 +11,12 @@ namespace Microsoft.DotNet.Tools.Migrate
{
public static int Run(string[] args)
{
// IMPORTANT:
// When updating the command line args for dotnet-migrate, we need to update the in-VS caller of dotnet migrate as well.
// It is located at dotnet/roslyn-project-system:
// src/Microsoft.VisualStudio.ProjectSystem.CSharp.VS/ProjectSystem/VS/Xproj/MigrateXprojFactory.cs
DebugHelper.HandleDebugSwitch(ref args);
CommandLineApplication app = new CommandLineApplication();
@ -20,10 +26,15 @@ namespace Microsoft.DotNet.Tools.Migrate
app.HandleResponseFiles = true;
app.HelpOption("-h|--help");
CommandArgument projectArgument = app.Argument("<PROJECT_JSON/PROJECT_DIR>",
"The path to project.json file or a directory to migrate." +
" If a directory is specified, then it will recursively search for project.json files to migrate." +
" Defaults to current directory if nothing is specified.");
CommandArgument projectArgument = app.Argument("<PROJECT_JSON/GLOBAL_JSON/PROJECT_DIR>",
string.Join(Environment.NewLine,
"The path to ",
" - a project.json file to migrate.",
"or",
" - a global.json file, it will migrate the folders specified in global.json.",
"or",
" - a directory to migrate, it will recursively search for project.json files to migrate.",
"Defaults to current directory if nothing is specified."));
CommandOption template = app.Option("-t|--template-file", "Base MSBuild template to use for migrated app. The default is the project included in dotnet new -t msbuild", CommandOptionType.SingleValue);
CommandOption sdkVersion = app.Option("-v|--sdk-package-version", "The version of the sdk package that will be referenced in the migrated app. The default is the version of the sdk in dotnet new -t msbuild", CommandOptionType.SingleValue);

View file

@ -8,14 +8,11 @@ namespace Microsoft.DotNet.Tools.Migrate
{
public static string GetSdkVersion(this ProjectRootElement projectRootElement)
{
//TODO: Temporarily pinning the SDK version for Migration. Once we have packageref migration we can remove this.
return "1.0.0-alpha-20160929-1";
// return projectRootElement
// .Items
// .Where(i => i.ItemType == "PackageReference")
// .First(i => i.Include == ConstantPackageNames.CSdkPackageName)
// .GetMetadataWithName("version").Value;
return projectRootElement
.Items
.Where(i => i.ItemType == "PackageReference")
.First(i => i.Include == ConstantPackageNames.CSdkPackageName)
.GetMetadataWithName("version").Value;
}
}
}

View file

@ -414,7 +414,7 @@ namespace Microsoft.DotNet.Tools.Publish
contexts.Where(c => Equals(c.TargetFramework, framework));
var rids = string.IsNullOrEmpty(runtime) ?
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers() :
DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers() :
new[] { runtime };
return contexts.Select(c => Workspace.GetRuntimeContext(c, rids));

View file

@ -1,14 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.MSBuild;
namespace Microsoft.DotNet.Tools.Publish3
{
public class Publish3Command
public partial class Publish3Command
{
public static int Run(string[] args)
{
@ -47,43 +45,17 @@ namespace Microsoft.DotNet.Tools.Publish3
app.OnExecute(() =>
{
List<string> msbuildArgs = new List<string>();
Publish3Command publish = new Publish3Command();
if (!string.IsNullOrEmpty(projectArgument.Value))
{
msbuildArgs.Add(projectArgument.Value);
}
publish.ProjectPath = projectArgument.Value;
publish.Framework = frameworkOption.Value();
publish.Runtime = runtimeOption.Value();
publish.OutputPath = outputOption.Value();
publish.Configuration = configurationOption.Value();
publish.VersionSuffix = versionSuffixOption.Value();
publish.ExtraMSBuildArguments = app.RemainingArguments;
msbuildArgs.Add("/t:Publish");
if (frameworkOption.HasValue())
{
msbuildArgs.Add($"/p:TargetFramework={frameworkOption.Value()}");
}
if (runtimeOption.HasValue())
{
msbuildArgs.Add($"/p:RuntimeIdentifier={runtimeOption.Value()}");
}
if (outputOption.HasValue())
{
msbuildArgs.Add($"/p:PublishDir={outputOption.Value()}");
}
if (configurationOption.HasValue())
{
msbuildArgs.Add($"/p:Configuration={configurationOption.Value()}");
}
if (versionSuffixOption.HasValue())
{
msbuildArgs.Add($"/p:VersionSuffix={versionSuffixOption.Value()}");
}
msbuildArgs.AddRange(app.RemainingArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute();
return publish.Execute();
});
return app.Execute(args);

View file

@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.MSBuild;
using Microsoft.DotNet.Tools.Restore3;
namespace Microsoft.DotNet.Tools.Publish3
{
public partial class Publish3Command
{
public string ProjectPath { get; set; }
public string Framework { get; set; }
public string Runtime { get; set; }
public string OutputPath { get; set; }
public string Configuration { get; set; }
public string VersionSuffix { get; set; }
public List<string> ExtraMSBuildArguments { get; set; }
private Publish3Command()
{
}
public int Execute()
{
int restoreResult = EnsureRestored();
if (restoreResult != 0)
{
throw new GracefulException("Restore failed. Please fix the errors and try publishing again.");
}
List<string> msbuildArgs = new List<string>();
if (!string.IsNullOrEmpty(ProjectPath))
{
msbuildArgs.Add(ProjectPath);
}
msbuildArgs.Add("/t:Publish");
if (!string.IsNullOrEmpty(Framework))
{
msbuildArgs.Add($"/p:TargetFramework={Framework}");
}
if (!string.IsNullOrEmpty(Runtime))
{
msbuildArgs.Add($"/p:RuntimeIdentifier={Runtime}");
}
if (!string.IsNullOrEmpty(OutputPath))
{
msbuildArgs.Add($"/p:PublishDir={OutputPath}");
}
if (!string.IsNullOrEmpty(Configuration))
{
msbuildArgs.Add($"/p:Configuration={Configuration}");
}
if (!string.IsNullOrEmpty(VersionSuffix))
{
msbuildArgs.Add($"/p:VersionSuffix={VersionSuffix}");
}
msbuildArgs.AddRange(ExtraMSBuildArguments);
return new MSBuildForwardingApp(msbuildArgs).Execute();
}
/// <summary>
/// Ensures that the project has been restored for the specified runtime.
/// </summary>
private int EnsureRestored()
{
int result = 0;
if (!string.IsNullOrEmpty(Runtime))
{
result = Restore3Command.Run(new[] { $"/p:RuntimeIdentifiers={Runtime}" });
}
return result;
}
}
}

View file

@ -83,7 +83,7 @@ namespace Microsoft.DotNet.Tools.Run
.EnsureValid(Project)
.FrameworkOnlyContexts;
var rids = RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers();
var rids = DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers();
ProjectContext frameworkContext;
if (Framework == null)

View file

@ -2,6 +2,7 @@
"version": "1.0.0-preview3-*",
"buildOptions": {
"emitEntryPoint": true,
"keyFile": "../../tools/Key.snk",
"embed": {
"include": [
"commands/dotnet-new/CSharp_Console.zip",

Some files were not shown because too many files have changed in this diff Show more