diff --git a/.gitignore b/.gitignore
index 75392f570d..be57879a77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,8 @@ _ReSharper.*
*.pidb
*.vspx
*.psess
+*.binlog
+*.log
packages
target
artifacts
@@ -16,6 +18,8 @@ StyleCop.Cache
node_modules
*.snk
.nuget
+.r
+.w
.deps
global.json
-*.binlog
+msbuild.ProjectImports.zip
diff --git a/.gitmodules b/.gitmodules
index ff191b1b02..673caeb7ba 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -170,6 +170,9 @@
path = modules/StaticFiles
url = https://github.com/aspnet/StaticFiles.git
branch = dev
+[submodule "modules/Templating"]
+ path = modules/Templating
+ url = https://github.com/aspnet/Templating.git
[submodule "modules/Testing"]
path = modules/Testing
url = https://github.com/aspnet/Testing.git
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 514e3339c0..f967d60789 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,6 +6,12 @@
"request": "launch",
"name": "ps: Interactive Session",
"cwd": "${workspaceRoot}"
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach",
+ "processId": "${command:pickProcess}"
}
]
}
diff --git a/NuGet.Config b/NuGet.config
similarity index 58%
rename from NuGet.Config
rename to NuGet.config
index 826a1f9035..b004e5cc74 100644
--- a/NuGet.Config
+++ b/NuGet.config
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/build/Key.snk b/build/Key.snk
new file mode 100644
index 0000000000..e10e4889c1
Binary files /dev/null and b/build/Key.snk differ
diff --git a/build/PackageArchive.targets b/build/PackageArchive.targets
new file mode 100644
index 0000000000..7688976518
--- /dev/null
+++ b/build/PackageArchive.targets
@@ -0,0 +1,74 @@
+
+
+ <_TemplatesDirectory>$(MSBuildThisFileDirectory)tools\templates\
+ <_WorkRoot>$(RepositoryRoot).w\
+ $(RepositoryRoot).deps\Signed\Packages\
+ $(RepositoryRoot).deps\Signed\Packages-NoTimeStamp\
+ nuGetPackagesArchive.timestamped
+ nuGetPackagesArchive.notimestamp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(_WorkRoot)obj\$(OutputPackageName)
+ $(ArtifactsDir)lzma\
+ $(FallbackOutputDir)$(OutputPackageName).lzma
+ $(_WorkRoot)restoresources.$(OutputPackageName).props
+
+
+
+ <_FallbackArchiveRestoreSources Include="$(MetapackageRestoreSource)" Condition="Exists($(MetapackageRestoreSource))" />
+ <_FallbackArchiveRestoreSources Include="$(_DependencyMirrorDirectory)" Condition="Exists($(_DependencyMirrorDirectory))" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/RepositoryBuild.targets b/build/RepositoryBuild.targets
index becde05fda..160b887038 100644
--- a/build/RepositoryBuild.targets
+++ b/build/RepositoryBuild.targets
@@ -2,11 +2,11 @@
- %(RepositoryToBuildInOrder.Order)
- %(RepositoryToBuildInOrder.Identity)
+ %(RepositoryBuildOrder.Order)
+ %(RepositoryBuildOrder.Identity)
- RepositoryToBuild=%(RepositoryToBuildInOrder.Identity);
- BuildRepositoryRoot=$([MSBuild]::NormalizeDirectory(%(RepositoryToBuildInOrder.RootPath)))
+ RepositoryToBuild=%(RepositoryBuildOrder.Identity);
+ BuildRepositoryRoot=$([MSBuild]::NormalizeDirectory(%(RepositoryBuildOrder.RootPath)))
@@ -16,20 +16,34 @@
false
+
+
+
+
+
+
+
+
+
+ Properties="BuildGroup=%(BatchedRepository.BuildGroup);BuildNumber=$(BuildNumber);IsFinalBuild=$(IsFinalBuild);Configuration=$(Configuration)" />
+
+ $(RepositoryBuildArguments) /p:AspNetUniverseBuildOffline=true
- $(RepositoryBuildArguments) '/p:DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath)'
- $(RepositoryBuildArguments) /p:BuildNumber=$(BuildNumber)
- $(RepositoryBuildArguments) /p:Configuration=$(Configuration)
+ $(RepositoryBuildArguments) /p:DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath)
+ $(RepositoryBuildArguments) /p:DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath)
+ $(RepositoryBuildArguments) /p:BuildNumber=$(BuildNumber) /p:Configuration=$(Configuration)
$(RepositoryBuildArguments) /noconsolelogger '/l:RepoTasks.FlowLogger,$(MSBuildThisFileDirectory)tasks\bin\publish\RepoTasks.dll;Summary;FlowId=$(RepositoryToBuild)'
$(_RepositoryBuildTargets) $(RepositoryBuildArguments)
diff --git a/build/RuntimeStore.targets b/build/RuntimeStore.targets
new file mode 100644
index 0000000000..c369b30a0a
--- /dev/null
+++ b/build/RuntimeStore.targets
@@ -0,0 +1,241 @@
+
+
+
+
+ <_DependencyBuildDirectory>$(RepositoryRoot).deps\build\
+ <_DependencyMirrorDirectory>$(RepositoryRoot).deps\mirror\
+ <_BuildScriptsDirectory>$(MSBuildThisFileDirectory)tools\scripts\
+ <_WorkRoot>$(RepositoryRoot).w\
+ <_RuntimeStoreWorkDirectory>$(_WorkRoot).rw\
+ <_RuntimeStoreOutputDirectory>$(_WorkRoot).ro\
+ <_TemplatesDirectory>$(MSBuildThisFileDirectory)tools\templates\
+ <_SrcDirectory>$(RepositoryRoot)src\
+ <_AllMetapackageDirectory>$(_SrcDirectory)Microsoft.AspNetCore.All\
+ <_ExistingManifestsDirectory>$(_AllMetapackageDirectory)build\
+ <_ArtifactsZipDirectory>$(ArtifactsDir)zip\
+ <_StoreZipDirectory>$(_ArtifactsZipDirectory)rs\
+ <_SymbolsZipDirectory>$(_ArtifactsZipDirectory)symbols\
+ <_DepsOutputDirectory>$(ArtifactsDir)deps\
+
+
+
+
+
+
+
+
+ $(_WorkRoot)Microsoft.AspNetCore.All\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(_WorkRoot)RS.References\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RuntimeStoreRestoreSources Include="$(_DependencyBuildDirectory)" Condition="Exists($(_DependencyBuildDirectory))" />
+ <_RuntimeStoreRestoreSources Include="$(_DependencyMirrorDirectory)" Condition="Exists($(_DependencyMirrorDirectory))" />
+ <_RuntimeStoreRestoreSources Include="$(BuildDir)" Condition="Exists($(BuildDir))" />
+
+
+
+
+
+ <_RsManifestProps>MicrosoftAspNetCoreAllPackageVersion=$(PackageVersion)
+ <_RsManifestProps>$(_RsManifestProps);DotNetRestoreSourcesPropsPath=$(GeneratedRestoreSourcesPropsPath)
+
+
+
+
+
+
+
+ win7-$(RuntimeStoreArch)
+ linux-$(RuntimeStoreArch)
+ osx-$(RuntimeStoreArch)
+
+
+
+
+
+
+
+
+
+ <__ComposeStoreProps />
+ <_ComposeStoreProps>$(_ComposeStoreProps);$(_RsManifestProps)
+ <_ComposeStoreProps>$(_ComposeStoreProps);ComposeDir=$(_RuntimeStoreOutputDirectory)
+ <_ComposeStoreProps>$(_ComposeStoreProps);ComposeWorkingDir=$(_RuntimeStoreWorkDirectory)
+ <_ComposeStoreProps>$(_ComposeStoreProps);RuntimeIdentifier=$(RuntimeStoreRID)
+ <_ComposeStoreProps>$(_ComposeStoreProps);RuntimeFrameworkVersion=$(MicrosoftNETCoreApp20PackageVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ArtifactsDir)aspnetcore-store-$(PackageVersion)-$(RuntimeStoreRID).zip
+ $(ArtifactsDir)aspnetcore-symbols-$(PackageVersion)-$(RuntimeStoreRID).zip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ aspnetcore-store-$(PackageVersion)-common.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/RuntimeStoreInstaller.targets b/build/RuntimeStoreInstaller.targets
new file mode 100644
index 0000000000..08f6ecf3a8
--- /dev/null
+++ b/build/RuntimeStoreInstaller.targets
@@ -0,0 +1,528 @@
+
+
+ <_TemplatesDirectory>$(MSBuildThisFileDirectory)tools\templates\
+ <_DockerDir>$(MSBuildThisFileDirectory)tools\docker\
+ <_PackagingDir>$(MSBuildThisFileDirectory)tools\packaging\
+ <_DebToolDir>$(MSBuildThisFileDirectory)tools\dotnet-deb-tool-consumer\
+ <_TimestampRSSource>$(RepositoryRoot).deps\Signed\Store\
+ <_TimestampFreeRSSource>$(RepositoryRoot).deps\Signed\Store-TimestampFree\
+ <_InstallerSource>$(RepositoryRoot).deps\Installers\
+ <_WorkRoot>$(RepositoryRoot).w\
+ <_WorkLayoutDir>$(_WorkRoot).l\
+ <_WorkOutputDir>$(_WorkRoot).o\
+ <_DockerRootDirectory>/opt/code/
+ <_InstallersOutputDir>$(ArtifactsDir)installers\
+
+ aspnetcore-store
+ dotnet-hosting
+ $(_PackagingDir)store_debian_config.json
+ $(_PackagingDir)hosting_debian_config.json
+
+ https://dotnetcli.blob.core.windows.net/dotnet
+ $(KOREBUILD_DOTNET_FEED_UNCACHED)
+ $(PublicCoreFeedPrefix)
+
+ $(PublicCoreFeedPrefix)/aspnetcore/store/2.0.0-26452/Build.RS.
+ $(CoreFeedPrefix)/Runtime/$(MicrosoftNETCoreApp20PackageVersion)/dotnet-runtime-$(MicrosoftNETCoreApp20PackageVersion)-linux-x64.tar.gz
+ $(_TimestampRSSource)aspnetcore-store-$(PackageVersion)-linux-x64.tar.gz
+ $(_TimestampFreeRSSource)aspnetcore-store-$(PackageVersionNoTimestamp)-
+ $(TimestampFreeRSArchivePrefix)linux-x64.tar.gz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DependentArchives Include="$(_InstallerSource)dotnet-runtime-$(MicrosoftNETCoreApp20PackageVersion)-linux-x64.tar.gz" />
+ <_DependentArchives Include="$(_InstallerSource)Build.RS.linux.tar.gz" />
+
+
+
+ @(_DependentArchives)
+ $(HostingInstallerName)-$(Version)-linux-x64.tar.gz
+ $(HostingInstallerName)-$(PackageVersionNoTimestamp)-linux-x64.tar.gz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(TimestampFreeRSArchivePrefix)linux-x64.tar.gz
+
+
+ $(TimestampFreeRSArchivePrefix)osx-x64.tar.gz
+
+
+ $(TimestampFreeRSArchivePrefix)win7-x64.zip
+
+
+ $(TimestampFreeRSArchivePrefix)win7-x86.zip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MaintainerName) <$(MaintainerEmail)>
+ $(RPMSummary.Replace('DEB_VERSION','$(RPMVersion)'))
+
+
+
+
+
+
+
+
+ rhel.7
+ .NET Foundation
+ /opt/rh/rh-dotnet20/root/usr/lib64/dotnet/
+ /usr/share/dotnet/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0.0
+
+
+ $(PackageVersion)
+
+
+ $(MicrosoftNETCoreApp20PackageVersion)
+
+
+ $(PackageVersionNoTimestamp)
+
+
+ $(MicrosoftNETCoreApp20PackageVersion)
+
+
+
+
+ @(HostingDependencies->' -d "%(Identity) >= %(Version)"', ' ')
+ @(TimestampFreeHostingDependencies->' -d "%(Identity) >= %(Version)"', ' ')
+ @(RSDependencies->' -d "%(Identity) >= %(Version)"', ' ')
+ $(RSDependencyArguments) @(RHStoreDirectories->' --directories "%(FullPath)"', ' ')
+ $(RSDependencyArguments) @(GenericStoreDirectories->' --directories "%(FullPath)"', ' ')
+
+ Image=$(Image);RPMVendor=$(RPMVendor)
+ RPMFileSuffix=rhel.7-x64.rpm;RPMInstallRoot=$(GenericInstallerInstallRoot)
+ RPMFileSuffix=rh.rhel.7-x64.rpm;RPMInstallRoot=$(RHInstallerInstallRoot)
+
+ MaintainerName=@(_RSMaintainerName);MaintainerEmail=@(_RSMaintainerEmail)
+ $(CommonRSArguments);RPMInstallerPrefix=$(RSInstallerName);RPMRevision=@(_RSPackageRevision)
+ $(CommonRSArguments);RPMSummary=@(_RSInstallerSummary);RPMDescription=@(_RSDescription)
+ $(CommonRSArguments);RPMLicense=@(_RSLicense);RPMHomepage=@(_RSHomepage)
+
+ $(CommonArguments);MaintainerName=@(_HostingMaintainerName);MaintainerEmail=@(_HostingMaintainerEmail)
+ $(CommonHostingArguments);RPMInstallerPrefix=$(HostingInstallerName);RPMRevision=@(_HostingRevision)
+ $(CommonHostingArguments);RPMSummary=@(_HostingSummary);RPMDescription=@(_HostingDescription)
+ $(CommonHostingArguments);RPMLicense=@(_HostingLicense);RPMHomepage=@(_HostingHomepage)
+
+ $(CommonArguments);$(CommonGenericArguments);$(CommonRSArguments)
+ $(TimestampRSArguments);RSArchive=$(TimestampRSArchive);RPMVersion=$(PackageVersion);RPMArguments=$(GenericRSArguments)
+
+ $(CommonArguments);$(CommonGenericArguments);$(CommonRSArguments)
+ $(TimestampFreeRSArguments);RSArchive=$(TimestampFreeLinuxRSArchive);RPMVersion=$(PackageVersionNoTimestamp);RPMArguments=$(GenericRSArguments)
+
+ $(CommonArguments);$(CommonGenericArguments);$(CommonHostingArguments)
+ $(TimestampHostingArguments);RPMVersion=$(PackageVersion);RPMArguments=$(HostingFPMArguments)
+
+ $(CommonArguments);$(CommonGenericArguments);$(CommonHostingArguments)
+ $(TimestampFreeHostingArguments);RPMVersion=$(PackageVersionNoTimestamp);RPMArguments=$(TimestampFreeHostingFPMArguments)
+
+ $(CommonArguments);$(CommonRHArguments);$(CommonRSArguments)
+ $(RHTimestampRSArguments);RSArchive=$(TimestampRSArchive);RPMVersion=$(PackageVersion);RPMArguments=$(RHRSArguments)
+
+ $(CommonArguments);$(CommonRHArguments);$(CommonRSArguments)
+ $(RHTimestampFreeRSArguments);RSArchive=$(TimestampFreeLinuxRSArchive);RPMVersion=$(PackageVersionNoTimestamp);RPMArguments=$(RHRSArguments)
+
+ $(CommonArguments);$(CommonRHArguments);$(CommonHostingArguments)
+ $(RHTimestampHostingArguments);RPMVersion=$(PackageVersion);RPMArguments=$(HostingFPMArguments)
+
+ $(CommonArguments);$(CommonRHArguments);$(CommonHostingArguments)
+ $(RHTimestampFreeHostingArguments);RPMVersion=$(PackageVersionNoTimestamp);RPMArguments=$(TimestampFreeHostingFPMArguments)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Image=$(Image);DebConfig=$(RSDebConfigFile);DebPrefix=$(RSInstallerName)
+ Image=$(Image);DebConfig=$(HostingDebConfigFile);DotnetVersion=$(MicrosoftNETCoreApp20PackageVersion);DebPrefix=$(HostingInstallerName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Version=$(Version);TimestampFreeVersion=$(PackageVersionNoTimestamp)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/Templating.targets b/build/Templating.targets
new file mode 100644
index 0000000000..d7592be916
--- /dev/null
+++ b/build/Templating.targets
@@ -0,0 +1,68 @@
+
+
+ $(MSBuildThisFileDirectory)..\modules\Templating\
+
+
+
+
+ $(IntermediateDir)dependencies.notimestamp.props
+
+ RepositoryRoot=$(TemplatingProjectRoot);
+ DotNetRestoreSourcesPropsPath=$(GeneratedRestoreSourcesPropsPath);
+ BuildNumber=$(BuildNumber);
+ Configuration=$(Configuration);
+
+
+ $(TemplateProjCommmonProperties);
+ DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath);
+ VersionMetadata=timestamped;
+
+
+ $(TemplateProjCommmonProperties);
+ DotNetPackageVersionPropsPath=$(GeneratedNoTimestampPackageVersionPropsPath);
+ IsFinalBuild=true;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_NoTimestampPackages Include="@(ExternalDependency)" />
+ <_NoTimestampPackages Include="%(FinalBuildArtifactInfo.PackageId)" Version="%(FinalBuildArtifactInfo.Version)" Condition=" '%(FinalBuildArtifactInfo.ArtifactType)' == 'NuGetPackage' " />
+ <_NoTimestampPackages Include="Microsoft.AspNetCore.All" Version="$(PackageVersionNoTimestamp)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/artifacts.props b/build/artifacts.props
index acf749a292..71a1c7a7cc 100644
--- a/build/artifacts.props
+++ b/build/artifacts.props
@@ -3,247 +3,255 @@
false
+ false
+ false
+ false
+ false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/build/common.props b/build/common.props
new file mode 100644
index 0000000000..db6fa6bd04
--- /dev/null
+++ b/build/common.props
@@ -0,0 +1,19 @@
+
+
+
+
+ Microsoft ASP.NET Core
+ https://github.com/aspnet/Universe
+ git
+ false
+ ..\..\build\Key.snk
+ true
+ true
+ true
+
+
+
+
+
+
+
diff --git a/build/dependencies.props b/build/dependencies.props
index f72f6fb109..ec31a3e3ca 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -1,4 +1,4 @@
-
+
@@ -12,12 +12,22 @@
false
false
+
+ false
+
+ false
+
+ false
+
+ false
+
+ false
-
+
- https://dotnet.myget.org/f/dotnet-core/api/v3/index.json
+ https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
@@ -51,7 +61,7 @@
2.6.0-beta1-62023-02
-
+
VSIX_MicrosoftCodeAnalysisPackageVersion
@@ -117,53 +127,56 @@
https://api.nuget.org/v3/index.json
+ 2.0.0
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
MicrosoftNETCoreApp10PackageVersion
MicrosoftNETCoreApp11PackageVersion
-
+
MicrosoftNETCoreApp20PackageVersion
-
-
-
+
+
+
+
@@ -180,80 +193,80 @@
-
-
-
+
+
+
-
-
-
-
+
+
+
+
VisualStudio_NewtonsoftJsonPackageVersion
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/build/push.targets b/build/push.targets
index 1fe21d36cd..2b8cac8dfb 100644
--- a/build/push.targets
+++ b/build/push.targets
@@ -1,42 +1,33 @@
-
+
+
+
+
+
+
+
-
-
- <_PackagesToPush Include="$(BuildDir)*.nupkg" />
- <_PackagesToPush Include="$(ArtifactsDir)mirror\*.nupkg" />
- <_LineupPackagesToPush Include="$(LineupBuildDir)*.nupkg" />
-
-
-
-
-
+
+
+
+
+
$(NpmRegistry.Replace("https:", "")):_authToken
-
-
-
-
diff --git a/build/repo.props b/build/repo.props
index 3c0277344d..180925e696 100644
--- a/build/repo.props
+++ b/build/repo.props
@@ -1,11 +1,9 @@
-
-
-
-
true
+
+
diff --git a/build/repo.targets b/build/repo.targets
index 5c6e445532..1dcef21a6f 100644
--- a/build/repo.targets
+++ b/build/repo.targets
@@ -1,29 +1,31 @@
+
+
+
+
$(RepositoryRoot)modules\
$(ArtifactsDir)lineups\
<_DependencyBuildDirectory>$(RepositoryRoot).deps\build\
- <_DependencyLineupDir>$(RepositoryRoot).deps\lineups\
<_DependencyPackagesDirectory>$(_DependencyBuildDirectory)
- <_RestoreGraphSpecsDirectory>$(IntermediateDir)package-specs\
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'=='' AND '$(CompileOnly)'=='true'">/t:Package /t:VerifyPackages
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'==''">/t:Build
-
$(IntermediateDir)mirror\
$(IntermediateDir)ext\
$(IntermediateDir)dependencies.props
+ $(IntermediateDir)sources.props
- $(PrepareDependsOn);VerifyPackageArtifactConfig;CleanArtifacts;PrepareOutputPaths
+ $(PrepareDependsOn);VerifyPackageArtifactConfig;PrepareOutputPaths
+ $(CleanDependsOn);CleanArtifacts;CleanUniverseArtifacts
$(RestoreDependsOn);RestoreExternalDependencies
- $(CleanDependsOn);CleanArtifacts
$(CompileDependsOn);BuildRepositories
- $(PackageDependsOn);CopyPackagesByCategory
+ $(PackageDependsOn);BuildAllMetapackage;BuildTemplates;SplitPackages
$(VerifyDependsOn);VerifyCoherentVersions
@@ -32,6 +34,10 @@
+
+
@@ -40,35 +46,70 @@
+
+
+
+
+
+
+
+
+
+
+
+ <_NoBuildSolution Update="@(_NoBuildSolution)" Build="false" />
+
+
+
-
+
-
+ <_LineupPackages Include="@(ExternalDependency)" />
+ <_LineupPackages Include="%(ArtifactInfo.PackageId)" Version="%(ArtifactInfo.Version)" Condition=" '%(ArtifactInfo.ArtifactType)' == 'NuGetPackage' " />
+ <_LineupPackages Include="Microsoft.AspNetCore.All" Version="$(PackageVersion)" />
+
+ <_LineupSources Include="$(_DependencyPackagesDirectory)" Condition="'$(_DependencyPackagesDirectory)' != '' AND Exists('$(_DependencyPackagesDirectory)')" />
+ <_LineupSources Include="$(BuildDir)" />
+ <_LineupSources Include="$(IntermediateExternalPackageDir)" />
+ <_LineupSources Include="$(IntermediateMirrorPackageDir)" />
+
+
@@ -76,6 +117,10 @@
+
+
+
+
<_RepositoriesToInclude Include="$(KOREBUILD_REPOSITORY_INCLUDE)" />
@@ -99,53 +144,23 @@
+
+ DependsOnTargets="_PrepareRepositories;_UpdateNuGetConfig;GeneratePropsFiles;ComputeGraph;_BuildRepositories" />
-
-
-
-
-
-
-
-
- RestoreGraphOutputPath=$(_RestoreGraphSpecsDirectory)$([System.IO.Path]::GetFileName('$([System.IO.Path]::GetDirectoryName(%(FullPath)))'))\%(Solution.FileName)%(Solution.Extension).json
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+ Properties="Configuration=$(Configuration);BuildNumber=$(BuildNumber);DotNetPackageVersionPropsPath=$(GeneratedPackageVersionPropsPath);DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath)">
+
+
@@ -164,7 +179,7 @@
SourceUri="$(BuildDir)" />
-
+
@@ -186,11 +201,12 @@
+
+ ExternalDependencies="@(ExternalDependency);@(ShippedExternalDependency)" />
diff --git a/build/tasks/AddArchiveReferences.cs b/build/tasks/AddArchiveReferences.cs
new file mode 100644
index 0000000000..5da49ee059
--- /dev/null
+++ b/build/tasks/AddArchiveReferences.cs
@@ -0,0 +1,133 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using NuGet.Versioning;
+using RepoTasks.Utilities;
+
+namespace RepoTasks
+{
+ public class AddArchiveReferences : Task
+ {
+ [Required]
+ public string ReferencePackagePath { get; set; }
+
+ [Required]
+ public string MetaPackageVersion { get; set; }
+
+ [Required]
+ public bool RemoveTimestamp { get; set; }
+
+ [Required]
+ public ITaskItem[] BuildArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] PackageArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] ExternalDependencies { get; set; }
+
+ public override bool Execute()
+ {
+ // Parse input
+ var externalArchiveArtifacts = ExternalDependencies.Where(p => p.GetMetadata("LZMA") == "true");
+ var externalArchiveTools = ExternalDependencies.Where(p => p.GetMetadata("LZMATools") == "true");
+ var archiveArtifacts = PackageArtifacts.Where(p => p.GetMetadata("LZMA") == "true");
+ var archiveTools = PackageArtifacts.Where(p => p.GetMetadata("LZMATools") == "true");
+ var buildArtifacts = BuildArtifacts.Select(ArtifactInfo.Parse)
+ .OfType()
+ .Where(p => !p.IsSymbolsArtifact);
+
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(ReferencePackagePath);
+
+ // Project
+ var projectElement = xmlDoc.FirstChild;
+
+ // Items
+ var itemGroupElement = xmlDoc.CreateElement("ItemGroup");
+ Log.LogMessage(MessageImportance.High, $"Archive will include the following packages");
+
+ foreach (var package in archiveArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = string.Equals(packageName, "Microsoft.AspNetCore.All", StringComparison.OrdinalIgnoreCase) ?
+ MetaPackageVersion :
+ buildArtifacts
+ .Single(p => string.Equals(p.PackageInfo.Id, packageName, StringComparison.OrdinalIgnoreCase))
+ .PackageInfo.Version.ToString();
+
+ if (RemoveTimestamp)
+ {
+ packageVersion = VersionUtilities.GetTimestampFreeVersion(packageVersion);
+ }
+
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ foreach (var package in externalArchiveArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = package.GetMetadata("Version");
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ foreach (var package in archiveTools)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = buildArtifacts
+ .Single(p => string.Equals(p.PackageInfo.Id, packageName, StringComparison.OrdinalIgnoreCase))
+ .PackageInfo.Version.ToString();
+
+ if (RemoveTimestamp)
+ {
+ packageVersion = VersionUtilities.GetTimestampFreeVersion(packageVersion);
+ }
+
+ Log.LogMessage(MessageImportance.High, $" - Tool: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("DotNetCliToolReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ foreach (var package in externalArchiveTools)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = package.GetMetadata("Version");
+ Log.LogMessage(MessageImportance.High, $" - Tool: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("DotNetCliToolReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+ projectElement.AppendChild(itemGroupElement);
+
+ // Save updated file
+ xmlDoc.AppendChild(projectElement);
+ xmlDoc.Save(ReferencePackagePath);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/AddMetapackageReferences.cs b/build/tasks/AddMetapackageReferences.cs
new file mode 100644
index 0000000000..5488dec22e
--- /dev/null
+++ b/build/tasks/AddMetapackageReferences.cs
@@ -0,0 +1,85 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using RepoTasks.Utilities;
+
+namespace RepoTasks
+{
+ public class AddMetapackageReferences : Task
+ {
+ [Required]
+ public string ReferencePackagePath { get; set; }
+
+ [Required]
+ public ITaskItem[] BuildArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] PackageArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] ExternalDependencies { get; set; }
+
+ public override bool Execute()
+ {
+ // Parse input
+ var metapackageArtifacts = PackageArtifacts.Where(p => p.GetMetadata("Metapackage") == "true");
+ var externalArtifacts = ExternalDependencies.Where(p => p.GetMetadata("Metapackage") == "true");
+ var buildArtifacts = BuildArtifacts.Select(ArtifactInfo.Parse)
+ .OfType()
+ .Where(p => !p.IsSymbolsArtifact);
+
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(ReferencePackagePath);
+
+ // Project
+ var projectElement = xmlDoc.FirstChild;
+
+ // Items
+ var itemGroupElement = xmlDoc.CreateElement("ItemGroup");
+ Log.LogMessage(MessageImportance.High, $"Metapackage will include the following packages");
+
+ foreach (var package in metapackageArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = buildArtifacts
+ .Single(p => string.Equals(p.PackageInfo.Id, packageName, StringComparison.OrdinalIgnoreCase))
+ .PackageInfo.Version.ToString();
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+ packageReferenceElement.SetAttribute("PrivateAssets", "None");
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ foreach (var package in externalArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = package.GetMetadata("Version");
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+ packageReferenceElement.SetAttribute("PrivateAssets", "None");
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ projectElement.AppendChild(itemGroupElement);
+
+ // Save updated file
+ xmlDoc.AppendChild(projectElement);
+ xmlDoc.Save(ReferencePackagePath);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/AddRSReferences.cs b/build/tasks/AddRSReferences.cs
new file mode 100644
index 0000000000..1cbc504661
--- /dev/null
+++ b/build/tasks/AddRSReferences.cs
@@ -0,0 +1,85 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using RepoTasks.Utilities;
+
+namespace RepoTasks
+{
+ public class AddRSReferences : Task
+ {
+ [Required]
+ public string ReferencePackagePath { get; set; }
+
+ [Required]
+ public ITaskItem[] BuildArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] PackageArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] ExternalDependencies { get; set; }
+
+ public override bool Execute()
+ {
+ // Parse input
+ var runtimeStoreArtifacts = PackageArtifacts.Where(p => p.GetMetadata("RuntimeStore") == "true");
+ var externalArtifacts = ExternalDependencies.Where(p => p.GetMetadata("RuntimeStore") == "true");
+ var buildArtifacts = BuildArtifacts.Select(ArtifactInfo.Parse)
+ .OfType()
+ .Where(p => !p.IsSymbolsArtifact);
+
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(ReferencePackagePath);
+
+ // Project
+ var projectElement = xmlDoc.FirstChild;
+
+ // Items
+ var itemGroupElement = xmlDoc.CreateElement("ItemGroup");
+ Log.LogMessage(MessageImportance.High, $"Runtime store will include the following packages");
+
+ foreach (var package in runtimeStoreArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = buildArtifacts
+ .Single(p => string.Equals(p.PackageInfo.Id, packageName, StringComparison.OrdinalIgnoreCase))
+ .PackageInfo.Version.ToString();
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+ packageReferenceElement.SetAttribute("PrivateAssets", "None");
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ foreach (var package in externalArtifacts)
+ {
+ var packageName = package.ItemSpec;
+ var packageVersion = package.GetMetadata("Version");
+ Log.LogMessage(MessageImportance.High, $" - Package: {packageName} Version: {packageVersion}");
+
+ var packageReferenceElement = xmlDoc.CreateElement("PackageReference");
+ packageReferenceElement.SetAttribute("Include", packageName);
+ packageReferenceElement.SetAttribute("Version", packageVersion);
+ packageReferenceElement.SetAttribute("PrivateAssets", "None");
+
+ itemGroupElement.AppendChild(packageReferenceElement);
+ }
+
+ projectElement.AppendChild(itemGroupElement);
+
+ // Save updated file
+ xmlDoc.AppendChild(projectElement);
+ xmlDoc.Save(ReferencePackagePath);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/AnalyzeBuildGraph.cs b/build/tasks/AnalyzeBuildGraph.cs
new file mode 100644
index 0000000000..94710b1aa3
--- /dev/null
+++ b/build/tasks/AnalyzeBuildGraph.cs
@@ -0,0 +1,245 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+using System.Text;
+using System.Threading;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using NuGet.Frameworks;
+using NuGet.Versioning;
+using RepoTools.BuildGraph;
+using RepoTasks.ProjectModel;
+using RepoTasks.Utilities;
+
+namespace RepoTasks
+{
+ public class AnalyzeBuildGraph : Task, ICancelableTask
+ {
+ private readonly CancellationTokenSource _cts = new CancellationTokenSource();
+
+ ///
+ /// Repositories that we are building new versions of.
+ ///
+ [Required]
+ public ITaskItem[] Solutions { get; set; }
+
+ [Required]
+ public ITaskItem[] Artifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] Dependencies { get; set; }
+
+ [Required]
+ public string Properties { get; set; }
+
+ public string StartGraphAt { get; set; }
+
+ ///
+ /// The order in which to build repositories
+ ///
+ [Output]
+ public ITaskItem[] RepositoryBuildOrder { get; set; }
+
+ public void Cancel()
+ {
+ _cts.Cancel();
+ }
+
+ public override bool Execute()
+ {
+ var packageArtifacts = Artifacts.Select(ArtifactInfo.Parse)
+ .OfType()
+ .Where(p => !p.IsSymbolsArtifact);
+
+ var factory = new SolutionInfoFactory(Log, BuildEngine5);
+ var props = MSBuildListSplitter.GetNamedProperties(Properties);
+
+ Log.LogMessage(MessageImportance.High, $"Beginning cross-repo analysis on {Solutions.Length} solutions. Hang tight...");
+
+ var solutions = factory.Create(Solutions, props, _cts.Token);
+ Log.LogMessage($"Found {solutions.Count} and {solutions.Sum(p => p.Projects.Count)} projects");
+
+ if (_cts.IsCancellationRequested)
+ {
+ return false;
+ }
+
+ EnsureConsistentGraph(packageArtifacts, solutions);
+ RepositoryBuildOrder = GetRepositoryBuildOrder(packageArtifacts, solutions.Where(s => s.ShouldBuild));
+
+ return !Log.HasLoggedErrors;
+ }
+
+ private struct VersionMismatch
+ {
+ public SolutionInfo Solution;
+ public ProjectInfo Project;
+ public string PackageId;
+ public string ActualVersion;
+ public NuGetVersion ExpectedVersion;
+ }
+
+ private void EnsureConsistentGraph(IEnumerable packages, IEnumerable solutions)
+ {
+ // ensure versions cascade
+ var buildPackageMap = packages.ToDictionary(p => p.PackageInfo.Id, p => p, StringComparer.OrdinalIgnoreCase);
+ var dependencyMap = new Dictionary>(StringComparer.OrdinalIgnoreCase);
+ foreach (var dep in Dependencies)
+ {
+ if (!dependencyMap.TryGetValue(dep.ItemSpec, out var versions))
+ {
+ dependencyMap[dep.ItemSpec] = versions = new List();
+ }
+ else if (dep.GetMetadata("NoWarn") == null || dep.GetMetadata("NoWarn").IndexOf("KRB" + KoreBuildErrors.MultipleExternalDependencyVersions) < 0)
+ {
+ Log.LogKoreBuildWarning(
+ KoreBuildErrors.MultipleExternalDependencyVersions,
+ message: $"Multiple versions of external dependency '{dep.ItemSpec}' are defined. In most cases, there should only be one version of external dependencies.");
+ }
+ versions.Add(dep.GetMetadata("Version"));
+ }
+
+ var inconsistentVersions = new List();
+ var reposThatShouldPatch = new HashSet();
+
+ // TODO cleanup the 4-deep nested loops
+ foreach (var solution in solutions)
+ foreach (var project in solution.Projects)
+ foreach (var tfm in project.Frameworks)
+ foreach (var dependency in tfm.Dependencies)
+ {
+ if (!buildPackageMap.TryGetValue(dependency.Key, out var package))
+ {
+ // This dependency is not one of the packages that will be compiled by this run of Universe.
+ if (!dependencyMap.TryGetValue(dependency.Key, out var externalVersions)
+ || !externalVersions.Contains(dependency.Value.Version))
+ {
+ Log.LogKoreBuildError(
+ project.FullPath,
+ KoreBuildErrors.UndefinedExternalDependency,
+ message: $"Undefined external dependency on {dependency.Key}/{dependency.Value.Version}");
+ }
+ continue;
+ }
+
+ var refVersion = VersionRange.Parse(dependency.Value.Version);
+ if (refVersion.IsFloating && refVersion.Float.Satisfies(package.PackageInfo.Version))
+ {
+ continue;
+ }
+ else if (package.PackageInfo.Version.Equals(refVersion.MinVersion))
+ {
+ continue;
+ }
+
+ if (!solution.ShouldBuild)
+ {
+ reposThatShouldPatch.Add(Path.GetFileName(Path.GetDirectoryName(solution.FullPath)));
+ }
+
+ inconsistentVersions.Add(new VersionMismatch
+ {
+ Solution = solution,
+ Project = project,
+ PackageId = dependency.Key,
+ ActualVersion = dependency.Value.Version,
+ ExpectedVersion = package.PackageInfo.Version,
+ });
+ }
+
+ if (inconsistentVersions.Count != 0)
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine();
+ sb.AppendLine($"Repos are inconsistent. The following projects have PackageReferences that should be updated");
+ foreach (var solution in inconsistentVersions.GroupBy(p => p.Solution.FullPath))
+ {
+ sb.Append(" - ").AppendLine(Path.GetFileName(solution.Key));
+ foreach (var project in solution.GroupBy(p => p.Project.FullPath))
+ {
+ sb.Append(" - ").AppendLine(Path.GetFileName(project.Key));
+ foreach (var mismatchedReference in project)
+ {
+ sb.AppendLine($" + {mismatchedReference.PackageId}/{{{mismatchedReference.ActualVersion} => {mismatchedReference.ExpectedVersion}}}");
+ }
+ }
+ }
+ sb.AppendLine();
+ Log.LogMessage(MessageImportance.High, sb.ToString());
+ Log.LogError("Package versions are inconsistent. See build log for details.");
+ }
+
+ foreach (var repo in reposThatShouldPatch)
+ {
+ Log.LogError($"{repo} should not be a 'ShippedRepository'. Version changes in other repositories mean it should be patched to perserve cascading version upgrades.");
+ }
+ }
+
+ private ITaskItem[] GetRepositoryBuildOrder(IEnumerable artifacts, IEnumerable solutions)
+ {
+ var repositories = solutions.Select(s =>
+ {
+ var repoName = Path.GetFileName(Path.GetDirectoryName(s.FullPath));
+ var repo = new Repository(repoName)
+ {
+ RootDir = Path.GetDirectoryName(s.FullPath)
+ };
+
+ var packages = artifacts.Where(a => a.RepoName.Equals(repoName, StringComparison.OrdinalIgnoreCase)).ToList();
+
+ foreach (var proj in s.Projects)
+ {
+ var projectGroup = packages.Any(p => p.PackageInfo.Id == proj.PackageId)
+ ? repo.Projects
+ : repo.SupportProjects;
+
+ projectGroup.Add(new Project(proj.PackageId)
+ {
+ Repository = repo,
+ PackageReferences = new HashSet(proj
+ .Frameworks
+ .SelectMany(f => f.Dependencies.Keys)
+ .Concat(proj.Tools.Select(t => t.Id)), StringComparer.OrdinalIgnoreCase),
+ });
+ }
+
+ return repo;
+ }).ToList();
+
+ var graph = GraphBuilder.Generate(repositories, StartGraphAt, Log);
+ var repositoriesWithOrder = new List<(ITaskItem repository, int order)>();
+ foreach (var repository in repositories)
+ {
+ var graphNodeRepository = graph.FirstOrDefault(g => g.Repository.Name == repository.Name);
+ if (graphNodeRepository == null)
+ {
+ // StartGraphAt was specified so the graph is incomplete.
+ continue;
+ }
+
+ var order = TopologicalSort.GetOrder(graphNodeRepository);
+ var repositoryTaskItem = new TaskItem(repository.Name);
+ repositoryTaskItem.SetMetadata("Order", order.ToString());
+ repositoryTaskItem.SetMetadata("RootPath", repository.RootDir);
+ repositoriesWithOrder.Add((repositoryTaskItem, order));
+ }
+
+ Log.LogMessage(MessageImportance.High, "Repository build order:");
+ foreach (var buildGroup in repositoriesWithOrder.GroupBy(r => r.order).OrderBy(g => g.Key))
+ {
+ var buildGroupRepos = buildGroup.Select(b => b.repository.ItemSpec);
+ Log.LogMessage(MessageImportance.High, $"{buildGroup.Key.ToString().PadLeft(2, ' ')}: {string.Join(", ", buildGroupRepos)}");
+ }
+
+ return repositoriesWithOrder
+ .OrderBy(r => r.order)
+ .Select(r => r.repository)
+ .ToArray();
+ }
+ }
+}
diff --git a/build/tasks/BuildGraph/DependencyGraphSpecProvider.cs b/build/tasks/BuildGraph/DependencyGraphSpecProvider.cs
deleted file mode 100644
index d16600578a..0000000000
--- a/build/tasks/BuildGraph/DependencyGraphSpecProvider.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.IO;
-using NuGet.ProjectModel;
-
-namespace RepoTools.BuildGraph
-{
- public class DependencyGraphSpecProvider
- {
- readonly string _packageSpecDirectory;
-
- public DependencyGraphSpecProvider(string packageSpecDirectory)
- {
- _packageSpecDirectory = packageSpecDirectory;
- }
-
- public DependencyGraphSpec GetDependencyGraphSpec(string repositoryName, string solutionPath)
- {
- var outputFile = Path.Combine(_packageSpecDirectory, repositoryName, Path.GetFileName(solutionPath) + ".json");
-
- if (!File.Exists(outputFile))
- {
- return null;
- }
-
- return DependencyGraphSpec.Load(outputFile);
- }
- }
-}
diff --git a/build/tasks/BuildGraph/Project.cs b/build/tasks/BuildGraph/Project.cs
index 72b5eee254..ad03468a61 100644
--- a/build/tasks/BuildGraph/Project.cs
+++ b/build/tasks/BuildGraph/Project.cs
@@ -23,6 +23,6 @@ namespace RepoTools.BuildGraph
public Repository Repository { get; set; }
- public ISet PackageReferences { get; } = new HashSet(StringComparer.OrdinalIgnoreCase);
+ public ISet PackageReferences { get; set; } = new HashSet(StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/build/tasks/BuildGraph/Repository.cs b/build/tasks/BuildGraph/Repository.cs
index a72137739e..e5bdaf414e 100644
--- a/build/tasks/BuildGraph/Repository.cs
+++ b/build/tasks/BuildGraph/Repository.cs
@@ -4,11 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.IO;
using System.Linq;
-using System.Threading.Tasks;
-using NuGet.LibraryModel;
-using NuGet.ProjectModel;
namespace RepoTools.BuildGraph
{
@@ -22,111 +18,16 @@ namespace RepoTools.BuildGraph
public string Name { get; private set; }
+ public string RootDir { get; set; }
+
public IList Projects { get; } = new List();
public IList SupportProjects { get; } = new List();
public IEnumerable AllProjects => Projects.Concat(SupportProjects);
- public static IList ReadAllRepositories(IList repositoryPaths, DependencyGraphSpecProvider provider)
- {
- var repositories = new Repository[repositoryPaths.Count];
-
- Parallel.For(0, repositoryPaths.Count, new ParallelOptions { MaxDegreeOfParallelism = 6 }, i =>
- {
- var repositoryPath = repositoryPaths[i];
- var repositoryName = Path.GetFileName(repositoryPath.TrimEnd(new [] { '\\', '/' }));
- var repository = Read(provider, repositoryName, repositoryPath);
- repositories[i] = repository;
- });
-
- return repositories;
- }
-
public bool Equals(Repository other) => string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Name);
-
- private static Repository Read(DependencyGraphSpecProvider provider, string name, string repositoryPath)
- {
- var repository = new Repository(name);
-
- ReadSharedSourceProjects(Path.Combine(repositoryPath, "shared"), repository, repository.Projects);
-
- var srcDirectory = Path.GetFullPath(Path.Combine(repositoryPath, "src"))
- .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
-
- var solutionFiles = Directory.EnumerateFiles(repositoryPath, "*.sln");
- foreach (var file in solutionFiles)
- {
- var spec = provider.GetDependencyGraphSpec(name, file);
- if (spec == null)
- {
- continue;
- }
-
- var projects = spec.Projects.OrderBy(p => p.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference ? 0 : 1);
- foreach (var specProject in projects)
- {
- var projectPath = Path.GetFullPath(specProject.FilePath)
- .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
-
- var projectGroup = projectPath.StartsWith(srcDirectory, StringComparison.OrdinalIgnoreCase) ?
- repository.Projects :
- repository.SupportProjects;
-
- var project = projectGroup.FirstOrDefault(f => f.Path == specProject.FilePath);
- if (project == null)
- {
- project = new Project(specProject.Name)
- {
- Repository = repository,
- Path = specProject.FilePath,
- Version = specProject.Version?.ToString(),
- };
-
- projectGroup.Add(project);
- }
-
- foreach (var package in GetPackageReferences(specProject))
- {
- project.PackageReferences.Add(package);
- }
- }
- }
-
- return repository;
- }
-
- private static List GetPackageReferences(PackageSpec specProject)
- {
- var allDependencies = Enumerable.Concat(
- specProject.Dependencies,
- specProject.TargetFrameworks.SelectMany(tfm => tfm.Dependencies))
- .Distinct();
-
- var packageReferences = allDependencies
- .Where(d => d.LibraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package))
- .Select(d => d.Name)
- .ToList();
- return packageReferences;
- }
-
- private static void ReadSharedSourceProjects(string sharedSourceProjectsRoot, Repository repository, IList projects)
- {
- if (!Directory.Exists(sharedSourceProjectsRoot))
- {
- return;
- }
-
- foreach (var directory in new DirectoryInfo(sharedSourceProjectsRoot).EnumerateDirectories())
- {
- var project = new Project(directory.Name)
- {
- Repository = repository,
- };
- projects.Add(project);
- }
- }
}
}
diff --git a/build/tasks/CalculateBuildGraph.cs b/build/tasks/CalculateBuildGraph.cs
deleted file mode 100644
index 5d922f7d39..0000000000
--- a/build/tasks/CalculateBuildGraph.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using RepoTools.BuildGraph;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace RepoTasks
-{
- public class CalculateBuildGraph : Task
- {
- [Required]
- public ITaskItem[] Repositories { get; set; }
-
- ///
- /// Directory that contains the package spec files.
- ///
- [Required]
- public string PackageSpecsDirectory { get; set; }
-
- ///
- /// Default to use for packages that may be produced from nuspec, not csproj. (e.g. .Sources packages).
- ///
- [Required]
- public string DefaultPackageVersion { get; set; }
-
- ///
- /// The repository at which to root the graph at
- ///
- public string StartGraphAt { get; set; }
-
- [Output]
- public ITaskItem[] RepositoriesToBuildInOrder { get; set; }
-
- public override bool Execute()
- {
- var graphSpecProvider = new DependencyGraphSpecProvider(PackageSpecsDirectory.Trim());
-
- var repositoryPaths = Repositories.Select(r => r.GetMetadata("RootPath")).ToList();
- var repositories = Repository.ReadAllRepositories(repositoryPaths, graphSpecProvider);
-
- var graph = GraphBuilder.Generate(repositories, StartGraphAt, Log);
- var repositoriesWithOrder = new List<(ITaskItem repository, int order)>();
- foreach (var repositoryTaskItem in Repositories)
- {
- var repositoryName = repositoryTaskItem.ItemSpec;
- var graphNodeRepository = graph.FirstOrDefault(g => g.Repository.Name == repositoryName);
- if (graphNodeRepository == null)
- {
- // StartGraphAt was specified so the graph is incomplete.
- continue;
- }
-
- var order = TopologicalSort.GetOrder(graphNodeRepository);
- repositoryTaskItem.SetMetadata("Order", order.ToString());
- repositoriesWithOrder.Add((repositoryTaskItem, order));
- }
-
- Log.LogMessage(MessageImportance.High, "Repository build order:");
- foreach (var buildGroup in repositoriesWithOrder.GroupBy(r => r.order).OrderBy(g => g.Key))
- {
- var buildGroupRepos = buildGroup.Select(b => b.repository.ItemSpec);
- Log.LogMessage(MessageImportance.High, $"{buildGroup.Key.ToString().PadLeft(2, ' ')}: {string.Join(", ", buildGroupRepos)}");
- }
-
- RepositoriesToBuildInOrder = repositoriesWithOrder
- .OrderBy(r => r.order)
- .Select(r => r.repository)
- .ToArray();
-
- return true;
- }
- }
-}
diff --git a/build/tasks/ComposeNewStore.cs b/build/tasks/ComposeNewStore.cs
new file mode 100644
index 0000000000..90f601e0a2
--- /dev/null
+++ b/build/tasks/ComposeNewStore.cs
@@ -0,0 +1,131 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ public class ComposeNewStore : Task
+ {
+ [Required]
+ public ITaskItem[] ExistingManifests { get; set; }
+
+ [Required]
+ public ITaskItem[] NewManifests { get; set; }
+
+ [Required]
+ public ITaskItem[] RuntimeStoreFiles { get; set; }
+
+ [Required]
+ public ITaskItem[] RuntimeStoreSymbolFiles { get; set; }
+
+ [Required]
+ public string ManifestDestination { get; set; }
+
+ [Required]
+ public string StoreDestination { get; set; }
+
+ [Required]
+ public string SymbolsDestination { get; set; }
+
+ public override bool Execute()
+ {
+ var existingFiles = new Dictionary>();
+ var newRuntimeStoreFiles = new List();
+ var newRuntimeStoreSymbolFiles = new List();
+
+ // Construct database of existing assets
+ foreach (var manifest in ExistingManifests)
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(manifest.GetMetadata("FullPath"));
+ var storeArtifacts = xmlDoc.SelectSingleNode("/StoreArtifacts");
+
+ foreach (XmlNode artifact in storeArtifacts.ChildNodes)
+ {
+ if (existingFiles.TryGetValue(artifact.Attributes["Id"].Value, out var versions))
+ {
+ versions.Add(artifact.Attributes["Version"].Value);
+ }
+ else
+ {
+ existingFiles[artifact.Attributes["Id"].Value] = new HashSet{ artifact.Attributes["Version"].Value };
+ }
+ }
+ }
+
+ // Insert new runtime store files
+ foreach (var storeFile in RuntimeStoreFiles)
+ {
+ // format: {bitness}}/{tfm}}/{id}/{version}}/...
+ var recursiveDir = storeFile.GetMetadata("RecursiveDir");
+ var components = recursiveDir.Split(Path.DirectorySeparatorChar);
+ var id = components[2];
+ var version = components[3];
+
+ if (!existingFiles.TryGetValue(id, out var versions) || !versions.Contains(version))
+ {
+ var destinationDir = Path.Combine(StoreDestination, recursiveDir);
+ if (!Directory.Exists(Path.Combine(StoreDestination, recursiveDir)))
+ {
+ Directory.CreateDirectory(destinationDir);
+ }
+
+ File.Copy(storeFile.GetMetadata("FullPath"), Path.Combine(destinationDir, $"{storeFile.GetMetadata("Filename")}{storeFile.GetMetadata("Extension")}"), overwrite: true);
+ }
+ }
+
+ // Insert new runtime store files
+ foreach (var symbolFile in RuntimeStoreSymbolFiles)
+ {
+ // format: {bitness}}/{tfm}}/{id}/{version}}/...
+ var recursiveDir = symbolFile.GetMetadata("RecursiveDir");
+ var components = recursiveDir.Split(Path.DirectorySeparatorChar);
+ var id = components[2];
+ var version = components[3];
+
+ if (!existingFiles.TryGetValue(id, out var versions) || !versions.Contains(version))
+ {
+ var destinationDir = Path.Combine(SymbolsDestination, recursiveDir);
+ if (!Directory.Exists(Path.Combine(SymbolsDestination, recursiveDir)))
+ {
+ Directory.CreateDirectory(destinationDir);
+ }
+
+ File.Copy(symbolFile.GetMetadata("FullPath"), Path.Combine(destinationDir, $"{symbolFile.GetMetadata("Filename")}{symbolFile.GetMetadata("Extension")}"), overwrite: true);
+ }
+ }
+
+ // Purge existing packages from manifest
+ foreach (var newManifest in NewManifests)
+ {
+ var newManifestPath = newManifest.GetMetadata("FullPath");
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(newManifestPath);
+ var storeArtifacts = xmlDoc.SelectSingleNode("/StoreArtifacts");
+ var artifactsToRemove = new List();
+
+ foreach (XmlNode artifact in storeArtifacts.ChildNodes)
+ {
+ if (existingFiles.TryGetValue(artifact.Attributes["Id"].Value, out var versions) && versions.Contains(artifact.Attributes["Version"].Value))
+ {
+ artifactsToRemove.Add(artifact);
+ }
+ }
+
+ foreach (var artifactToRemove in artifactsToRemove)
+ {
+ storeArtifacts.RemoveChild(artifactToRemove);
+ }
+
+ xmlDoc.Save(ManifestDestination);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/ConsolidateManifests.cs b/build/tasks/ConsolidateManifests.cs
new file mode 100644
index 0000000000..12838855a6
--- /dev/null
+++ b/build/tasks/ConsolidateManifests.cs
@@ -0,0 +1,57 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ // Takes multiple runtime store manifests and create a consolidated manifest containing all unique entries.
+ public class ConsolidateManifests : Task
+ {
+ [Required]
+ public ITaskItem[] Manifests { get; set; }
+
+ [Required]
+ public string ManifestDestination { get; set; }
+
+ public override bool Execute()
+ {
+ var artifacts = new HashSet>();
+
+ // Construct database of all artifacts
+ foreach (var manifest in Manifests)
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(manifest.GetMetadata("FullPath"));
+ var storeArtifacts = xmlDoc.SelectSingleNode("/StoreArtifacts");
+
+ foreach (XmlNode artifact in storeArtifacts.ChildNodes)
+ {
+ artifacts.Add(new Tuple(artifact.Attributes["Id"].Value, artifact.Attributes["Version"].Value));
+ }
+ }
+
+
+ var consolidatedXmlDoc = new XmlDocument();
+ var packagesElement = consolidatedXmlDoc.CreateElement("StoreArtifacts");
+
+ foreach (var artifact in artifacts)
+ {
+ var packageElement = consolidatedXmlDoc.CreateElement("Package");
+ packageElement.SetAttribute("Id", artifact.Item1);
+ packageElement.SetAttribute("Version", artifact.Item2);
+
+ packagesElement.AppendChild(packageElement);
+ }
+
+ consolidatedXmlDoc.AppendChild(packagesElement);
+ consolidatedXmlDoc.Save(ManifestDestination);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/CopyPackagesToSplitFolders.cs b/build/tasks/CopyPackagesToSplitFolders.cs
index ca5ebf3544..b9ead3f5b6 100644
--- a/build/tasks/CopyPackagesToSplitFolders.cs
+++ b/build/tasks/CopyPackagesToSplitFolders.cs
@@ -7,7 +7,7 @@ using System.Text;
using Microsoft.Build.Framework;
using NuGet.Packaging;
using NuGet.Packaging.Core;
-using RepoTasks.ProjectModel;
+using RepoTasks.Utilities;
namespace RepoTasks
{
@@ -44,26 +44,22 @@ namespace RepoTasks
foreach (var file in Files)
{
- var isSymbolsPackage = file.ItemSpec.EndsWith(".symbols.nupkg", StringComparison.OrdinalIgnoreCase);
-
PackageIdentity identity;
using (var reader = new PackageArchiveReader(file.ItemSpec))
{
identity = reader.GetIdentity();
}
+ var isSymbolsPackage = file.ItemSpec.EndsWith(".symbols.nupkg", StringComparison.OrdinalIgnoreCase);
PackageCategory category;
if (isSymbolsPackage)
{
category = PackageCategory.Symbols;
}
- else
+ else if (!expectedPackages.TryGetCategory(identity.Id, out category))
{
- if (!expectedPackages.TryGetCategory(identity.Id, out category))
- {
- Log.LogError($"Unexpected package artifact with id: {identity.Id}");
- continue;
- }
+ Log.LogError($"Unexpected package artifact with id: {identity.Id}");
+ continue;
}
string destDir;
diff --git a/build/tasks/CreateCommonManifest.cs b/build/tasks/CreateCommonManifest.cs
new file mode 100644
index 0000000000..5a412fa8e9
--- /dev/null
+++ b/build/tasks/CreateCommonManifest.cs
@@ -0,0 +1,61 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ ///
+ /// Creates a common manifest file used for trimming publish output given a list of packages and package definitions containing their versions.
+ ///
+ public class CreateCommonManifest : Task
+ {
+ ///
+ /// The path for the common manifest file to be created.
+ ///
+ ///
+ [Required]
+ public string DestinationFilePath { get; set; }
+
+ ///
+ /// The packages to include in the common manifest file.
+ ///
+ ///
+ [Required]
+ public ITaskItem[] Packages { get; set; }
+
+ ///
+ /// The package definitions used for resolving package versions.
+ ///
+ ///
+ [Required]
+ public ITaskItem[] PackageDefinitions { get; set; }
+
+ public override bool Execute()
+ {
+ var xmlDoc = new XmlDocument();
+ var packagesElement = xmlDoc.CreateElement("StoreArtifacts");
+
+ foreach (var package in Packages)
+ {
+ var packageName = package.ItemSpec;
+ var packageElement = xmlDoc.CreateElement("Package");
+ packageElement.SetAttribute("Id", packageName);
+ packageElement.SetAttribute("Version", PackageDefinitions
+ .Where(p => string.Equals(p.GetMetadata("Name"), packageName, StringComparison.OrdinalIgnoreCase))
+ .Select(p => p.GetMetadata("Version")).Single());
+
+ packagesElement.AppendChild(packageElement);
+ }
+
+ xmlDoc.AppendChild(packagesElement);
+ xmlDoc.Save(DestinationFilePath);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/DownloadNuGetPackages.cs b/build/tasks/DownloadNuGetPackages.cs
new file mode 100644
index 0000000000..f1d0d6300b
--- /dev/null
+++ b/build/tasks/DownloadNuGetPackages.cs
@@ -0,0 +1,196 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using NuGet.Build;
+using NuGet.Commands;
+using NuGet.Configuration;
+using NuGet.DependencyResolver;
+using NuGet.Packaging.Core;
+using NuGet.Protocol;
+using NuGet.Protocol.Core.Types;
+using NuGet.Versioning;
+using Task = System.Threading.Tasks.Task;
+
+namespace RepoTasks
+{
+ public class DownloadNuGetPackages : Microsoft.Build.Utilities.Task, ICancelableTask
+ {
+ private static readonly Task FalseTask = Task.FromResult(false);
+ private readonly CancellationTokenSource _cts = new CancellationTokenSource();
+
+ [Required]
+ public ITaskItem[] Packages { get; set; }
+
+ [Required]
+ public string DestinationFolder { get; set; }
+
+ [Output]
+ public ITaskItem[] Files { get; set; }
+
+ public void Cancel() => _cts.Cancel();
+
+ public override bool Execute()
+ {
+ return ExecuteAsync().GetAwaiter().GetResult();
+ }
+
+ public async Task ExecuteAsync()
+ {
+ DestinationFolder = DestinationFolder.Replace('\\', '/');
+
+ var requests = new Dictionary>(StringComparer.OrdinalIgnoreCase);
+ var files = new List();
+ var downloadCount = 0;
+ foreach (var item in Packages)
+ {
+ var id = item.ItemSpec;
+ var rawVersion = item.GetMetadata("Version");
+ if (!NuGetVersion.TryParse(rawVersion, out var version))
+ {
+ Log.LogError($"Package '{id}' has an invalid 'Version' metadata value: '{rawVersion}'.");
+ return false;
+ }
+
+ var source = item.GetMetadata("Source");
+ if (string.IsNullOrEmpty(source))
+ {
+ Log.LogError($"Package '{id}' is missing the 'Source' metadata value.");
+ return false;
+ }
+
+ if (!requests.TryGetValue(source, out var packages))
+ {
+ packages = requests[source] = new List();
+ }
+
+ var request = new PackageIdentity(id, version);
+ var dest = GetExpectedOutputPath(request);
+ files.Add(new TaskItem(dest));
+ if (File.Exists(dest))
+ {
+ Log.LogMessage($"Skipping {request.Id} {request.Version}. Already exists in '{dest}'");
+ continue;
+ }
+ else
+ {
+ downloadCount++;
+ packages.Add(request);
+ }
+ }
+
+ Files = files.ToArray();
+
+ if (downloadCount == 0)
+ {
+ Log.LogMessage("All packages are downloaded.");
+ return true;
+ }
+
+ Directory.CreateDirectory(DestinationFolder);
+ var logger = new MSBuildLogger(Log);
+ var timer = Stopwatch.StartNew();
+
+ logger.LogMinimal($"Downloading {downloadCount} package(s)");
+
+ using (var cacheContext = new SourceCacheContext())
+ {
+ var defaultSettings = Settings.LoadDefaultSettings(root: null, configFileName: null, machineWideSettings: null);
+ var sourceProvider = new CachingSourceProvider(new PackageSourceProvider(defaultSettings));
+ var tasks = new List>();
+
+ foreach (var feed in requests)
+ {
+ var repo = sourceProvider.CreateRepository(new PackageSource(feed.Key));
+ tasks.Add(DownloadPackagesAsync(repo, feed.Value, cacheContext, logger, _cts.Token));
+ }
+
+ var all = Task.WhenAll(tasks);
+ var wait = TimeSpan.FromSeconds(Math.Max(downloadCount * 5, 120));
+ var delay = Task.Delay(wait);
+
+ var finished = await Task.WhenAny(all, delay);
+ if (ReferenceEquals(delay, finished))
+ {
+ Log.LogError($"Timed out after {wait.TotalSeconds}s");
+ Cancel();
+ return false;
+ }
+
+ if (!tasks.All(a => a.Result))
+ {
+ Log.LogError("Failed to download all packages");
+ return false;
+ }
+
+ timer.Stop();
+ logger.LogMinimal($"Finished downloading {downloadCount} package(s) in {timer.ElapsedMilliseconds}ms");
+ return true;
+ }
+ }
+
+ private async Task DownloadPackagesAsync(
+ SourceRepository repo,
+ IEnumerable requests,
+ SourceCacheContext cacheContext,
+ NuGet.Common.ILogger logger,
+ CancellationToken cancellationToken)
+ {
+ var remoteLibraryProvider = new SourceRepositoryDependencyProvider(repo, logger, cacheContext, ignoreFailedSources: false, ignoreWarning: false);
+ var downloads = new List>();
+ var metadataResource = await repo.GetResourceAsync();
+
+ foreach (var request in requests)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (metadataResource != null && !await metadataResource.Exists(request, logger, cancellationToken))
+ {
+ logger.LogError($"Package {request.Id} {request.Version} is not available on '{repo}'");
+ downloads.Add(FalseTask);
+ continue;
+ }
+
+ var download = DownloadPackageAsync(cacheContext, logger, remoteLibraryProvider, request, cancellationToken);
+ downloads.Add(download);
+ }
+
+ await Task.WhenAll(downloads);
+ return downloads.All(d => d.Result);
+ }
+
+ private async Task DownloadPackageAsync(SourceCacheContext cacheContext,
+ NuGet.Common.ILogger logger,
+ SourceRepositoryDependencyProvider remoteLibraryProvider,
+ PackageIdentity request,
+ CancellationToken cancellationToken)
+ {
+ var dest = GetExpectedOutputPath(request);
+ logger.LogInformation($"Downloading {request.Id} {request.Version} to '{dest}'");
+
+ using (var packageDependency = await remoteLibraryProvider.GetPackageDownloaderAsync(request, cacheContext, logger, cancellationToken))
+ {
+ if (!await packageDependency.CopyNupkgFileToAsync(dest, cancellationToken))
+ {
+ logger.LogError($"Could not download {request.Id} {request.Version} from {remoteLibraryProvider.Source}");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private string GetExpectedOutputPath(PackageIdentity request)
+ {
+ return Path.Combine(DestinationFolder, $"{request.Id.ToLowerInvariant()}.{request.Version.ToNormalizedString()}.nupkg");
+ }
+ }
+}
diff --git a/build/tasks/GeneratePackageVersionPropsFile.cs b/build/tasks/GeneratePackageVersionPropsFile.cs
new file mode 100644
index 0000000000..c007fd321f
--- /dev/null
+++ b/build/tasks/GeneratePackageVersionPropsFile.cs
@@ -0,0 +1,125 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using RepoTasks.ProjectModel;
+using RepoTasks.Utilities;
+using System.Text;
+
+namespace RepoTasks
+{
+ public class GeneratePackageVersionPropsFile : Task
+ {
+ [Required]
+ public ITaskItem[] Packages { get; set; }
+
+ [Required]
+ public string OutputPath { get; set; }
+
+ public override bool Execute()
+ {
+ OutputPath = OutputPath.Replace('\\', '/');
+ Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
+
+ var props = new XElement("PropertyGroup");
+ var root = new XElement("Project", props);
+ var doc = new XDocument(root);
+
+ props.Add(new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"));
+
+ var varNames = new HashSet();
+ var versionElements = new List();
+ foreach (var pkg in Packages)
+ {
+ var packageVersion = pkg.GetMetadata("Version");
+
+ if (string.IsNullOrEmpty(packageVersion))
+ {
+ Log.LogError("Package {0} is missing the Version metadata", pkg.ItemSpec);
+ continue;
+ }
+
+
+ string packageVarName;
+ if (!string.IsNullOrEmpty(pkg.GetMetadata("VariableName")))
+ {
+ packageVarName = pkg.GetMetadata("VariableName");
+ if (!packageVarName.EndsWith("Version", StringComparison.Ordinal))
+ {
+ Log.LogError("VariableName for {0} must end in 'Version'", pkg.ItemSpec);
+ continue;
+ }
+ }
+ else
+ {
+ packageVarName = GetVariableName(pkg.ItemSpec);
+ }
+
+ var packageTfm = pkg.GetMetadata("TargetFramework");
+ var key = $"{packageVarName}/{packageTfm}";
+ if (varNames.Contains(key))
+ {
+ Log.LogError("Multiple packages would produce {0} in the generated dependencies.props file. Set VariableName to differentiate the packages manually", key);
+ continue;
+ }
+ varNames.Add(key);
+ var elem = new XElement(packageVarName, packageVersion);
+ if (!string.IsNullOrEmpty(packageTfm))
+ {
+ elem.Add(new XAttribute("Condition", $" '$(TargetFramework)' == '{packageTfm}' "));
+ }
+ versionElements.Add(elem);
+ }
+
+ foreach (var item in versionElements.OrderBy(p => p.Name.ToString()))
+ {
+ props.Add(item);
+ }
+
+ var settings = new XmlWriterSettings
+ {
+ OmitXmlDeclaration = true,
+ Indent = true,
+ };
+ using (var writer = XmlWriter.Create(OutputPath, settings))
+ {
+ Log.LogMessage(MessageImportance.Normal, $"Generate {OutputPath}");
+ doc.Save(writer);
+ }
+ return !Log.HasLoggedErrors;
+ }
+
+ private string GetVariableName(string packageId)
+ {
+ var sb = new StringBuilder();
+ var first = true;
+ foreach (var ch in packageId)
+ {
+ if (ch == '.')
+ {
+ first = true;
+ continue;
+ }
+
+ if (first)
+ {
+ first = false;
+ sb.Append(char.ToUpperInvariant(ch));
+ }
+ else
+ {
+ sb.Append(ch);
+ }
+ }
+ sb.Append("PackageVersion");
+ return sb.ToString();
+ }
+ }
+}
diff --git a/build/tasks/GenerateRestoreSourcesPropsFile.cs b/build/tasks/GenerateRestoreSourcesPropsFile.cs
new file mode 100644
index 0000000000..2d27ba4e6a
--- /dev/null
+++ b/build/tasks/GenerateRestoreSourcesPropsFile.cs
@@ -0,0 +1,55 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ public class GenerateRestoreSourcesPropsFile : Task
+ {
+ [Required]
+ public ITaskItem[] Sources { get; set; }
+
+ [Required]
+ public string OutputPath { get; set; }
+
+ public override bool Execute()
+ {
+ OutputPath = OutputPath.Replace('\\', '/');
+ Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
+
+ var sources = new XElement("DotNetRestoreSources");
+ var propertyGroup = new XElement("PropertyGroup", sources);
+ var doc = new XDocument(new XElement("Project", propertyGroup));
+
+ propertyGroup.Add(new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"));
+
+ var sb = new StringBuilder();
+
+ foreach (var source in Sources)
+ {
+ sb.Append(source.ItemSpec).AppendLine(";");
+ }
+
+ sources.SetValue(sb.ToString());
+
+ var settings = new XmlWriterSettings
+ {
+ OmitXmlDeclaration = true,
+ };
+ using (var writer = XmlWriter.Create(OutputPath, settings))
+ {
+ Log.LogMessage(MessageImportance.Normal, $"Generate {OutputPath}");
+ doc.Save(writer);
+ }
+ return !Log.HasLoggedErrors;
+ }
+ }
+}
diff --git a/build/tasks/Logger/MSBuildLogger.cs b/build/tasks/Logger/MSBuildLogger.cs
new file mode 100644
index 0000000000..458bd698d9
--- /dev/null
+++ b/build/tasks/Logger/MSBuildLogger.cs
@@ -0,0 +1,200 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using NuGet.Common;
+
+namespace NuGet.Build
+{
+ ///
+ /// TaskLoggingHelper -> ILogger
+ ///
+ internal class MSBuildLogger : LoggerBase, Common.ILogger
+ {
+ private readonly TaskLoggingHelper _taskLogging;
+
+ private delegate void LogMessageWithDetails(string subcategory,
+ string code,
+ string helpKeyword,
+ string file,
+ int lineNumber,
+ int columnNumber,
+ int endLineNumber,
+ int endColumnNumber,
+ MessageImportance importance,
+ string message,
+ params object[] messageArgs);
+
+ private delegate void LogErrorWithDetails(string subcategory,
+ string code,
+ string helpKeyword,
+ string file,
+ int lineNumber,
+ int columnNumber,
+ int endLineNumber,
+ int endColumnNumber,
+ string message,
+ params object[] messageArgs);
+
+ private delegate void LogMessageAsString(MessageImportance importance,
+ string message,
+ params object[] messageArgs);
+
+ private delegate void LogErrorAsString(string message,
+ params object[] messageArgs);
+
+ public MSBuildLogger(TaskLoggingHelper taskLogging)
+ {
+ _taskLogging = taskLogging ?? throw new ArgumentNullException(nameof(taskLogging));
+ }
+
+ public override void Log(ILogMessage message)
+ {
+ if (DisplayMessage(message.Level))
+ {
+ if (RuntimeEnvironmentHelper.IsMono)
+ {
+ LogForMono(message);
+ return;
+ }
+ else
+ {
+ var logMessage = message as IRestoreLogMessage;
+
+ if (logMessage == null)
+ {
+ logMessage = new RestoreLogMessage(message.Level, message.Message)
+ {
+ Code = message.Code,
+ FilePath = message.ProjectPath
+ };
+ }
+ LogForNonMono(logMessage);
+ }
+ }
+ }
+
+ ///
+ /// Log using with metadata for non mono platforms.
+ ///
+ private void LogForNonMono(IRestoreLogMessage message)
+ {
+ switch (message.Level)
+ {
+ case LogLevel.Error:
+ LogError(message, _taskLogging.LogError, _taskLogging.LogError);
+ break;
+
+ case LogLevel.Warning:
+ LogError(message, _taskLogging.LogWarning, _taskLogging.LogWarning);
+ break;
+
+ case LogLevel.Minimal:
+ LogMessage(message, MessageImportance.High, _taskLogging.LogMessage, _taskLogging.LogMessage);
+ break;
+
+ case LogLevel.Information:
+ LogMessage(message, MessageImportance.Normal, _taskLogging.LogMessage, _taskLogging.LogMessage);
+ break;
+
+ case LogLevel.Debug:
+ case LogLevel.Verbose:
+ default:
+ // Default to LogLevel.Debug and low importance
+ LogMessage(message, MessageImportance.Low, _taskLogging.LogMessage, _taskLogging.LogMessage);
+ break;
+ }
+ }
+
+ ///
+ /// Log using basic methods to avoid missing methods on mono.
+ ///
+ private void LogForMono(ILogMessage message)
+ {
+ switch (message.Level)
+ {
+ case LogLevel.Error:
+ _taskLogging.LogError(message.Message);
+ break;
+
+ case LogLevel.Warning:
+ _taskLogging.LogWarning(message.Message);
+ break;
+
+ case LogLevel.Minimal:
+ _taskLogging.LogMessage(MessageImportance.High, message.Message);
+ break;
+
+ case LogLevel.Information:
+ _taskLogging.LogMessage(MessageImportance.Normal, message.Message);
+ break;
+
+ case LogLevel.Debug:
+ case LogLevel.Verbose:
+ default:
+ // Default to LogLevel.Debug and low importance
+ _taskLogging.LogMessage(MessageImportance.Low, message.Message);
+ break;
+ }
+
+ return;
+ }
+
+ private void LogMessage(IRestoreLogMessage logMessage,
+ MessageImportance importance,
+ LogMessageWithDetails logWithDetails,
+ LogMessageAsString logAsString)
+ {
+ if (logMessage.Code > NuGetLogCode.Undefined)
+ {
+ // NuGet does not currently have a subcategory while throwing logs, hence string.Empty
+ logWithDetails(string.Empty,
+ Enum.GetName(typeof(NuGetLogCode), logMessage.Code),
+ Enum.GetName(typeof(NuGetLogCode), logMessage.Code),
+ logMessage.FilePath,
+ logMessage.StartLineNumber,
+ logMessage.StartColumnNumber,
+ logMessage.EndLineNumber,
+ logMessage.EndColumnNumber,
+ importance,
+ logMessage.Message);
+ }
+ else
+ {
+ logAsString(importance, logMessage.Message);
+ }
+ }
+
+ private void LogError(IRestoreLogMessage logMessage,
+ LogErrorWithDetails logWithDetails,
+ LogErrorAsString logAsString)
+ {
+ if (logMessage.Code > NuGetLogCode.Undefined)
+ {
+ // NuGet does not currently have a subcategory while throwing logs, hence string.Empty
+ logWithDetails(string.Empty,
+ Enum.GetName(typeof(NuGetLogCode), logMessage.Code),
+ Enum.GetName(typeof(NuGetLogCode), logMessage.Code),
+ logMessage.FilePath,
+ logMessage.StartLineNumber,
+ logMessage.StartColumnNumber,
+ logMessage.EndLineNumber,
+ logMessage.EndColumnNumber,
+ logMessage.Message);
+ }
+ else
+ {
+ logAsString(logMessage.Message);
+ }
+ }
+
+ public override System.Threading.Tasks.Task LogAsync(ILogMessage message)
+ {
+ Log(message);
+
+ return System.Threading.Tasks.Task.FromResult(0);
+ }
+ }
+}
diff --git a/build/tasks/ProjectModel/DotNetCliReferenceInfo.cs b/build/tasks/ProjectModel/DotNetCliReferenceInfo.cs
new file mode 100644
index 0000000000..c490dab999
--- /dev/null
+++ b/build/tasks/ProjectModel/DotNetCliReferenceInfo.cs
@@ -0,0 +1,24 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class DotNetCliReferenceInfo
+ {
+ public DotNetCliReferenceInfo(string id, string version)
+ {
+ if (string.IsNullOrEmpty(id))
+ {
+ throw new ArgumentException(nameof(id));
+ }
+
+ Id = id;
+ Version = version;
+ }
+
+ public string Id { get; }
+ public string Version { get; }
+ }
+}
diff --git a/build/tasks/ProjectModel/PackageReferenceInfo.cs b/build/tasks/ProjectModel/PackageReferenceInfo.cs
new file mode 100644
index 0000000000..d01089d594
--- /dev/null
+++ b/build/tasks/ProjectModel/PackageReferenceInfo.cs
@@ -0,0 +1,29 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class PackageReferenceInfo
+ {
+ public PackageReferenceInfo(string id, string version, bool isImplicitlyDefined, IReadOnlyList noWarn)
+ {
+ if (string.IsNullOrEmpty(id))
+ {
+ throw new ArgumentException(nameof(id));
+ }
+
+ Id = id;
+ Version = version;
+ IsImplicitlyDefined = isImplicitlyDefined;
+ NoWarn = noWarn;
+ }
+
+ public string Id { get; }
+ public string Version { get; }
+ public bool IsImplicitlyDefined { get; }
+ public IReadOnlyList NoWarn { get; }
+ }
+}
diff --git a/build/tasks/ProjectModel/ProjectFrameworkInfo.cs b/build/tasks/ProjectModel/ProjectFrameworkInfo.cs
new file mode 100644
index 0000000000..35a212f9a1
--- /dev/null
+++ b/build/tasks/ProjectModel/ProjectFrameworkInfo.cs
@@ -0,0 +1,22 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NuGet.Frameworks;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class ProjectFrameworkInfo
+ {
+ public ProjectFrameworkInfo(NuGetFramework targetFramework, IReadOnlyDictionary dependencies)
+ {
+ TargetFramework = targetFramework ?? throw new ArgumentNullException(nameof(targetFramework));
+ Dependencies = dependencies ?? throw new ArgumentNullException(nameof(dependencies));
+ }
+
+ public NuGetFramework TargetFramework { get; }
+ public IReadOnlyDictionary Dependencies { get; }
+ }
+}
diff --git a/build/tasks/ProjectModel/ProjectInfo.cs b/build/tasks/ProjectModel/ProjectInfo.cs
new file mode 100644
index 0000000000..1dd4339185
--- /dev/null
+++ b/build/tasks/ProjectModel/ProjectInfo.cs
@@ -0,0 +1,48 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class ProjectInfo
+ {
+ public ProjectInfo(string fullPath,
+ string projectExtensionsPath,
+ IReadOnlyList frameworks,
+ IReadOnlyList tools,
+ bool isPackable,
+ string packageId,
+ string packageVersion)
+ {
+ if (!Path.IsPathRooted(fullPath))
+ {
+ throw new ArgumentException("Path must be absolute", nameof(fullPath));
+ }
+
+ Frameworks = frameworks ?? throw new ArgumentNullException(nameof(frameworks));
+ Tools = tools ?? throw new ArgumentNullException(nameof(tools));
+
+ FullPath = fullPath;
+ FileName = Path.GetFileName(fullPath);
+ Directory = Path.GetDirectoryName(FullPath);
+ ProjectExtensionsPath = projectExtensionsPath ?? Path.Combine(Directory, "obj");
+ IsPackable = isPackable;
+ PackageId = packageId;
+ PackageVersion = packageVersion;
+ }
+
+ public string FullPath { get; }
+ public string FileName { get; }
+ public string ProjectExtensionsPath { get; }
+ public string Directory { get; }
+ public string PackageId { get; }
+ public string PackageVersion { get; }
+ public bool IsPackable { get; }
+
+ public IReadOnlyList Frameworks { get; }
+ public IReadOnlyList Tools { get; }
+ }
+}
diff --git a/build/tasks/ProjectModel/ProjectInfoFactory.cs b/build/tasks/ProjectModel/ProjectInfoFactory.cs
new file mode 100644
index 0000000000..5c739f1784
--- /dev/null
+++ b/build/tasks/ProjectModel/ProjectInfoFactory.cs
@@ -0,0 +1,134 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NuGet.Frameworks;
+using RepoTasks.Utilities;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class ProjectInfoFactory
+ {
+ private readonly TaskLoggingHelper _logger;
+
+ public ProjectInfoFactory(TaskLoggingHelper logger)
+ {
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ public ProjectInfo Create(string path, ProjectCollection projectCollection)
+ {
+ var project = GetProject(path, projectCollection);
+ var instance = project.CreateProjectInstance(ProjectInstanceSettings.ImmutableWithFastItemLookup);
+ var projExtPath = instance.GetPropertyValue("MSBuildProjectExtensionsPath");
+
+ var targetFrameworks = instance.GetPropertyValue("TargetFrameworks");
+ var targetFramework = instance.GetPropertyValue("TargetFramework");
+
+ var frameworks = new List();
+ if (!string.IsNullOrEmpty(targetFrameworks) && string.IsNullOrEmpty(targetFramework))
+ {
+ // multi targeting
+ foreach (var tfm in targetFrameworks.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
+ {
+ project.SetGlobalProperty("TargetFramework", tfm);
+ var innerBuild = project.CreateProjectInstance(ProjectInstanceSettings.ImmutableWithFastItemLookup);
+
+ var tfmInfo = new ProjectFrameworkInfo(NuGetFramework.Parse(tfm), GetDependencies(innerBuild));
+
+ frameworks.Add(tfmInfo);
+ }
+
+ project.RemoveGlobalProperty("TargetFramework");
+ }
+ else if (!string.IsNullOrEmpty(targetFramework))
+ {
+ var tfmInfo = new ProjectFrameworkInfo(NuGetFramework.Parse(targetFramework), GetDependencies(instance));
+
+ frameworks.Add(tfmInfo);
+ }
+
+ var projectDir = Path.GetDirectoryName(path);
+
+ var tools = GetTools(instance).ToArray();
+ bool.TryParse(instance.GetPropertyValue("IsPackable"), out var isPackable);
+ var packageId = instance.GetPropertyValue("PackageId");
+ var packageVersion = instance.GetPropertyValue("PackageVersion");
+
+ return new ProjectInfo(path,
+ projExtPath,
+ frameworks,
+ tools,
+ isPackable,
+ packageId,
+ packageVersion);
+ }
+
+ private static object _projLock = new object();
+
+ private static Project GetProject(string path, ProjectCollection projectCollection)
+ {
+ var projects = projectCollection.GetLoadedProjects(path);
+ foreach(var proj in projects)
+ {
+ if (proj.GetPropertyValue("DesignTimeBuild") == "true")
+ {
+ return proj;
+ }
+ }
+
+ var xml = ProjectRootElement.Open(path, projectCollection);
+ var globalProps = new Dictionary()
+ {
+ ["DesignTimeBuild"] = "true",
+ };
+
+ var project = new Project(xml,
+ globalProps,
+ toolsVersion: "15.0",
+ projectCollection: projectCollection)
+ {
+ IsBuildEnabled = false
+ };
+
+ return project;
+ }
+
+ private IReadOnlyDictionary GetDependencies(ProjectInstance project)
+ {
+ var references = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ foreach (var item in project.GetItems("PackageReference"))
+ {
+ bool.TryParse(item.GetMetadataValue("IsImplicitlyDefined"), out var isImplicit);
+ var noWarn = item.GetMetadataValue("NoWarn");
+ IReadOnlyList noWarnItems = string.IsNullOrEmpty(noWarn)
+ ? Array.Empty()
+ : MSBuildListSplitter.SplitItemList(noWarn).ToArray();
+
+ var info = new PackageReferenceInfo(item.EvaluatedInclude, item.GetMetadataValue("Version"), isImplicit, noWarnItems);
+
+ if (references.ContainsKey(info.Id))
+ {
+ _logger.LogKoreBuildWarning(project.ProjectFileLocation.File, KoreBuildErrors.DuplicatePackageReference, $"Found a duplicate PackageReference for {info.Id}. Restore results may be unpredictable.");
+ }
+
+ references[info.Id] = info;
+ }
+
+ return references;
+ }
+
+ private static IEnumerable GetTools(ProjectInstance project)
+ {
+ return project.GetItems("DotNetCliToolReference").Select(item =>
+ new DotNetCliReferenceInfo(item.EvaluatedInclude, item.GetMetadataValue("Version")));
+ }
+ }
+}
diff --git a/build/tasks/ProjectModel/SolutionInfo.cs b/build/tasks/ProjectModel/SolutionInfo.cs
new file mode 100644
index 0000000000..5fe51132db
--- /dev/null
+++ b/build/tasks/ProjectModel/SolutionInfo.cs
@@ -0,0 +1,34 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class SolutionInfo
+ {
+ public SolutionInfo(string fullPath, string configName, IReadOnlyList projects, bool shouldBuild)
+ {
+ if (string.IsNullOrEmpty(fullPath))
+ {
+ throw new ArgumentException(nameof(fullPath));
+ }
+
+ if (string.IsNullOrEmpty(configName))
+ {
+ throw new ArgumentException(nameof(configName));
+ }
+
+ FullPath = fullPath;
+ ConfigName = configName;
+ Projects = projects ?? throw new ArgumentNullException(nameof(projects));
+ ShouldBuild = shouldBuild;
+ }
+
+ public string FullPath { get; }
+ public string ConfigName { get; }
+ public IReadOnlyList Projects { get; }
+ public bool ShouldBuild { get; }
+ }
+}
diff --git a/build/tasks/ProjectModel/SolutionInfoFactory.cs b/build/tasks/ProjectModel/SolutionInfoFactory.cs
new file mode 100644
index 0000000000..9ea368cc0a
--- /dev/null
+++ b/build/tasks/ProjectModel/SolutionInfoFactory.cs
@@ -0,0 +1,134 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using RepoTasks.Utilities;
+
+namespace RepoTasks.ProjectModel
+{
+ internal class SolutionInfoFactory
+ {
+ private readonly TaskLoggingHelper _logger;
+ private readonly IBuildEngine4 _buildEngine;
+
+ public SolutionInfoFactory(TaskLoggingHelper logger, IBuildEngine4 buildEngine)
+ {
+ _logger = logger;
+ _buildEngine = buildEngine;
+ }
+
+ public IReadOnlyList Create(IEnumerable solutionItems, IDictionary properties, CancellationToken ct)
+ {
+ var timer = Stopwatch.StartNew();
+
+ var solutions = new ConcurrentBag();
+
+ Parallel.ForEach(solutionItems, solution =>
+ {
+ if (ct.IsCancellationRequested)
+ {
+ return;
+ }
+
+ var solutionFile = solution.ItemSpec.Replace('\\', '/');
+ var solutionProps = new Dictionary(properties, StringComparer.OrdinalIgnoreCase);
+ foreach (var prop in MSBuildListSplitter.GetNamedProperties(solution.GetMetadata("AdditionalProperties")))
+ {
+ solutionProps[prop.Key] = prop.Value;
+ }
+
+ if (solutionProps.TryGetValue("Configuration", out var configName))
+ {
+ solutionProps["Configuration"] = configName = "Debug";
+ }
+
+ var key = $"SlnInfo:{solutionFile}:{configName}";
+ var obj = _buildEngine.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build);
+
+ if (obj is SolutionInfo cachedSlnInfo)
+ {
+ solutions.Add(cachedSlnInfo);
+ return;
+ }
+
+ _logger.LogMessage($"Analyzing {solutionFile} ({configName})");
+ var projects = new ConcurrentBag();
+ var projectFiles = GetProjectsForSolutionConfig(solutionFile, configName);
+ using (var projCollection = new ProjectCollection(solutionProps) { IsBuildEnabled = false })
+ {
+ Parallel.ForEach(projectFiles, projectFile =>
+ {
+ if (ct.IsCancellationRequested)
+ {
+ return;
+ }
+
+ try
+ {
+ projects.Add(new ProjectInfoFactory(_logger).Create(projectFile, projCollection));
+ }
+ catch (Exception ex)
+ {
+ _logger.LogErrorFromException(ex);
+ }
+ });
+ }
+
+ bool.TryParse(solution.GetMetadata("Build"), out var shouldBuild);
+
+ var solutionInfo = new SolutionInfo(
+ solutionFile,
+ configName,
+ projects.ToArray(),
+ shouldBuild);
+
+ _buildEngine.RegisterTaskObject(key, solutionInfo, RegisteredTaskObjectLifetime.Build, allowEarlyCollection: true);
+
+ solutions.Add(solutionInfo);
+ });
+
+ timer.Stop();
+ _logger.LogMessage(MessageImportance.High, $"Finished design-time build in {timer.ElapsedMilliseconds}ms");
+ return solutions.ToArray();
+ }
+
+ private IList GetProjectsForSolutionConfig(string filePath, string configName)
+ {
+ var sln = SolutionFile.Parse(filePath);
+
+ if (string.IsNullOrEmpty(configName))
+ {
+ configName = sln.GetDefaultConfigurationName();
+ }
+
+ var projects = new List();
+
+ var config = sln.SolutionConfigurations.FirstOrDefault(c => c.ConfigurationName == configName);
+ if (config == null)
+ {
+ throw new InvalidOperationException($"A solution configuration by the name of '{configName}' was not found in '{filePath}'");
+ }
+
+ foreach (var project in sln.ProjectsInOrder
+ .Where(p =>
+ p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat // skips solution folders
+ && p.ProjectConfigurations.TryGetValue(config.FullName, out var projectConfig)
+ && projectConfig.IncludeInBuild))
+ {
+ projects.Add(project.AbsolutePath.Replace('\\', '/'));
+ }
+
+ return projects;
+ }
+ }
+}
diff --git a/build/tasks/ReplaceInFile.cs b/build/tasks/ReplaceInFile.cs
new file mode 100644
index 0000000000..6833277787
--- /dev/null
+++ b/build/tasks/ReplaceInFile.cs
@@ -0,0 +1,33 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ public class ReplaceInFile : Task
+ {
+ [Required]
+ public string Filename { get; set; }
+
+ [Required]
+ public ITaskItem[] Items { get; set; }
+
+ public override bool Execute()
+ {
+ var fileText = File.ReadAllText(Filename);
+
+ foreach (var item in Items)
+ {
+ fileText = fileText.Replace(item.ItemSpec, item.GetMetadata("Replacement"));
+ }
+
+ File.WriteAllText(Filename, fileText);
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj
index eaf591d21b..39574ccdb1 100644
--- a/build/tasks/RepoTasks.csproj
+++ b/build/tasks/RepoTasks.csproj
@@ -3,11 +3,10 @@
netstandard2.0
- 2.0.0-*
-
+
diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks
index b3cb598991..5410effb57 100644
--- a/build/tasks/RepoTasks.tasks
+++ b/build/tasks/RepoTasks.tasks
@@ -3,7 +3,19 @@
<_RepoTaskAssembly>$(MSBuildThisFileDirectory)bin\publish\RepoTasks.dll
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/tasks/ResolveHostingStartupPackages.cs b/build/tasks/ResolveHostingStartupPackages.cs
new file mode 100644
index 0000000000..8bfc27399c
--- /dev/null
+++ b/build/tasks/ResolveHostingStartupPackages.cs
@@ -0,0 +1,30 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks
+{
+ public class ResolveHostingStartupPackages : Task
+ {
+ [Required]
+ public ITaskItem[] BuildArtifacts { get; set; }
+
+ [Required]
+ public ITaskItem[] PackageArtifacts { get; set; }
+
+ [Output]
+ public ITaskItem[] HostingStartupArtifacts { get; set; }
+
+ public override bool Execute()
+ {
+ // Parse input
+ var hostingStartupArtifacts = PackageArtifacts.Where(p => p.GetMetadata("HostingStartup") == "true");
+ HostingStartupArtifacts = BuildArtifacts.Where(p => hostingStartupArtifacts.Any(h => h.GetMetadata("Identity") == p.GetMetadata("PackageId"))).ToArray();
+
+ return true;
+ }
+ }
+}
diff --git a/build/tasks/TrimDeps.cs b/build/tasks/TrimDeps.cs
new file mode 100644
index 0000000000..b63bdb35cc
--- /dev/null
+++ b/build/tasks/TrimDeps.cs
@@ -0,0 +1,60 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace RepoTasks
+{
+ public class TrimDeps : Task
+ {
+ [Required]
+ public ITaskItem[] DepsFiles { get; set; }
+
+ public override bool Execute()
+ {
+ foreach (var depsFile in DepsFiles)
+ {
+ ChangeEntryPointLibraryName(depsFile.GetMetadata("Identity"));
+ }
+
+ // Parse input
+ return true;
+ }
+
+
+ private void ChangeEntryPointLibraryName(string depsFile)
+ {
+ JToken deps;
+ using (var file = File.OpenText(depsFile))
+ using (JsonTextReader reader = new JsonTextReader(file))
+ {
+ deps = JObject.ReadFrom(reader);
+ }
+
+ foreach (JProperty target in deps["targets"])
+ {
+ var targetLibrary = target.Value.Children().FirstOrDefault();
+ if (targetLibrary == null)
+ {
+ continue;
+ }
+
+ targetLibrary.Remove();
+ }
+
+ var library = deps["libraries"].Children().First();
+ library.Remove();
+
+ using (var file = File.CreateText(depsFile))
+ using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented })
+ {
+ deps.WriteTo(writer);
+ }
+ }
+ }
+}
diff --git a/build/tasks/Utilities/ArtifactInfo.cs b/build/tasks/Utilities/ArtifactInfo.cs
new file mode 100644
index 0000000000..6e35289a3b
--- /dev/null
+++ b/build/tasks/Utilities/ArtifactInfo.cs
@@ -0,0 +1,64 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.IO;
+using System.Linq;
+using NuGet.Frameworks;
+using NuGet.Packaging;
+using NuGet.Packaging.Core;
+using NuGet.Versioning;
+using Microsoft.Build.Framework;
+using RepoTasks.ProjectModel;
+
+namespace RepoTasks.Utilities
+{
+ internal abstract class ArtifactInfo
+ {
+ public static ArtifactInfo Parse(ITaskItem item)
+ {
+ ArtifactInfo info;
+ switch (item.GetMetadata("ArtifactType").ToLowerInvariant())
+ {
+ case "nugetpackage":
+ info = new Package { PackageInfo = GetPackageInfo(item) };
+ break;
+ case "nugetsymbolspackage":
+ info = new Package { PackageInfo = GetPackageInfo(item), IsSymbolsArtifact = true };
+ break;
+ default:
+ throw new InvalidDataException($"Unrecognized artifact type: {item.GetMetadata("ArtifactType")} for artifact {item.ItemSpec}");
+ }
+
+ info.RepositoryRoot = item.GetMetadata("RepositoryRoot")?.TrimEnd(new [] { '\\', '/' });
+
+ if (!string.IsNullOrEmpty(info.RepositoryRoot))
+ {
+ info.RepoName = Path.GetFileName(info.RepositoryRoot);
+ }
+
+ return info;
+ }
+
+ public string RepositoryRoot { get; private set; }
+ public string RepoName { get; private set; }
+
+ public class Package : ArtifactInfo
+ {
+ public PackageInfo PackageInfo { get; set; }
+ public bool IsSymbolsArtifact { get; set; }
+ }
+
+ private static PackageInfo GetPackageInfo(ITaskItem item)
+ {
+ return new PackageInfo(
+ item.GetMetadata("PackageId"),
+ NuGetVersion.Parse(item.GetMetadata("Version")),
+ string.IsNullOrEmpty(item.GetMetadata("TargetFramework"))
+ ? MSBuildListSplitter.SplitItemList(item.GetMetadata("TargetFramework")).Select(s => new PackageDependencyGroup(NuGetFramework.Parse(s), Array.Empty())).ToArray()
+ : new [] { new PackageDependencyGroup(NuGetFramework.Parse(item.GetMetadata("TargetFramework")), Array.Empty()) },
+ Path.GetDirectoryName(item.ItemSpec),
+ item.GetMetadata("PackageType"));
+ }
+ }
+}
diff --git a/build/tasks/Utilities/KoreBuildErrors.cs b/build/tasks/Utilities/KoreBuildErrors.cs
new file mode 100644
index 0000000000..f21bde3436
--- /dev/null
+++ b/build/tasks/Utilities/KoreBuildErrors.cs
@@ -0,0 +1,32 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace RepoTasks.Utilities
+{
+ public static class KoreBuildErrors
+ {
+ public const string Prefix = "KRB";
+
+ // Typically used in repos in Directory.Build.targets
+ public const int PackagesHaveNotYetBeenPinned = 1001;
+
+ // Warnings
+ public const int DotNetAssetVersionIsFloating = 2000;
+ public const int RepoVersionDoesNotMatchProjectVersion = 2001;
+ public const int RepoPackageVersionDoesNotMatchProjectPackageVersion = 2002;
+ public const int DuplicatePackageReference = 2003;
+ public const int MultipleExternalDependencyVersions = 2004;
+
+ // NuGet errors
+ public const int InvalidNuspecFile = 4001;
+ public const int PackageReferenceHasVersion = 4002;
+ public const int DotNetCliReferenceReferenceHasVersion = 4003;
+ public const int PackageVersionNotFoundInLineup = 4004;
+ public const int UndefinedExternalDependency = 4005;
+ public const int EmptyPackageReferenceVersion = 4006;
+
+ // Other unknown errors
+ public const int PolicyFailedToApply = 5000;
+ public const int UnknownPolicyType = 5001;
+ }
+}
diff --git a/build/tasks/Utilities/LoggingExtensions.cs b/build/tasks/Utilities/LoggingExtensions.cs
new file mode 100644
index 0000000000..833edb1aa4
--- /dev/null
+++ b/build/tasks/Utilities/LoggingExtensions.cs
@@ -0,0 +1,26 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.Build.Utilities;
+
+namespace RepoTasks.Utilities
+{
+ public static class LoggingExtensions
+ {
+ public static void LogKoreBuildError(this TaskLoggingHelper logger, int code, string message, params object[] messageArgs)
+ => LogKoreBuildError(logger, null, code, message, messageArgs: messageArgs);
+
+ public static void LogKoreBuildError(this TaskLoggingHelper logger, string filename, int code, string message, params object[] messageArgs)
+ {
+ logger.LogError(null, KoreBuildErrors.Prefix + code, null, filename, 0, 0, 0, 0, message, messageArgs: messageArgs);
+ }
+
+ public static void LogKoreBuildWarning(this TaskLoggingHelper logger, int code, string message, params object[] messageArgs)
+ => LogKoreBuildWarning(logger, null, code, message, messageArgs: messageArgs);
+
+ public static void LogKoreBuildWarning(this TaskLoggingHelper logger, string filename, int code, string message, params object[] messageArgs)
+ {
+ logger.LogWarning(null, KoreBuildErrors.Prefix + code, null, filename, 0, 0, 0, 0, message, messageArgs: messageArgs);
+ }
+ }
+}
diff --git a/build/tasks/Utilities/MSBuildListSplitter.cs b/build/tasks/Utilities/MSBuildListSplitter.cs
new file mode 100644
index 0000000000..de4ff8724b
--- /dev/null
+++ b/build/tasks/Utilities/MSBuildListSplitter.cs
@@ -0,0 +1,45 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace RepoTasks.Utilities
+{
+ internal static class MSBuildListSplitter
+ {
+ private static readonly char[] SemiColon = { ';' };
+
+ public static IEnumerable SplitItemList(string value)
+ {
+ return string.IsNullOrEmpty(value)
+ ? Enumerable.Empty()
+ : value.Split(SemiColon, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ public static Dictionary GetNamedProperties(string input)
+ {
+ var values = new Dictionary();
+ if (string.IsNullOrEmpty(input))
+ {
+ return values;
+ }
+
+ foreach (var item in input.Split(SemiColon, StringSplitOptions.RemoveEmptyEntries))
+ {
+ var splitIdx = item.IndexOf('=');
+ if (splitIdx <= 0)
+ {
+ continue;
+ }
+
+ var key = item.Substring(0, splitIdx).Trim();
+ var value = item.Substring(splitIdx + 1);
+ values[key] = value;
+ }
+
+ return values;
+ }
+ }
+}
diff --git a/build/tasks/ProjectModel/PackageCategory.cs b/build/tasks/Utilities/PackageCategory.cs
similarity index 90%
rename from build/tasks/ProjectModel/PackageCategory.cs
rename to build/tasks/Utilities/PackageCategory.cs
index 0baa60e7a4..78afe9cbce 100644
--- a/build/tasks/ProjectModel/PackageCategory.cs
+++ b/build/tasks/Utilities/PackageCategory.cs
@@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-namespace RepoTasks.ProjectModel
+namespace RepoTasks.Utilities
{
public enum PackageCategory
{
diff --git a/build/tasks/ProjectModel/PackageCollection.cs b/build/tasks/Utilities/PackageCollection.cs
similarity index 98%
rename from build/tasks/ProjectModel/PackageCollection.cs
rename to build/tasks/Utilities/PackageCollection.cs
index 56b998969a..d066360f53 100644
--- a/build/tasks/ProjectModel/PackageCollection.cs
+++ b/build/tasks/Utilities/PackageCollection.cs
@@ -7,7 +7,7 @@ using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
-namespace RepoTasks.ProjectModel
+namespace RepoTasks.Utilities
{
public class PackageCollection
{
diff --git a/build/tasks/Utilities/VersionUtilities.cs b/build/tasks/Utilities/VersionUtilities.cs
new file mode 100644
index 0000000000..042ecae378
--- /dev/null
+++ b/build/tasks/Utilities/VersionUtilities.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using NuGet.Versioning;
+
+namespace RepoTasks.Utilities
+{
+ public class VersionUtilities
+ {
+ public static string GetTimestampFreeVersion(string packageVersion)
+ {
+ var version = new NuGetVersion(packageVersion);
+ var updatedVersion = new NuGetVersion(version.Version, GetTimestampFreeReleaseLabel(version.Release));
+ return updatedVersion.ToNormalizedString();
+ }
+
+ public static string GetTimestampFreeReleaseLabel(string releaseLabel)
+ {
+ if (releaseLabel.StartsWith("rtm-", StringComparison.OrdinalIgnoreCase))
+ {
+ // E.g. change version 2.5.0-rtm-123123 to 2.5.0.
+ releaseLabel = string.Empty;
+ }
+ else
+ {
+ var timeStampFreeVersion = Environment.GetEnvironmentVariable("TIMESTAMP_FREE_VERSION");
+ if (string.IsNullOrEmpty(timeStampFreeVersion))
+ {
+ timeStampFreeVersion = "final";
+ }
+
+ if (!timeStampFreeVersion.StartsWith("-"))
+ {
+ timeStampFreeVersion = "-" + timeStampFreeVersion;
+ }
+
+ // E.g. change version 2.5.0-rc2-123123 to 2.5.0-rc2-final.
+ var index = releaseLabel.LastIndexOf('-');
+ if (index != -1)
+ {
+ releaseLabel = releaseLabel.Substring(0, index) + timeStampFreeVersion;
+ }
+ }
+
+ return releaseLabel;
+ }
+ }
+}
\ No newline at end of file
diff --git a/build/tools/docker/debian.8/Dockerfile b/build/tools/docker/debian.8/Dockerfile
new file mode 100644
index 0000000000..0c032b9d7f
--- /dev/null
+++ b/build/tools/docker/debian.8/Dockerfile
@@ -0,0 +1,51 @@
+#
+# Copyright (c) .NET Foundation. All rights reserved.
+# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#
+
+# Dockerfile that creates a container suitable to build dotnet-cli
+FROM debian:jessie
+
+# Misc Dependencies for build
+RUN apt-get update && \
+ apt-get -qqy install \
+ curl \
+ unzip \
+ gettext \
+ sudo \
+ libunwind8 \
+ libkrb5-3 \
+ libicu52 \
+ liblttng-ust0 \
+ libssl1.0.0 \
+ zlib1g \
+ libuuid1 \
+ debhelper \
+ build-essential \
+ devscripts \
+ git \
+ cmake \
+ clang-3.5 \
+ wget && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Use clang as c++ compiler
+RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100
+RUN update-alternatives --set c++ /usr/bin/clang++-3.5
+
+# Setup User to match Host User, and give superuser permissions
+ARG USER_ID=0
+RUN useradd -m code_executor -u ${USER_ID} -g sudo
+RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# With the User Change, we need to change permissions on these directories
+RUN chmod -R a+rwx /usr/local
+RUN chmod -R a+rwx /home
+RUN chmod -R 755 /usr/lib/sudo
+
+# Set user to the one we just created
+USER ${USER_ID}
+
+# Set working directory
+WORKDIR /opt/code
diff --git a/build/tools/docker/rhel.7/Dockerfile b/build/tools/docker/rhel.7/Dockerfile
new file mode 100644
index 0000000000..73247d2809
--- /dev/null
+++ b/build/tools/docker/rhel.7/Dockerfile
@@ -0,0 +1,27 @@
+#
+# Copyright (c) .NET Foundation. All rights reserved.
+# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#
+
+# Dockerfile that creates a container suitable to build dotnet-cli
+FROM microsoft/dotnet-buildtools-prereqs:rhel-7-rpmpkg-c982313-20174116044113
+
+# Install from sudo main package TODO This package needs to be mirrored
+RUN yum install -y https://www.sudo.ws/sudo/dist/packages/RHEL/7/sudo-1.8.20-3.el7.x86_64.rpm \
+ && yum clean all
+
+# Setup User to match Host User, and give superuser permissions
+ARG USER_ID=0
+RUN useradd -m code_executor -u ${USER_ID} -g root
+RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# With the User Change, we need to change permssions on these directories
+RUN chmod -R a+rwx /usr/local
+RUN chmod -R a+rwx /home
+RUN chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo
+
+# Set user to the one we just created
+USER ${USER_ID}
+
+# Set working directory
+WORKDIR /opt/code
diff --git a/build/tools/docker/ubuntu.14.04/Dockerfile b/build/tools/docker/ubuntu.14.04/Dockerfile
new file mode 100644
index 0000000000..f039506971
--- /dev/null
+++ b/build/tools/docker/ubuntu.14.04/Dockerfile
@@ -0,0 +1,52 @@
+#
+# Copyright (c) .NET Foundation. All rights reserved.
+# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#
+
+# Dockerfile that creates a container suitable to build dotnet-cli
+FROM ubuntu:14.04
+
+# Misc Dependencies for build
+RUN apt-get update && \
+ apt-get -qqy install \
+ curl \
+ unzip \
+ gettext \
+ sudo \
+ libunwind8 \
+ libkrb5-3 \
+ libicu52 \
+ liblttng-ust0 \
+ libssl1.0.0 \
+ zlib1g \
+ libuuid1 \
+ debhelper \
+ build-essential \
+ devscripts \
+ git \
+ cmake \
+ clang-3.5 \
+ lldb-3.6 \
+ wget && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Use clang as c++ compiler
+RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100
+RUN update-alternatives --set c++ /usr/bin/clang++-3.5
+
+# Setup User to match Host User, and give superuser permissions
+ARG USER_ID=0
+RUN useradd -m code_executor -u ${USER_ID} -g sudo
+RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# With the User Change, we need to change permissions on these directories
+RUN chmod -R a+rwx /usr/local
+RUN chmod -R a+rwx /home
+RUN chmod -R 755 /usr/lib/sudo
+
+# Set user to the one we just created
+USER ${USER_ID}
+
+# Set working directory
+WORKDIR /opt/code
diff --git a/build/tools/docker/ubuntu.16.04/Dockerfile b/build/tools/docker/ubuntu.16.04/Dockerfile
new file mode 100644
index 0000000000..79e76f0703
--- /dev/null
+++ b/build/tools/docker/ubuntu.16.04/Dockerfile
@@ -0,0 +1,48 @@
+#
+# Copyright (c) .NET Foundation. All rights reserved.
+# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#
+
+FROM ubuntu:16.04
+
+# Install the base toolchain we need to build anything (clang, cmake, make and the like)
+# this does not include libraries that we need to compile different projects, we'd like
+# them in a different layer.
+RUN apt-get update && \
+ apt-get install -y cmake \
+ make \
+ llvm-3.5 \
+ clang-3.5 \
+ git \
+ curl \
+ tar \
+ sudo \
+ debhelper \
+ build-essential \
+ devscripts \
+ libunwind8 \
+ libkrb5-3 \
+ libicu55 \
+ liblttng-ust0 \
+ libssl1.0.0 \
+ zlib1g \
+ libuuid1 \
+ liblldb-3.6 \
+ wget && \
+ apt-get clean
+
+# Setup User to match Host User, and give superuser permissions
+ARG USER_ID=0
+RUN useradd -m code_executor -u ${USER_ID} -g sudo
+RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# With the User Change, we need to change permissions on these directories
+RUN chmod -R a+rwx /usr/local
+RUN chmod -R a+rwx /home
+RUN chmod -R 755 /usr/lib/sudo
+
+# Set user to the one we just created
+USER ${USER_ID}
+
+# Set working directory
+WORKDIR /opt/code
\ No newline at end of file
diff --git a/build/tools/docker/ubuntu.16.10/Dockerfile b/build/tools/docker/ubuntu.16.10/Dockerfile
new file mode 100644
index 0000000000..c57bd4c3ff
--- /dev/null
+++ b/build/tools/docker/ubuntu.16.10/Dockerfile
@@ -0,0 +1,52 @@
+#
+# Copyright (c) .NET Foundation. All rights reserved.
+# Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+#
+
+# Dockerfile that creates a container suitable to build dotnet-cli
+FROM ubuntu:16.10
+
+# Misc Dependencies for build
+RUN apt-get update && \
+ apt-get -qqy install \
+ curl \
+ unzip \
+ gettext \
+ sudo \
+ libunwind8 \
+ libkrb5-3 \
+ libicu57 \
+ liblttng-ust0 \
+ libssl1.0.0 \
+ zlib1g \
+ libuuid1 \
+ liblldb-3.5 \
+ debhelper \
+ build-essential \
+ devscripts \
+ git \
+ cmake \
+ clang-3.5 \
+ wget && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+# Use clang as c++ compiler
+RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-3.5 100
+RUN update-alternatives --set c++ /usr/bin/clang++-3.5
+
+# Setup User to match Host User, and give superuser permissions
+ARG USER_ID=0
+RUN useradd -m code_executor -u ${USER_ID} -g sudo
+RUN echo 'code_executor ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# With the User Change, we need to change permissions on these directories
+RUN chmod -R a+rwx /usr/local
+RUN chmod -R a+rwx /home
+RUN chmod -R 755 /usr/lib/sudo
+
+# Set user to the one we just created
+USER ${USER_ID}
+
+# Set working directory
+WORKDIR /opt/code
\ No newline at end of file
diff --git a/build/tools/dotnet-deb-tool-consumer/dotnet-deb-tool-consumer.csproj b/build/tools/dotnet-deb-tool-consumer/dotnet-deb-tool-consumer.csproj
new file mode 100644
index 0000000000..659448ee0e
--- /dev/null
+++ b/build/tools/dotnet-deb-tool-consumer/dotnet-deb-tool-consumer.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netcoreapp1.0
+ $(RestoreSources);https://dotnet.myget.org/F/cli-deps/api/v3/index.json
+
+
+
+
+
+
+
diff --git a/build/tools/packaging/changelog b/build/tools/packaging/changelog
new file mode 100644
index 0000000000..f28d88ed10
--- /dev/null
+++ b/build/tools/packaging/changelog
@@ -0,0 +1,2 @@
+* DATE MAINTAINER_NAME - PACKAGE_VERSION-PACKAGE_REVISION
+-
\ No newline at end of file
diff --git a/build/tools/packaging/hosting_debian_config.json b/build/tools/packaging/hosting_debian_config.json
new file mode 100644
index 0000000000..92c825e901
--- /dev/null
+++ b/build/tools/packaging/hosting_debian_config.json
@@ -0,0 +1,35 @@
+{
+ "maintainer_name": "Microsoft",
+ "maintainer_email": "nugetaspnet@microsoft.com",
+
+ "package_name": "dotnet-hosting",
+ "install_root": "/usr/share/dotnet",
+
+ "short_description": "Microsoft .NET Core DEB_VERSION Linux Server Hosting",
+ "long_description": "Microsoft .NET Core Linux Server Hosting enables hosting of ASP.NET Core applications and contains the ASP.NET Core Runtime Package Store and .NET Core Runtime. It is open source, cross-platform and is supported by Microsoft. We hope you enjoy using it! If you do, please consider joining the active community of developers that are contributing to the project on GitHub (https://github.com/aspnet/home). We happily accept issues and PRs.",
+ "homepage": "https://www.asp.net/",
+
+ "release":{
+ "package_version":"0.0.0.0",
+ "package_revision":"1",
+ "urgency" : "low",
+ "changelog_message" : ""
+ },
+
+ "control": {
+ "priority":"standard",
+ "section":"devel",
+ "architecture":"any"
+ },
+
+ "copyright": "Microsoft",
+ "license": {
+ "type": "Apache-2.0",
+ "full_text": "Copyright (c) .NET Foundation. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthese files except in compliance with the License. You may obtain a copy of the\nLicense at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the License for the\nspecific language governing permissions and limitations under the License."
+ },
+
+ "debian_dependencies": {
+ "dotnet-runtime-DOTNET_VERSION": {},
+ "aspnetcore-store-DEB_VERSION": {}
+ }
+}
\ No newline at end of file
diff --git a/build/tools/packaging/store_debian_config.json b/build/tools/packaging/store_debian_config.json
new file mode 100644
index 0000000000..70dffe42a9
--- /dev/null
+++ b/build/tools/packaging/store_debian_config.json
@@ -0,0 +1,34 @@
+{
+ "maintainer_name": "Microsoft",
+ "maintainer_email": "nugetaspnet@microsoft.com",
+
+ "package_name": "aspnetcore-store",
+ "install_root": "/usr/share/dotnet",
+
+ "short_description": "Microsoft ASP.NET Core DEB_VERSION Runtime Package Store",
+ "long_description": "Runtime package store for Microsoft ASP.NET Core. It is open source, cross-platform and is supported by Microsoft. We hope you enjoy using it! If you do, please consider joining the active community of developers that are contributing to the project on GitHub (https://github.com/aspnet/home). We happily accept issues and PRs.",
+ "homepage": "https://www.asp.net/",
+
+ "release":{
+ "package_version":"0.0.0.0",
+ "package_revision":"1",
+ "urgency" : "low",
+ "changelog_message" : ""
+ },
+
+ "control": {
+ "priority":"standard",
+ "section":"devel",
+ "architecture":"any"
+ },
+
+ "copyright": "Microsoft",
+ "license": {
+ "type": "Apache-2.0",
+ "full_text": "Copyright (c) .NET Foundation. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthese files except in compliance with the License. You may obtain a copy of the\nLicense at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See the License for the\nspecific language governing permissions and limitations under the License."
+ },
+
+ "debian_dependencies": {
+ "aspnetcore-store-2.0.0": {}
+ }
+}
\ No newline at end of file
diff --git a/build/tools/templates/Archive/Archive.csproj b/build/tools/templates/Archive/Archive.csproj
new file mode 100644
index 0000000000..088d82c8fa
--- /dev/null
+++ b/build/tools/templates/Archive/Archive.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ netcoreapp2.0
+ false
+ netcoreapp2.0
+ $(DotNetRestoreSources)
+ $(RestoreSources);https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
+
+ $(RestoreSources);
+ https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
+
+
+ $(RestoreSources);
+ https://api.nuget.org/v3/index.json;
+
+
+
+
diff --git a/build/tools/templates/HostingStartup/HostingStartup.csproj b/build/tools/templates/HostingStartup/HostingStartup.csproj
new file mode 100644
index 0000000000..dbb96336d5
--- /dev/null
+++ b/build/tools/templates/HostingStartup/HostingStartup.csproj
@@ -0,0 +1,20 @@
+
+
+
+ netcoreapp2.0
+ Exe
+
+
+
+
+
+
+
+
+ $(RuntimeFrameworkVersion)
+ $(DepsOutputPath)\$(HostingStartupPackageName)\shared\Microsoft.NETCore.App\$(DepsRuntimeFrameworkVersion)\$(HostingStartupPackageName).deps.json
+
+
+
+
+
diff --git a/build/tools/templates/HostingStartup/Program.cs b/build/tools/templates/HostingStartup/Program.cs
new file mode 100644
index 0000000000..8cd3c0026c
--- /dev/null
+++ b/build/tools/templates/HostingStartup/Program.cs
@@ -0,0 +1,7 @@
+// 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.
+
+public class Program
+{
+ public static void Main() { }
+}
\ No newline at end of file
diff --git a/build/tools/templates/RS.Manifest/RS.Manifest.csproj b/build/tools/templates/RS.Manifest/RS.Manifest.csproj
new file mode 100644
index 0000000000..d5b5a1c33a
--- /dev/null
+++ b/build/tools/templates/RS.Manifest/RS.Manifest.csproj
@@ -0,0 +1,32 @@
+
+
+
+
+
+ netcoreapp2.0
+ $(DotNetRestoreSources)
+
+ $(RestoreSources);
+ https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
+
+
+ $(RestoreSources);
+ https://api.nuget.org/v3/index.json;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/tools/templates/RS.References/RS.References.csproj b/build/tools/templates/RS.References/RS.References.csproj
new file mode 100644
index 0000000000..b28793fed0
--- /dev/null
+++ b/build/tools/templates/RS.References/RS.References.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ $(DotNetRestoreSources)
+
+ $(RestoreSources);
+ https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
+
+
+ $(RestoreSources);
+ https://api.nuget.org/v3/index.json;
+
+ netcoreapp2.0
+ false
+ false
+ false
+
+
+
diff --git a/modules/Templating b/modules/Templating
new file mode 160000
index 0000000000..aee0d26d67
--- /dev/null
+++ b/modules/Templating
@@ -0,0 +1 @@
+Subproject commit aee0d26d67279b33ffa974721c50b4499519133d
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 0000000000..7d57abfc71
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj b/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj
new file mode 100644
index 0000000000..5d15ffa141
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/Microsoft.AspNetCore.All.csproj
@@ -0,0 +1,32 @@
+
+
+
+
+
+ $(DotNetRestoreSources)
+
+ $(RestoreSources);
+ https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json;
+ https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
+
+
+ $(RestoreSources);
+ https://api.nuget.org/v3/index.json;
+
+
+ false
+ false
+ netcoreapp2.0
+ aspnetcore
+ Microsoft.AspNetCore.All
+ false
+ $(MicrosoftNETCoreApp20PackageVersion)
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/PublishWithAspNetCoreTargetManifest.targets b/src/Microsoft.AspNetCore.All/build/PublishWithAspNetCoreTargetManifest.targets
new file mode 100644
index 0000000000..a590cf01f1
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/PublishWithAspNetCoreTargetManifest.targets
@@ -0,0 +1,29 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ $(TargetManifestFiles);@(AspNetCoreTargetManifestFiles)
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-common.xml b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-common.xml
new file mode 100755
index 0000000000..3b0c4bda7c
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-common.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-linux-x64.xml b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-linux-x64.xml
new file mode 100755
index 0000000000..e548a00368
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-linux-x64.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-osx-x64.xml b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-osx-x64.xml
new file mode 100755
index 0000000000..369db3ef5b
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-osx-x64.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x64.xml b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x64.xml
new file mode 100755
index 0000000000..0155a8e72c
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x64.xml
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x86.xml b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x86.xml
new file mode 100755
index 0000000000..362dab9895
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/aspnetcore-store-2.0.0-win7-x86.xml
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/build/netcoreapp2.0/Microsoft.AspNetCore.All.targets b/src/Microsoft.AspNetCore.All/build/netcoreapp2.0/Microsoft.AspNetCore.All.targets
new file mode 100644
index 0000000000..0bed51f606
--- /dev/null
+++ b/src/Microsoft.AspNetCore.All/build/netcoreapp2.0/Microsoft.AspNetCore.All.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Microsoft.AspNetCore.All/lib/netcoreapp2.0/_._ b/src/Microsoft.AspNetCore.All/lib/netcoreapp2.0/_._
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/version.props b/version.props
index 834077241d..53bd896f60 100644
--- a/version.props
+++ b/version.props
@@ -2,6 +2,10 @@
2.1.0
preview1
- $(VersionSuffix)-$(BuildNumber)
+ $(VersionPrefix)
+ $(VersionPrefix)
+ $(VersionPrefix)-$(VersionSuffix)-final
+ $(VersionPrefix)-$(VersionSuffix)-final
+ $(VersionSuffix)-$(BuildNumber)