Update to MSBuild
This commit is contained in:
parent
c598f1918d
commit
471f48f56e
|
|
@ -14,56 +14,7 @@ artifacts
|
|||
StyleCop.Cache
|
||||
node_modules
|
||||
*.snk
|
||||
.nuget/NuGet.exe
|
||||
project.lock.json
|
||||
.build
|
||||
.nuget/
|
||||
|
||||
# repo folders
|
||||
/Antiforgery/
|
||||
/AzureIntegration/
|
||||
/BasicMiddleware/
|
||||
/BrowserLink/
|
||||
/CORS/
|
||||
/Caching/
|
||||
/Common/
|
||||
/Configuration/
|
||||
/DataProtection/
|
||||
/DependencyInjection/
|
||||
/Diagnostics/
|
||||
/DotNetTools/
|
||||
/EntityFramework.Tools/
|
||||
/EntityFramework/
|
||||
/Entropy/
|
||||
/EventNotification/
|
||||
/FileSystem/
|
||||
/Hosting/
|
||||
/HtmlAbstractions/
|
||||
/HttpAbstractions/
|
||||
/HttpSysServer/
|
||||
/IISIntegration/
|
||||
/Identity/
|
||||
/IdentityService/
|
||||
/JsonPatch/
|
||||
/KestrelHttpServer/
|
||||
/Localization/
|
||||
/Logging/
|
||||
/MetaPackages/
|
||||
/Microsoft.Data.Sqlite/
|
||||
/MusicStore/
|
||||
/Mvc/
|
||||
/MvcPrecompilation/
|
||||
/Options/
|
||||
/PlatformAbstractions/
|
||||
/Proxy/
|
||||
/Razor/
|
||||
/ResponseCaching/
|
||||
/Routing/
|
||||
/Scaffolding/
|
||||
/Security/
|
||||
/ServerTests/
|
||||
/Session/
|
||||
/SignalR/
|
||||
/StaticFiles/
|
||||
/Testing/
|
||||
/WebSockets/
|
||||
.nuget
|
||||
.r
|
||||
.deps
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26228.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildGraph", "tools\BuildGraph\BuildGraph.csproj", "{B0621D49-4770-4552-9425-D6BD2CF0FB50}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PinVersions", "tools\PinVersions\PinVersions.csproj", "{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{085280EC-7055-426A-BF9C-1B692B9599AB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
tools\shared\DependencyGraphSpecProvider.cs = tools\shared\DependencyGraphSpecProvider.cs
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
#update-release
|
||||
-// Merge dev branch to release
|
||||
@{
|
||||
Parallel.ForEach(GetAllRepos(), CloneOrUpdate);
|
||||
|
||||
Log.Info("************************************* Checking repos for diffs *************************");
|
||||
|
||||
foreach (var repo in GetAllRepos())
|
||||
{
|
||||
Log.Info("Checking repo: " + repo);
|
||||
// Check if the repo previously had a release branch
|
||||
try
|
||||
{
|
||||
GitCommand(repo, "rev-parse --verify --quiet origin/release");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Info("Repository " + repo + " does not have a release branch.");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
GitCommand(repo, "log -1 --exit-code origin/dev..origin/release");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warn("Unmerged changes in repository " + repo);
|
||||
GitCommand(repo, "log origin/dev..origin/release");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Info("No conflicts in repos, continuing with creating release branch.");
|
||||
|
||||
foreach (var repo in GetAllRepos())
|
||||
{
|
||||
GitCommand(repo, "checkout origin/dev -B release");
|
||||
var filesChanged = false;
|
||||
|
||||
// Update NuGet.Config
|
||||
var nugetConfigPath = Path.Combine(repo, "NuGet.config");
|
||||
if (File.Exists(nugetConfigPath))
|
||||
{
|
||||
var original = File.ReadAllText(nugetConfigPath);
|
||||
var modified = original
|
||||
.Replace("https://dotnet.myget.org/F/aspnetcore-ci-dev", "https://dotnet.myget.org/F/aspnetcore-ci-release");
|
||||
|
||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
||||
{
|
||||
File.WriteAllText(nugetConfigPath, modified);
|
||||
GitCommand(repo, "add NuGet.config");
|
||||
filesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
var buildPs1Path = Path.Combine(repo, "build.ps1");
|
||||
if (File.Exists(buildPs1Path))
|
||||
{
|
||||
var original = File.ReadAllText(buildPs1Path);
|
||||
var modified = original
|
||||
.Replace("https://github.com/aspnet/KoreBuild/archive/dev.zip", "https://github.com/aspnet/KoreBuild/archive/release.zip");
|
||||
|
||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
||||
{
|
||||
File.WriteAllText(buildPs1Path, modified);
|
||||
GitCommand(repo, "add build.ps1");
|
||||
filesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
var buildShPath = Path.Combine(repo, "build.sh");
|
||||
if (File.Exists(buildShPath))
|
||||
{
|
||||
var original = File.ReadAllText(buildShPath);
|
||||
var modified = original
|
||||
.Replace("https://github.com/aspnet/KoreBuild/archive/dev.zip", "https://github.com/aspnet/KoreBuild/archive/release.zip");
|
||||
|
||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
||||
{
|
||||
File.WriteAllText(buildShPath, modified);
|
||||
GitCommand(repo, "add build.sh");
|
||||
filesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (filesChanged)
|
||||
{
|
||||
GitCommand(repo, "commit -m \"Updating to release.\"");
|
||||
}
|
||||
|
||||
GitCommand(repo, "push origin release:release");
|
||||
GitCommand(repo, "checkout origin/dev -B dev");
|
||||
GitCommand(repo, "merge release -s ours");
|
||||
GitCommand(repo, "push origin dev:dev");
|
||||
}
|
||||
}
|
||||
|
||||
#update-master .pull-all
|
||||
-// Merge release branch to master
|
||||
-// Pin versions of packages in project.json and updated project.lock.json
|
||||
-// More information https://github.com/aspnet/Universe/wiki/%23pin-version-:-Pinning-package-version-for-a-particular-release-in-project.json
|
||||
@{
|
||||
var koreBuildTag = GetEnvironmentParameter("KOREBUILD_TAG");
|
||||
var coherenceFeed = GetEnvironmentParameter("COHERENCE_FEED");
|
||||
|
||||
if (string.IsNullOrEmpty(coherenceFeed))
|
||||
{
|
||||
throw new Exception("COHERENCE_FEED not specified. Usually this is Packages-NoTimestamp directory of Coherence-Signed.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(koreBuildTag))
|
||||
{
|
||||
throw new Exception("KOREBUILD_TAG environment variable is not specified.");
|
||||
}
|
||||
|
||||
var excludeReposForJson = new[]
|
||||
{
|
||||
"Coherence",
|
||||
"Coherence-Signed",
|
||||
"dnvm",
|
||||
"Entropy",
|
||||
"Setup",
|
||||
"libuv-build",
|
||||
};
|
||||
|
||||
Exec("dotnet", "restore", "tools/PinVersion");
|
||||
|
||||
foreach (var repo in GetAllRepos())
|
||||
{
|
||||
GitCommand(repo, "checkout origin/release -B master");
|
||||
|
||||
if (File.Exists(Path.Combine(repo, "NuGet.config")))
|
||||
{
|
||||
File.Copy(Path.Combine("build-template", "NuGet.master.config"),
|
||||
Path.Combine(repo, "NuGet.config"),
|
||||
overwrite: true);
|
||||
GitCommand(repo, "add NuGet.*");
|
||||
GitCommand(repo, "commit -m \"Updating NuGet.config\"");
|
||||
}
|
||||
}
|
||||
|
||||
var reposToPin = GetAllRepos().Except(excludeReposForJson);
|
||||
var repositoryNamesFile = Path.GetTempFileName();
|
||||
|
||||
File.WriteAllLines(repositoryNamesFile, reposToPin.Select(r => Path.Combine(Directory.GetCurrentDirectory(), r)));
|
||||
var pinToolsArgs = string.Format(@"run -p tools/PinVersion ""{0}"" ""{1}"" ""{2}""",
|
||||
coherenceFeed,
|
||||
koreBuildTag,
|
||||
repositoryNamesFile);
|
||||
Exec("dotnet", pinToolsArgs, "");
|
||||
try
|
||||
{
|
||||
File.Delete(repositoryNamesFile);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
foreach (var repo in reposToPin)
|
||||
{
|
||||
var repoPath = Path.Combine(Directory.GetCurrentDirectory(), repo);
|
||||
try
|
||||
{
|
||||
GitCommand(repo, "commit -am \"Updating json files to pin versions and build files to pin KoreBuild\"");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Don't fail if there was nothing to add.
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var repo in GetAllRepos())
|
||||
{
|
||||
GitCommand(repo, "push origin +master:master");
|
||||
}
|
||||
|
||||
CallTarget("update-prerelease-tags");
|
||||
}
|
||||
|
||||
#update-prerelease-tags
|
||||
-// Update tags on each repo to have the latest release tag
|
||||
@{
|
||||
var preReleaseTag = GetEnvironmentParameter("PRERELEASETAG");
|
||||
if (string.IsNullOrEmpty(preReleaseTag))
|
||||
{
|
||||
throw new Exception("PRERELEASETAG tag not defined");
|
||||
}
|
||||
|
||||
var versionFile = "version.txt";
|
||||
|
||||
foreach (var repo in GetAllRepos())
|
||||
{
|
||||
GitCommand(repo, "pull --tags");
|
||||
string version = null;
|
||||
|
||||
try
|
||||
{
|
||||
GitCommand(repo, string.Format("describe --tags > ..\\{0}", versionFile));
|
||||
}
|
||||
catch
|
||||
{
|
||||
version = "1.0.0-" + preReleaseTag;
|
||||
Log.Warn(string.Format("{0} repo not tagged. Using default version {1}.", repo, version));
|
||||
}
|
||||
|
||||
if (version == null)
|
||||
{
|
||||
version = File.ReadAllText(versionFile);
|
||||
File.Delete(versionFile);
|
||||
}
|
||||
|
||||
Log.Info(string.Format("Current version on repo {0} is {1}", repo, version));
|
||||
|
||||
var majorVersion = version.Split(new string[]{"-"}, StringSplitOptions.None)[0];
|
||||
|
||||
var newVersion = majorVersion + string.Format("-{0}", preReleaseTag);
|
||||
|
||||
Log.Info(string.Format("New version for repo is {0}", newVersion));
|
||||
|
||||
GitCommand(repo, string.Format("tag -f -a {0} -m \"Tag for new release {0}\"", newVersion));
|
||||
|
||||
GitCommand(repo, "push origin --tags +" + newVersion);
|
||||
}
|
||||
}
|
||||
|
||||
functions
|
||||
@{
|
||||
IEnumerable<string> GetAllRepos()
|
||||
{
|
||||
var nonDefaultRepos = new[]
|
||||
{
|
||||
"CoreCLR",
|
||||
"Coherence",
|
||||
"Coherence-Signed",
|
||||
"KoreBuild",
|
||||
"Universe",
|
||||
"libuv-build",
|
||||
};
|
||||
|
||||
return Enumerable.Concat(nonDefaultRepos, repositories);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="AspNetVNext" value="https://www.myget.org/f/aspnetmaster/api/v3/index.json" />
|
||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<Project>
|
||||
<ItemDefinitionGroup>
|
||||
<Repository>
|
||||
<Branch>dev</Branch>
|
||||
<CloneUrl>git@github.com:aspnet/%(Identity)</CloneUrl>
|
||||
</Repository>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Repository Include="Antiforgery" Commit="" />
|
||||
<Repository Include="AzureIntegration" Commit="" />
|
||||
<Repository Include="BasicMiddleware" Commit="" />
|
||||
<Repository Include="BrowserLink" Commit="" />
|
||||
<Repository Include="Caching" Commit="" />
|
||||
<Repository Include="Common" Commit="" />
|
||||
<Repository Include="Configuration" Commit="" />
|
||||
<Repository Include="CORS" Commit="" />
|
||||
<Repository Include="DataProtection" Commit="" />
|
||||
<Repository Include="DependencyInjection" Commit="" />
|
||||
<Repository Include="Diagnostics" Commit="" />
|
||||
<Repository Include="DotNetTools" Commit="" />
|
||||
<Repository Include="EntityFramework" Commit="" />
|
||||
<Repository Include="EntityFramework.Tools" Commit="" />
|
||||
<Repository Include="Entropy" Commit="" />
|
||||
<Repository Include="EventNotification" Commit="" />
|
||||
<Repository Include="FileSystem" Commit="" />
|
||||
<Repository Include="Hosting" Commit="" />
|
||||
<Repository Include="HtmlAbstractions" Commit="" />
|
||||
<Repository Include="HttpAbstractions" Commit="" />
|
||||
<Repository Include="HttpSysServer" Commit="" />
|
||||
<Repository Include="Identity" Commit="" />
|
||||
<Repository Include="IdentityService" Commit="" />
|
||||
<Repository Include="IISIntegration" Commit="" />
|
||||
<Repository Include="JsonPatch" Commit="" />
|
||||
<Repository Include="KestrelHttpServer" Commit="" />
|
||||
<Repository Include="Localization" Commit="" />
|
||||
<Repository Include="Logging" Commit="" />
|
||||
<Repository Include="MetaPackages" Commit="" />
|
||||
<Repository Include="Microsoft.Data.Sqlite" Commit="" />
|
||||
<Repository Include="MusicStore" Commit="" />
|
||||
<Repository Include="Mvc" Commit="" />
|
||||
<Repository Include="MvcPrecompilation" Commit="" />
|
||||
<Repository Include="Options" Commit="" />
|
||||
<Repository Include="PlatformAbstractions" Commit="" />
|
||||
<Repository Include="Proxy" Commit="" />
|
||||
<Repository Include="Razor" Commit="" />
|
||||
<Repository Include="ResponseCaching" Commit="" />
|
||||
<Repository Include="Routing" Commit="" />
|
||||
<Repository Include="Scaffolding" Commit="" />
|
||||
<Repository Include="Security" Commit="" />
|
||||
<Repository Include="ServerTests" Commit="" />
|
||||
<Repository Include="Session" Commit="" />
|
||||
<Repository Include="SignalR" Commit="" />
|
||||
<Repository Include="StaticFiles" Commit="" />
|
||||
<Repository Include="Testing" Commit="" />
|
||||
<Repository Include="WebSockets" Commit="" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<Project>
|
||||
<Import Project="$(_BuildGraphFile)" />
|
||||
|
||||
<Target Name="BuildRepositories">
|
||||
<ItemGroup>
|
||||
<BatchedRepository Include="$(MSBuildProjectFullPath)">
|
||||
<AdditionalProperties>
|
||||
RepositoryToBuild=%(RepositoryToBuildInOrder.Identity);
|
||||
BuildRepositoryRoot=$(_CloneRepositoryRoot)%(RepositoryToBuildInOrder.Identity)\
|
||||
</AdditionalProperties>
|
||||
<BuildGroup>%(RepositoryToBuildInOrder.Order)</BuildGroup>
|
||||
</BatchedRepository>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BatchBuilds Condition="$(BuildInParallel) AND '$(CompileOnly)'=='true'">true</BatchBuilds>
|
||||
<BatchBuilds Condition="'$(BatchBuilds)'==''">false</BatchBuilds>
|
||||
</PropertyGroup>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(BatchedRepository)"
|
||||
BuildInParallel="$(BatchBuilds)"
|
||||
Targets="_BuildRepository"
|
||||
Properties="BuildGroup=%(BatchedRepository.BuildGroup)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_BuildRepository" DependsOnTargets="_PinVersions">
|
||||
<PropertyGroup>
|
||||
<RepositoryKoreBuildDirectory>$(BuildRepositoryRoot).build\</RepositoryKoreBuildDirectory>
|
||||
<RepositoryArtifactsDirectory>$(BuildRepositoryRoot)artifacts\build\</RepositoryArtifactsDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<KoreBuildFiles Include="$(KoreBuildDirectory)**\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Text="============ Building $(RepositoryToBuild) ============" Importance="High" />
|
||||
<Copy SourceFiles="@(KoreBuildFiles)" DestinationFolder="$(RepositoryKoreBuildDirectory)%(RecursiveDir)" />
|
||||
|
||||
<ItemGroup>
|
||||
<RepositoryKoreBuildProject Include="$(RepositoryKoreBuildDirectory)$(KoreBuildProject)">
|
||||
<AdditionalProperties>
|
||||
RepositoryRoot=$(BuildRepositoryRoot);
|
||||
BuildNumber=$(BuildNumber);
|
||||
Configuration=$(Configuration)
|
||||
</AdditionalProperties>
|
||||
</RepositoryKoreBuildProject>
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(RepositoryKoreBuildProject)"
|
||||
Targets="Restore"
|
||||
Properties="PreflightRestore=true" />
|
||||
|
||||
<MSBuild
|
||||
Projects="@(RepositoryKoreBuildProject)"
|
||||
Targets="$(_RepositoryBuildTargets)" />
|
||||
|
||||
<ItemGroup>
|
||||
<RepositoryArtifacts Include="$(RepositoryArtifactsDirectory)*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy
|
||||
SourceFiles="@(RepositoryArtifacts)"
|
||||
DestinationFolder="$(UniverseBuildDir)" />
|
||||
|
||||
<Exec
|
||||
Command="$(DotNetPath) nuget push "%(RepositoryArtifacts.Identity)" -s $(NuGetFeed) -k $(APIKEY)"
|
||||
Condition="'$(PublishPackages)'=='true' AND '%(RepositoryArtifacts.Extension)'=='.nupkg'" />
|
||||
|
||||
<Message Text="============ Done building $(RepositoryToBuild) ============" Importance="High" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_PinVersions">
|
||||
<PropertyGroup>
|
||||
<PinToolBinary>$(RepositoryRoot)tools\PinVersions\bin\$(Configuration)\netcoreapp1.1\PinVersions.dll</PinToolBinary>
|
||||
<PinVersionArgs>$(DotNetPath) $(PinToolBinary) --graph-specs-root "$(_RestoreGraphSpecsDirectory) " -s "$(UniverseBuildDir) " "$(BuildRepositoryRoot) "</PinVersionArgs>
|
||||
<PinVersionArgs Condition="Exists('$(_DependencyPackagesDirectory)')">$(PinVersionArgs) -s "$(_DependencyPackagesDirectory) "</PinVersionArgs>
|
||||
</PropertyGroup>
|
||||
|
||||
<Exec Command="$(PinVersionArgs)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<DisableDefaultItems>true</DisableDefaultItems>
|
||||
<DisableDefaultTargets>true</DisableDefaultTargets>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,56 +1,220 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<_SakeTargets Condition="'$(Configuration)' == 'Release'">--config-release</_SakeTargets>
|
||||
<NuGetPublishVolatileFeed>https://dotnet.myget.org/F/aspnetcore-volatile-dev/api/v2/package</NuGetPublishVolatileFeed>
|
||||
|
||||
<_BuildGraphFile>$(BuildDir)BuildGraph.proj</_BuildGraphFile>
|
||||
<_CloneRepositoryRoot>$(RepositoryRoot).r\</_CloneRepositoryRoot>
|
||||
<_DependencyPackagesDirectory>$(RepositoryRoot).deps\build\</_DependencyPackagesDirectory>
|
||||
<_CommitsFile>$(RepositoryRoot).deps\build\RepositoryCommits.proj</_CommitsFile>
|
||||
<_RestoreGraphSpecsDirectory>$(RepositoryRoot)obj\package-specs\</_RestoreGraphSpecsDirectory>
|
||||
|
||||
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'=='' AND '$(CompileOnly)'=='true'">Package;VerifyPackages</_RepositoryBuildTargets>
|
||||
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'==''">Verify</_RepositoryBuildTargets>
|
||||
<_RepositoriesWithCommitsFile>$(RepositoryRoot).deps\build\Repositories.props</_RepositoriesWithCommitsFile>
|
||||
|
||||
<PrepareDependsOn>$(PrepareDependsOn);CleanUniverseArtifacts</PrepareDependsOn>
|
||||
<CleanDependsOn>$(CleanDependsOn);CleanUniverseArtifacts</CleanDependsOn>
|
||||
<BuildDependsOn>$(BuildDependsOn);CloneRepositories;BuildRepositories</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- workaround. Using Sake as the intermediate means this property doesn't flow into repo builds. -->
|
||||
<Target Name="SetBuildNumber" Condition="'$(BuildNumber)' != ''">
|
||||
<SetEnvironmentVariable Variable="BuildNumber" Value="$(BuildNumber)" />
|
||||
<Import
|
||||
Project="$(_RepositoriesWithCommitsFile)"
|
||||
Condition="Exists('$(_RepositoriesWithCommitsFile)')" />
|
||||
<Import
|
||||
Project="Repositories.props"
|
||||
Condition="!Exists('$(_RepositoriesWithCommitsFile)')" />
|
||||
<Import
|
||||
Project="$(_CommitsFile)"
|
||||
Condition="Exists('$(_CommitsFile)')" />
|
||||
|
||||
<Target Name="CleanUniverseArtifacts">
|
||||
<RemoveDir Directories="$(RepositoryRoot)obj" Condition="Exists('$(RepositoryRoot)obj')" />
|
||||
<RemoveDir Directories="$(_CloneRepositoryRoot)" Condition="Exists('$(_CloneRepositoryRoot)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="VerifyAll">
|
||||
<Target Name="_FilterRepositories">
|
||||
<ItemGroup Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)'!=''">
|
||||
<_RepositoriesToInclude Include="$(KOREBUILD_REPOSITORY_INCLUDE)" />
|
||||
<Repository
|
||||
Remove="@(Repository)"
|
||||
Condition="'@(Repository)'!='@(_RepositoriesToInclude)' AND '%(Identity)'!=''" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(KOREBUILD_REPOSITORY_EXCLUDE)'!=''">
|
||||
<RepositoriesToExclude Include="$(KOREBUILD_REPOSITORY_EXCLUDE)" />
|
||||
<Repository Remove="@(RepositoriesToExclude)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Error Text="KOREBUILD_REPOSITORY_EXCLUDE AND KOREBUILD_REPOSITORY_INCLUDE are specified."
|
||||
Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)' != '' AND '$(KOREBUILD_REPOSITORY_EXCLUDE)' != ''" />
|
||||
|
||||
<Message Text="%(Repository.CloneUrl)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CloneRepositories" DependsOnTargets="_FilterRepositories">
|
||||
<ItemGroup>
|
||||
<_CloneRepository Include="$(MSBuildProjectFullPath)">
|
||||
<AdditionalProperties>
|
||||
CloneRepository=%(Repository.Identity);
|
||||
CloneUrl=%(Repository.CloneUrl);
|
||||
CloneBranch=%(Repository.Branch);
|
||||
CloneRepositoryCommit=%(Repository.Commit);
|
||||
UseGateBranch=$(UseGateBranch)
|
||||
</AdditionalProperties>
|
||||
</_CloneRepository>
|
||||
</ItemGroup>
|
||||
|
||||
<MakeDir Directories="$(_CloneRepositoryRoot)" />
|
||||
|
||||
<MSBuild Projects="@(_CloneRepository)"
|
||||
Targets="_CloneRepository"
|
||||
BuildInParallel="$(BuildInParallel)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CloneRepository">
|
||||
<PropertyGroup>
|
||||
<_SakeTargets>$(_SakeTargets):verify-all</_SakeTargets>
|
||||
<ShallowClone Condition="'$(ShallowClone)'=='' OR '$(CloneRepositoryCommit)'!=''">false</ShallowClone>
|
||||
<_CloneArguments>git clone --quiet $(CloneUrl)</_CloneArguments>
|
||||
<_CloneArguments Condition="'$(ShallowClone)'=='true'">$(_CloneArguments) --depth 1</_CloneArguments>
|
||||
</PropertyGroup>
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
||||
|
||||
<Message Text="Cloning $(CloneRepository) ..." Importance="High" />
|
||||
<Exec
|
||||
Command="$(_CloneArguments) --branch $(CloneBranch)-gate"
|
||||
Condition="'$(UseGateBranch)'=='true'"
|
||||
IgnoreExitCode="true"
|
||||
IgnoreStandardErrorWarningFormat="true"
|
||||
WorkingDirectory="$(_CloneRepositoryRoot)">
|
||||
<Output TaskParameter="ExitCode" PropertyName="GateBranchExitCode" />
|
||||
</Exec>
|
||||
|
||||
<Warning Text="Using $(CloneBranch)-gate for $(CloneRepository)"
|
||||
Condition="'$(GateBranchExitCode)'=='0'" />
|
||||
|
||||
<Exec
|
||||
Command="$(_CloneArguments) --branch $(CloneBranch)"
|
||||
Condition="'$(GateBranchExitCode)'!='0'"
|
||||
WorkingDirectory="$(_CloneRepositoryRoot)" />
|
||||
|
||||
<Exec
|
||||
Command="git reset --quiet --hard $(CloneRepositoryCommit)"
|
||||
WorkingDirectory="$(_CloneRepositoryRoot)$(CloneRepository)"
|
||||
Condition="'$(CloneRepositoryCommit)'!=''" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CIBuild" DependsOnTargets="SetBuildNumber">
|
||||
<Target Name="BuildRepositories"
|
||||
DependsOnTargets="_FilterRepositories;_FindDotNetPath;_GenerateRestoreGraphSpecs;_GenerateBuildGraph;_UpdateNuGetConfig;_CreateRepositoriesListWithCommits">
|
||||
|
||||
<PropertyGroup>
|
||||
<_SakeTargets>$(_SakeTargets):ci-build</_SakeTargets>
|
||||
<_BuildRepositoryProperties>
|
||||
UniverseBuildDir=$(BuildDir);
|
||||
BuildInParallel=$(BuildInParallel);
|
||||
BuildNumber=$(BuildNumber);
|
||||
Configuration=$(Configuration);
|
||||
DotNetPath=$(DotNetPath);
|
||||
KoreBuildDirectory=$(MSBuildProjectDirectory)\;
|
||||
KoreBuildProject=$(MSBuildProjectFile);
|
||||
RepositoryRoot=$(RepositoryRoot);
|
||||
_BuildGraphFile=$(_BuildGraphFile);
|
||||
_CloneRepositoryRoot=$(_CloneRepositoryRoot);
|
||||
_DependencyPackagesDirectory=$(_DependencyPackagesDirectory);
|
||||
_RepositoryBuildTargets=$(_RepositoryBuildTargets);
|
||||
_RestoreGraphSpecsDirectory=$(_RestoreGraphSpecsDirectory)
|
||||
</_BuildRepositoryProperties>
|
||||
</PropertyGroup>
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
||||
|
||||
<MSBuild
|
||||
Projects="$(MSBuildThisFileDirectory)RepositoryBuild.targets"
|
||||
Targets="BuildRepositories"
|
||||
Properties="$(_BuildRepositoryProperties)" />
|
||||
|
||||
<MSBuild
|
||||
Projects="$(MSBuildThisFileDirectory)PublishPackages.targets"
|
||||
Condition="'$(PublishPackages)'=='true'"
|
||||
Properties="
|
||||
PackagesDirectory=$(ArtifactsDir);
|
||||
DotNetPath=$(DotNetPath);
|
||||
NuGetFeed=$(NuGetPublishFeed);
|
||||
APIKey=$(APIKey)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CITest" DependsOnTargets="SetBuildNumber">
|
||||
<PropertyGroup>
|
||||
<_SakeTargets>$(_SakeTargets):ci-test</_SakeTargets>
|
||||
<Target Name="_GenerateRestoreGraphSpecs" DependsOnTargets="_FindDotNetPath">
|
||||
<ItemGroup>
|
||||
<Solution Include="$(_CloneRepositoryRoot)%(Repository.Identity)\*.sln">
|
||||
<Repository>%(Repository.Identity)</Repository>
|
||||
</Solution>
|
||||
|
||||
<Solution>
|
||||
<AdditionalProperties>RestoreGraphOutputPath=$(_RestoreGraphSpecsDirectory)%(Solution.Repository)\%(Solution.FileName)%(Solution.Extension).json</AdditionalProperties>
|
||||
</Solution>
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(Solution)"
|
||||
Targets="GenerateRestoreGraphFile"
|
||||
BuildInParallel="$(BuildInParallel)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateBuildGraph" DependsOnTargets="_FindDotNetPath">
|
||||
<Exec
|
||||
Command="$(DotNetPath) run -r "$(_CloneRepositoryRoot) " --graph-specs-root "$(_RestoreGraphSpecsDirectory) " "$(_BuildGraphFile)""
|
||||
WorkingDirectory="$(RepositoryRoot)tools\BuildGraph\" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_UpdateNuGetConfig">
|
||||
<UpdatePackageSource
|
||||
NuGetConfigPath="$(_CloneRepositoryRoot)%(Repository.Identity)\NuGet.config"
|
||||
SourceName="Dependencies"
|
||||
SourceUri="$(_DependencyPackagesDirectory)"
|
||||
Condition="Exists('$(_DependencyPackagesDirectory)')" />
|
||||
|
||||
<MakeDir Directories="$(BuildDir)" Condition="!Exists('$(BuildDir)')" />
|
||||
|
||||
<UpdatePackageSource
|
||||
NuGetConfigPath="$(_CloneRepositoryRoot)%(Repository.Identity)\NuGet.config"
|
||||
SourceName="Artifacts"
|
||||
SourceUri="$(BuildDir)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CreateRepositoriesListWithCommits" DependsOnTargets="_GetRepositoryCommits">
|
||||
<PropertyGroup>
|
||||
<RepositoryFileWithCommit>$(BuildDir)Repositories.props</RepositoryFileWithCommit>
|
||||
</PropertyGroup>
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
||||
<Copy
|
||||
SourceFiles="$(MSBuildThisFileDirectory)Repositories.props"
|
||||
DestinationFiles="$(RepositoryFileWithCommit)" />
|
||||
|
||||
<XmlPoke2
|
||||
XmlInputPath="$(RepositoryFileWithCommit)"
|
||||
Query="//Repository[@Include='%(Repository.Identity)']/@Commit"
|
||||
Value="%(Repository.Commit)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CIPull">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=ci-pull;RepositoryRoot=$(RepositoryRoot)" />
|
||||
<!-- Based on the solution here: http://stackoverflow.com/a/11331566 -->
|
||||
<Target Name="_GetRepositoryCommits" Outputs="%(Repository.Identity)">
|
||||
<PropertyGroup>
|
||||
<RepositoryCloneDirectory>$(_CloneRepositoryRoot)%(Repository.Identity)</RepositoryCloneDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<Error Text="%(Repository.Identity) has not been cloned."
|
||||
Condition="!Exists('$(RepositoryCloneDirectory)')" />
|
||||
|
||||
<GetGitCommitInfo WorkingDirectory="$(RepositoryCloneDirectory)">
|
||||
<Output TaskParameter="CommitHash" PropertyName="_Hash" />
|
||||
</GetGitCommitInfo>
|
||||
|
||||
<ItemGroup>
|
||||
<Repository Update="%(Identity)" Commit="$(_Hash)" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<_Hash></_Hash>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="UpdateRepos">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=update;RepositoryRoot=$(RepositoryRoot)" />
|
||||
<Target Name="_FindDotNetPath">
|
||||
<GetDotNetHost>
|
||||
<Output TaskParameter="ExecutablePath" PropertyName="DotNetPath" />
|
||||
</GetDotNetHost>
|
||||
</Target>
|
||||
|
||||
<Target Name="CleanAll">
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="Sake"
|
||||
Properties="SakeTargets=git-clean;RepositoryRoot=$(RepositoryRoot)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
1186
makefile.shade
1186
makefile.shade
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\shared\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Cli.Utils" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
public class DGMLFormatter : GraphFormatter
|
||||
{
|
||||
public override void Format(IList<GraphNode> nodes, string outputPath)
|
||||
{
|
||||
var xmlns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml");
|
||||
var xdoc = new XDocument(
|
||||
new XElement(xmlns + "DirectedGraph",
|
||||
new XElement(xmlns + "Nodes", GetNodes(xmlns, nodes).ToArray()),
|
||||
new XElement(xmlns + "Links", GetLinks(xmlns, nodes).ToArray()),
|
||||
new XElement(xmlns + "Properties", GetProperties(xmlns).ToArray())));
|
||||
|
||||
using (var writer = File.OpenWrite(outputPath))
|
||||
{
|
||||
xdoc.Save(writer);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<XElement> GetLinks(XNamespace xmlns, IEnumerable<GraphNode> nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
foreach (var outgoing in node.Outgoing)
|
||||
{
|
||||
yield return new XElement(xmlns + "Link",
|
||||
new XAttribute("Source", node.Repository.Name),
|
||||
new XAttribute("Target", outgoing.Repository.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<XElement> GetNodes(XNamespace xmlns, IEnumerable<GraphNode> nodes)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
yield return new XElement(xmlns + "Node",
|
||||
new XAttribute("Id", node.Repository.Name),
|
||||
new XAttribute("Label", $"{node.Repository.Name}"));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<XElement> GetProperties(XNamespace xmlns)
|
||||
{
|
||||
yield return new XElement(xmlns + "Property",
|
||||
new XAttribute("Id", "Label"),
|
||||
new XAttribute("Label", "Label"),
|
||||
new XAttribute("DataType", "String"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
public static class GraphBuilder
|
||||
{
|
||||
public static IList<GraphNode> Generate(IList<Repository> repositories)
|
||||
{
|
||||
// Build global list of primary projects
|
||||
var primaryProjects = repositories.SelectMany(c => c.Projects)
|
||||
.ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
|
||||
var graphNodes = repositories.Select(r => new GraphNode { Repository = r })
|
||||
.ToDictionary(r => r.Repository);
|
||||
|
||||
foreach (var project in repositories.SelectMany(r => r.AllProjects))
|
||||
{
|
||||
var thisProjectRepositoryNode = graphNodes[project.Repository];
|
||||
|
||||
foreach (var packageDependency in project.PackageReferences)
|
||||
{
|
||||
if (primaryProjects.TryGetValue(packageDependency, out var dependencyProject))
|
||||
{
|
||||
var dependencyRepository = dependencyProject.Repository;
|
||||
var dependencyNode = graphNodes[dependencyRepository];
|
||||
|
||||
thisProjectRepositoryNode.Incoming.Add(dependencyNode);
|
||||
dependencyNode.Outgoing.Add(thisProjectRepositoryNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graphNodes.Values.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
public abstract class GraphFormatter
|
||||
{
|
||||
public abstract void Format(IList<GraphNode> nodes, string outputPath);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
[DebuggerDisplay("{Repository.Name}")]
|
||||
public class GraphNode
|
||||
{
|
||||
public Repository Repository { get; set; }
|
||||
|
||||
public ISet<GraphNode> Incoming { get; } = new HashSet<GraphNode>();
|
||||
|
||||
public ISet<GraphNode> Outgoing { get; } = new HashSet<GraphNode>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
public class MSBuildGraphFormatter : GraphFormatter
|
||||
{
|
||||
public override void Format(IList<GraphNode> nodes, string outputPath)
|
||||
{
|
||||
var sortedNodes = nodes.Select(node => new { Repository = node.Repository, Order = TopologicalSort.GetOrder(node) })
|
||||
.OrderBy(item => item.Order);
|
||||
var projectElement = new XElement("Project",
|
||||
new XElement("ItemGroup",
|
||||
sortedNodes.Select(item => new XElement("RepositoryToBuildInOrder",
|
||||
new XAttribute("Include", item.Repository.Name),
|
||||
new XAttribute("Order", item.Order)))));
|
||||
|
||||
File.WriteAllText(outputPath, projectElement.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
using UniverseTools;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandLineApplication();
|
||||
var outputTypeOption = app.Option("--output-type",
|
||||
"Output type of generated graph. Valid values are: msbuild, and dgml.",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
var repositoriesRootOption = app.Option("-r|--repositories-root",
|
||||
"Directory containing repositories to calculate graph for.",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
var packageSpecsDirectoryOption = app.Option("--graph-specs-root",
|
||||
"Directory containing package specs. (Optional)",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
var outputPathArgument = app.Argument("Output path", "Output path");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
if (!repositoriesRootOption.HasValue())
|
||||
{
|
||||
Console.Error.WriteLine($"Option {repositoriesRootOption.Template} must have a value.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var outputPath = outputPathArgument.Value;
|
||||
if (string.IsNullOrEmpty(outputPath))
|
||||
{
|
||||
Console.Error.WriteLine($"Output path not specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
Directory.CreateDirectory(outputDirectory);
|
||||
|
||||
var outputType = outputTypeOption.Value() ?? "msbuild";
|
||||
|
||||
|
||||
var graphSpecProvider = packageSpecsDirectoryOption.HasValue()
|
||||
? new DependencyGraphSpecProvider(packageSpecsDirectoryOption.Value().Trim())
|
||||
: DependencyGraphSpecProvider.Default;
|
||||
IList<Repository> repositories;
|
||||
using (graphSpecProvider)
|
||||
{
|
||||
repositories = Repository.ReadAllRepositories(repositoriesRootOption.Value().Trim(), graphSpecProvider);
|
||||
}
|
||||
|
||||
var graph = GraphBuilder.Generate(repositories);
|
||||
GraphFormatter formatter;
|
||||
switch (outputType)
|
||||
{
|
||||
case "msbuild":
|
||||
formatter = new MSBuildGraphFormatter();
|
||||
break;
|
||||
case "dgml":
|
||||
formatter = new DGMLFormatter();
|
||||
break;
|
||||
default:
|
||||
app.Error.WriteLine($"Unknown output type: {outputType}.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
formatter.Format(graph, outputPathArgument.Value);
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
return app.Execute(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
[DebuggerDisplay("{Name}")]
|
||||
public class Project
|
||||
{
|
||||
public Project(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public Repository Repository { get; set; }
|
||||
|
||||
public IList<string> PackageReferences { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
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;
|
||||
using UniverseTools;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
[DebuggerDisplay("{Name}")]
|
||||
public class Repository : IEquatable<Repository>
|
||||
{
|
||||
public Repository(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public IList<Project> Projects { get; } = new List<Project>();
|
||||
|
||||
public IList<Project> SupportProjects { get; } = new List<Project>();
|
||||
|
||||
public IEnumerable<Project> AllProjects => Projects.Concat(SupportProjects);
|
||||
|
||||
public static IList<Repository> ReadAllRepositories(string repositoriesRoot, DependencyGraphSpecProvider provider)
|
||||
{
|
||||
var directories = new DirectoryInfo(repositoriesRoot).GetDirectories();
|
||||
var repositories = new Repository[directories.Length];
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
Parallel.For(0, directories.Length, new ParallelOptions { MaxDegreeOfParallelism = 6 }, i =>
|
||||
{
|
||||
var directoryInfo = directories[i];
|
||||
Console.WriteLine($"Gathering dependency information from {directoryInfo.Name}.");
|
||||
|
||||
var repository = Read(provider, directoryInfo.Name, directoryInfo.FullName);
|
||||
repositories[i] = repository;
|
||||
|
||||
Console.WriteLine($"Done gathering dependency information from {directoryInfo.Name}.");
|
||||
});
|
||||
sw.Stop();
|
||||
|
||||
Console.WriteLine($"Done reading dependency information for all repos in {sw.Elapsed}.");
|
||||
|
||||
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.Combine(repositoryPath, "src");
|
||||
|
||||
var solutionFiles = Directory.EnumerateFiles(repositoryPath, "*.sln");
|
||||
var knownProjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var file in solutionFiles)
|
||||
{
|
||||
var spec = provider.GetDependencyGraphSpec(name, file);
|
||||
foreach (var specProject in spec.Projects)
|
||||
{
|
||||
if (!knownProjects.Add(specProject.FilePath) ||
|
||||
specProject.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var projectPath = Path.GetFullPath(specProject.FilePath);
|
||||
|
||||
var project = new Project(specProject.Name)
|
||||
{
|
||||
PackageReferences = GetPackageReferences(specProject),
|
||||
Repository = repository,
|
||||
};
|
||||
|
||||
var projectGroup = projectPath.StartsWith(srcDirectory, StringComparison.OrdinalIgnoreCase) ?
|
||||
repository.Projects :
|
||||
repository.SupportProjects;
|
||||
projectGroup.Add(project);
|
||||
}
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
private static List<string> GetPackageReferences(NuGet.ProjectModel.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<Project> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BuildGraph
|
||||
{
|
||||
public class TopologicalSort : IComparer<GraphNode>
|
||||
{
|
||||
public static readonly TopologicalSort Instance = new TopologicalSort();
|
||||
|
||||
public int Compare(GraphNode x, GraphNode y)
|
||||
{
|
||||
var xScore = GetOrder(x);
|
||||
var yScore = GetOrder(y);
|
||||
return xScore.CompareTo(yScore);
|
||||
}
|
||||
|
||||
public static int GetOrder(GraphNode node)
|
||||
{
|
||||
var visited = new List<GraphNode>();
|
||||
return GetOrder(node, visited);
|
||||
}
|
||||
|
||||
private static int GetOrder(GraphNode node, List<GraphNode> visited)
|
||||
{
|
||||
if (visited.Contains(node))
|
||||
{
|
||||
var cycle = string.Join(" -> ", visited.Select(v => v.Repository.Name));
|
||||
throw new Exception($"Cycle detected in the build graph: {cycle} -> {node.Repository.Name}.");
|
||||
}
|
||||
|
||||
var score = 0;
|
||||
visited.Add(node);
|
||||
foreach (var dependentNode in node.Incoming)
|
||||
{
|
||||
score = Math.Max(score, GetOrder(dependentNode, visited));
|
||||
}
|
||||
visited.RemoveAt(visited.Count - 1);
|
||||
|
||||
return score + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinVersion", "PinVersion\PinVersion.xproj", "{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>3d3b5750-0c24-4f1c-9304-b5e4d85cf5a0</ProjectGuid>
|
||||
<RootNamespace>PinVersion</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NuGet.Common;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using NuGet.Protocol.Core.v3;
|
||||
using NuGet.Versioning;
|
||||
|
||||
namespace PinVersion
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static ConcurrentDictionary<string, Task<NuGetVersion>> _packageVersionLookup =
|
||||
new ConcurrentDictionary<string, Task<NuGetVersion>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
if (args.Length != 3)
|
||||
{
|
||||
Console.Error.WriteLine("Usage <package source> <Korebuild Tag> <repository-names-file>");
|
||||
}
|
||||
|
||||
var packageSource = args[0];
|
||||
var korebuildTag = args[1];
|
||||
|
||||
var repositoryNames = File.ReadAllLines(args[2]);
|
||||
|
||||
Task.WaitAll(repositoryNames
|
||||
.Select(repositoryPath => ExecuteAsync(repositoryPath, packageSource, korebuildTag))
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
public static async Task ExecuteAsync(string repositoryPath, string packageSource, string korebuildTag)
|
||||
{
|
||||
var packageRepository = Repository.Factory.GetCoreV3(packageSource);
|
||||
var metadataResource = await packageRepository.GetResourceAsync<MetadataResource>();
|
||||
|
||||
// Pin project.json files
|
||||
foreach (var file in Directory.EnumerateFiles(repositoryPath, "project.json", SearchOption.AllDirectories))
|
||||
{
|
||||
var projectJson = JObject.Parse(File.ReadAllText(file));
|
||||
var projectName = Path.GetFileName(Path.GetDirectoryName(file));
|
||||
var latestPackageVersion = await GetOrAddVersion(metadataResource, projectName);
|
||||
if (latestPackageVersion != null)
|
||||
{
|
||||
((JValue)projectJson["version"]).Value = latestPackageVersion.ToNormalizedString();
|
||||
}
|
||||
|
||||
var frameworkDependencies = projectJson["frameworks"]
|
||||
?.Cast<JProperty>()
|
||||
?.Select(f => ((JObject)f.Value)["dependencies"])
|
||||
?? Enumerable.Empty<JToken>();
|
||||
var dependencies = Enumerable.Concat(new[] { projectJson["dependencies"] }, frameworkDependencies)
|
||||
.Where(d => d != null)
|
||||
.SelectMany(d => d)
|
||||
.Cast<JProperty>();
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
latestPackageVersion = await GetOrAddVersion(metadataResource, dependency.Name);
|
||||
if (latestPackageVersion != null)
|
||||
{
|
||||
if (dependency.Value.Type == JTokenType.Object)
|
||||
{
|
||||
// "key": { "version": "1.0.0-*", "type": "build" }
|
||||
var value = (JObject)dependency.Value;
|
||||
value["version"] = latestPackageVersion.ToNormalizedString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// "key": "version"
|
||||
dependency.Value = latestPackageVersion.ToNormalizedString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (var fileWriter = new JsonTextWriter(new StreamWriter(file)))
|
||||
{
|
||||
fileWriter.Formatting = Formatting.Indented;
|
||||
fileWriter.Indentation = 2;
|
||||
projectJson.WriteTo(fileWriter);
|
||||
}
|
||||
|
||||
// Update KoreBuild path
|
||||
|
||||
var buildFiles = new[] { "build.ps1", "build.sh" };
|
||||
foreach (var buildFile in buildFiles)
|
||||
{
|
||||
var buildFilePath = Path.Combine(repositoryPath, buildFile);
|
||||
if (File.Exists(buildFilePath))
|
||||
{
|
||||
var content = File.ReadAllText(buildFilePath);
|
||||
var replaced = content.Replace("KoreBuild/archive/release.zip", $"KoreBuild/archive/{korebuildTag}.zip");
|
||||
|
||||
if (content != replaced)
|
||||
{
|
||||
File.WriteAllText(buildFilePath, replaced);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Task<NuGetVersion> GetOrAddVersion(MetadataResource resource, string packageId)
|
||||
{
|
||||
return _packageVersionLookup.GetOrAdd(packageId, id =>
|
||||
{
|
||||
return resource.GetLatestVersion(
|
||||
packageId,
|
||||
includePrerelease: true,
|
||||
includeUnlisted: false,
|
||||
log: NullLogger.Instance,
|
||||
token: default(CancellationToken));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"NuGet.Protocol.Core.v3": "3.5.0-beta-final"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": { }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using NuGet.Common;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.LibraryModel;
|
||||
using NuGet.ProjectModel;
|
||||
using NuGet.Protocol;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using NuGet.Versioning;
|
||||
using UniverseTools;
|
||||
|
||||
namespace PinVersions
|
||||
{
|
||||
class PinVersionUtility
|
||||
{
|
||||
private readonly string _repositoryRoot;
|
||||
private readonly FindPackageByIdResource[] _findPackageResources;
|
||||
private readonly ConcurrentDictionary<string, Task<NuGetVersion>> _exactMatches = new ConcurrentDictionary<string, Task<NuGetVersion>>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly DependencyGraphSpecProvider _provider;
|
||||
private readonly SourceCacheContext _sourceCacheContext;
|
||||
|
||||
public PinVersionUtility(string repositoryRoot, List<string> pinSources, DependencyGraphSpecProvider provider)
|
||||
{
|
||||
_repositoryRoot = repositoryRoot;
|
||||
_findPackageResources = new FindPackageByIdResource[pinSources.Count];
|
||||
for (var i = 0; i < pinSources.Count; i++)
|
||||
{
|
||||
var repository = FactoryExtensionsV3.GetCoreV3(Repository.Factory, pinSources[i].Trim());
|
||||
_findPackageResources[i] = repository.GetResource<FindPackageByIdResource>();
|
||||
}
|
||||
_provider = provider;
|
||||
_sourceCacheContext = new SourceCacheContext();
|
||||
}
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
var repositoryDirectoryInfo = new DirectoryInfo(_repositoryRoot);
|
||||
var knownProjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var slnFile in repositoryDirectoryInfo.EnumerateFiles("*.sln"))
|
||||
{
|
||||
var graphSpec = _provider.GetDependencyGraphSpec(repositoryDirectoryInfo.Name, slnFile.FullName);
|
||||
foreach (var specProject in graphSpec.Projects)
|
||||
{
|
||||
if (!knownProjects.Add(specProject.FilePath) ||
|
||||
specProject.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var projectFileInfo = new FileInfo(specProject.FilePath);
|
||||
var pinnedReferencesFile = Path.Combine(
|
||||
specProject.RestoreMetadata.OutputPath,
|
||||
projectFileInfo.Name + ".pinnedversions.targets");
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(pinnedReferencesFile));
|
||||
|
||||
var allDependencies = specProject.Dependencies.Select(dependency => new { Dependency = dependency, FrameworkName = NuGetFramework.AnyFramework })
|
||||
.Concat(specProject.TargetFrameworks.SelectMany(tfm => tfm.Dependencies.Select(dependency => new { Dependency = dependency, tfm.FrameworkName })))
|
||||
.Where(d => d.Dependency.LibraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package));
|
||||
|
||||
var packageReferencesItemGroup = new XElement("ItemGroup");
|
||||
foreach (var dependency in allDependencies)
|
||||
{
|
||||
var reference = dependency.Dependency;
|
||||
var versionRange = reference.LibraryRange.VersionRange;
|
||||
if (!versionRange.IsFloating)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var exactVersion = GetExactVersion(reference.Name, versionRange);
|
||||
if (exactVersion == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var metadata = new List<XAttribute>
|
||||
{
|
||||
new XAttribute("Update", reference.Name),
|
||||
new XAttribute("Version", exactVersion.ToNormalizedString()),
|
||||
};
|
||||
|
||||
if (dependency.FrameworkName != NuGetFramework.AnyFramework)
|
||||
{
|
||||
metadata.Add(new XAttribute("Condition", $"'$(TargetFramework)'=='{dependency.FrameworkName.GetShortFolderName()}'"));
|
||||
}
|
||||
|
||||
packageReferencesItemGroup.Add(new XElement("PackageReference", metadata));
|
||||
}
|
||||
|
||||
var pinnedVersionRoot = new XElement("Project", packageReferencesItemGroup);
|
||||
File.WriteAllText(pinnedReferencesFile, pinnedVersionRoot.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NuGetVersion GetExactVersion(string name, VersionRange range)
|
||||
{
|
||||
if (range.MinVersion == null)
|
||||
{
|
||||
throw new Exception($"Unsupported version range {range}.");
|
||||
}
|
||||
|
||||
if (!_exactMatches.TryGetValue(name, out var versionTask))
|
||||
{
|
||||
versionTask = _exactMatches.GetOrAdd(name, GetExactVersionAsync(name, range.MinVersion));
|
||||
}
|
||||
|
||||
return versionTask.Result;
|
||||
}
|
||||
|
||||
private async Task<NuGetVersion> GetExactVersionAsync(string name, NuGetVersion floatingVersion)
|
||||
{
|
||||
foreach (var findPackageResource in _findPackageResources)
|
||||
{
|
||||
var packageVersions = await findPackageResource.GetAllVersionsAsync(name, _sourceCacheContext, NullLogger.Instance, default(CancellationToken));
|
||||
|
||||
var matchingVersions = packageVersions.Where(v => v.Version == floatingVersion.Version).ToList();
|
||||
switch (matchingVersions.Count)
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return matchingVersions[0];
|
||||
default:
|
||||
throw new Exception($"More than one version for {name} found that matches the specified version constraint: {string.Join(" ", matchingVersions)}.");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\shared\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Cli.Utils" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
using UniverseTools;
|
||||
|
||||
namespace PinVersions
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandLineApplication();
|
||||
|
||||
var pinSourceOption = app.Option("-s|--source",
|
||||
"Feed containing packages to pin.",
|
||||
CommandOptionType.MultipleValue);
|
||||
|
||||
var packageSpecsDirectoryOption = app.Option("--graph-specs-root",
|
||||
"Directory containing package specs. (Optional)",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
var repositoryArgument = app.Argument("Repository", "Repository directory");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
if (!pinSourceOption.HasValue())
|
||||
{
|
||||
Console.Error.WriteLine($"Option {pinSourceOption.Template} must have a value.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(repositoryArgument.Value))
|
||||
{
|
||||
Console.Error.WriteLine($"Repository argument must be specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var graphSpecProvider = packageSpecsDirectoryOption.HasValue() ?
|
||||
new DependencyGraphSpecProvider(packageSpecsDirectoryOption.Value().Trim()) :
|
||||
DependencyGraphSpecProvider.Default;
|
||||
|
||||
using (graphSpecProvider)
|
||||
{
|
||||
var pinVersionUtility = new PinVersionUtility(repositoryArgument.Value.Trim(), pinSourceOption.Values, graphSpecProvider);
|
||||
pinVersionUtility.Execute();
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
return app.Execute(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using NuGet.ProjectModel;
|
||||
|
||||
namespace UniverseTools
|
||||
{
|
||||
public class DependencyGraphSpecProvider : IDisposable
|
||||
{
|
||||
private readonly string _packageSpecDirectory;
|
||||
private readonly bool _deleteSpecDirectoryOnDispose;
|
||||
private readonly string _muxerPath;
|
||||
|
||||
public DependencyGraphSpecProvider(string packageSpecDirectory)
|
||||
: this(packageSpecDirectory, deleteSpecDirectoryOnDispose: false)
|
||||
{
|
||||
}
|
||||
|
||||
private DependencyGraphSpecProvider(string packageSpecDirectory, bool deleteSpecDirectoryOnDispose)
|
||||
{
|
||||
_packageSpecDirectory = packageSpecDirectory;
|
||||
_deleteSpecDirectoryOnDispose = deleteSpecDirectoryOnDispose;
|
||||
_muxerPath = new Muxer().MuxerPath;
|
||||
}
|
||||
|
||||
public static DependencyGraphSpecProvider Default { get; } =
|
||||
new DependencyGraphSpecProvider(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()), deleteSpecDirectoryOnDispose: true);
|
||||
|
||||
public DependencyGraphSpec GetDependencyGraphSpec(string repositoryName, string solutionPath)
|
||||
{
|
||||
var outputFile = Path.Combine(_packageSpecDirectory, repositoryName, Path.GetFileName(solutionPath) + ".json");
|
||||
|
||||
if (!File.Exists(outputFile))
|
||||
{
|
||||
RunMSBuild(solutionPath, outputFile);
|
||||
}
|
||||
|
||||
return DependencyGraphSpec.Load(outputFile);
|
||||
}
|
||||
|
||||
private void RunMSBuild(string solutionPath, string outputFile)
|
||||
{
|
||||
var psi = new ProcessStartInfo(_muxerPath);
|
||||
|
||||
var arguments = new List<string>
|
||||
{
|
||||
"msbuild",
|
||||
$"\"{solutionPath}\"",
|
||||
"/t:GenerateRestoreGraphFile",
|
||||
"/nologo",
|
||||
"/v:q",
|
||||
"/p:BuildProjectReferences=false",
|
||||
$"/p:RestoreGraphOutputPath=\"{outputFile}\"",
|
||||
};
|
||||
|
||||
psi.Arguments = string.Join(" ", arguments);
|
||||
psi.RedirectStandardOutput = true;
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = psi,
|
||||
EnableRaisingEvents = true,
|
||||
};
|
||||
process.OutputDataReceived += (sender, args) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(args.Data))
|
||||
{
|
||||
Console.WriteLine(args.Data);
|
||||
}
|
||||
};
|
||||
|
||||
using (process)
|
||||
{
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
|
||||
process.WaitForExit(60 * 5000);
|
||||
if (process.ExitCode != 0)
|
||||
{
|
||||
throw new Exception($"{psi.FileName} {psi.Arguments} failed. Exit code {process.ExitCode}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_deleteSpecDirectoryOnDispose)
|
||||
{
|
||||
Directory.Delete(_packageSpecDirectory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue