From aa25401a502b4a9971edaa0097620774a7977ae4 Mon Sep 17 00:00:00 2001 From: Pranav K <prkrishn@hotmail.com> Date: Fri, 7 Jul 2017 16:19:53 -0700 Subject: [PATCH] Make the calculation of the build graph a task so we can pass metadata around --- NuGet.Config | 1 + Universe.sln | 6 -- build/RepositoryBuild.targets | 41 +++------ build/repo.targets | 80 ++++++------------ build/tasks/BuildGraph/CalculateBuildGraph.cs | 65 ++++++++++++++ .../BuildGraph/DependencyGraphSpecProvider.cs | 21 +++++ .../tasks}/BuildGraph/GraphBuilder.cs | 6 +- .../tasks}/BuildGraph/GraphNode.cs | 2 +- {tools => build/tasks}/BuildGraph/Project.cs | 4 +- .../tasks}/BuildGraph/Repository.cs | 31 +++---- .../tasks}/BuildGraph/TopologicalSort.cs | 2 +- build/tasks/RepoTasks.csproj | 13 +++ build/tasks/RepoTasks.tasks | 7 ++ tools/BuildGraph/BuildGraph.csproj | 16 ---- tools/BuildGraph/DGMLFormatter.cs | 56 ------------- tools/BuildGraph/GraphFormatter.cs | 9 -- tools/BuildGraph/MSBuildGraphFormatter.cs | 23 ----- tools/BuildGraph/Program.cs | 84 ------------------- 18 files changed, 163 insertions(+), 304 deletions(-) create mode 100644 build/tasks/BuildGraph/CalculateBuildGraph.cs create mode 100644 build/tasks/BuildGraph/DependencyGraphSpecProvider.cs rename {tools => build/tasks}/BuildGraph/GraphBuilder.cs (92%) rename {tools => build/tasks}/BuildGraph/GraphNode.cs (92%) rename {tools => build/tasks}/BuildGraph/Project.cs (93%) rename {tools => build/tasks}/BuildGraph/Repository.cs (79%) rename {tools => build/tasks}/BuildGraph/TopologicalSort.cs (97%) create mode 100644 build/tasks/RepoTasks.csproj create mode 100644 build/tasks/RepoTasks.tasks delete mode 100644 tools/BuildGraph/BuildGraph.csproj delete mode 100644 tools/BuildGraph/DGMLFormatter.cs delete mode 100644 tools/BuildGraph/GraphFormatter.cs delete mode 100644 tools/BuildGraph/MSBuildGraphFormatter.cs delete mode 100644 tools/BuildGraph/Program.cs diff --git a/NuGet.Config b/NuGet.Config index 7604d0051e1..cbeb8fa20d8 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -2,6 +2,7 @@ <configuration> <packageSources> <clear /> + <add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-release/api/v3/index.json" /> <add key="NuGet" value="https://api.nuget.org/v3/index.json" /> </packageSources> </configuration> diff --git a/Universe.sln b/Universe.sln index c4f59d60fe0..d1dd9a12a56 100644 --- a/Universe.sln +++ b/Universe.sln @@ -3,8 +3,6 @@ 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}" @@ -18,10 +16,6 @@ Global 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 {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 diff --git a/build/RepositoryBuild.targets b/build/RepositoryBuild.targets index f733ef2caef..52fe532c384 100644 --- a/build/RepositoryBuild.targets +++ b/build/RepositoryBuild.targets @@ -1,14 +1,13 @@ <Project> - <Import Project="$(_BuildGraphFile)" /> - - <Target Name="BuildRepositories"> + <Target Name="_BuildRepositories"> <ItemGroup> <BatchedRepository Include="$(MSBuildProjectFullPath)"> <BuildGroup>%(RepositoryToBuildInOrder.Order)</BuildGroup> <Repository>%(RepositoryToBuildInOrder.Identity)</Repository> <AdditionalProperties> RepositoryToBuild=%(RepositoryToBuildInOrder.Identity); - BuildRepositoryRoot=$(_CloneRepositoryRoot)%(RepositoryToBuildInOrder.Identity)\ + BuildRepositoryRoot=%(RepositoryToBuildInOrder.RepositoryPath)\; + CommitHash=%(RepositoryToBuildInOrder.Commit) </AdditionalProperties> </BatchedRepository> </ItemGroup> @@ -18,26 +17,6 @@ <BatchBuilds Condition="'$(BatchBuilds)'==''">false</BatchBuilds> </PropertyGroup> - <Message - Text="Building repositories in the following batches:" - Importance="High" - Condition="'$(BatchBuilds)'=='true'" /> - - <Message - Text="%(BatchedRepository.BuildGroup): @(BatchedRepository -> '%(Repository)', ', ')" - Importance="High" - Condition="'$(BatchBuilds)'=='true'" /> - - <Message - Text="Building repositories in the following order:" - Importance="High" - Condition="'$(BatchBuilds)'!='true'" /> - - <Message - Text="%(BatchedRepository.Repository)" - Importance="High" - Condition="'$(BatchBuilds)'!='true'" /> - <MSBuild Projects="@(BatchedRepository)" BuildInParallel="$(BatchBuilds)" @@ -48,6 +27,9 @@ <Target Name="_BuildRepository" DependsOnTargets="_PinVersions"> <PropertyGroup> + <!-- If there are duplicate properties, the properties which are defined later in the order would override the earlier ones --> + <RepositoryBuildArguments>$(RepositoryBuildArguments) /p:BuildNumber=$(BuildNumber) /p:Configuration=$(Configuration) /p:CommitHash=$(CommitHash)</RepositoryBuildArguments> + <BuildArguments>$(_RepositoryBuildTargets) $(RepositoryBuildArguments)</BuildArguments> <RepositoryArtifactsRoot>$(BuildRepositoryRoot)artifacts</RepositoryArtifactsRoot> <RepositoryArtifactsBuildDirectory>$(RepositoryArtifactsRoot)\build\</RepositoryArtifactsBuildDirectory> @@ -83,26 +65,27 @@ <Copy SourceFiles="@(RepositoryArtifacts)" - DestinationFolder="$(UniverseBuildDir)" /> + DestinationFolder="$(BuildDir)" /> <Move SourceFiles="@(RepositoryMSBuildArtifacts)" - DestinationFolder="$(UniverseMSBuildDir)\$(RepositoryToBuild)\%(RecursiveDir)" /> + DestinationFolder="$(ArtifactsDir)msbuild\$(RepositoryToBuild)\%(RecursiveDir)" /> <Message Text="Publishing the following packages to the volatile feed: @(RepositoryNupkgs -> '%(Filename)%(Extension)', ', ')" Condition="'$(PublishPackages)'=='true' AND '@(RepositoryNupkgs)' != ''" /> <Exec - Command="$(DotNetPath) $(PackagePublisherPath) -d $(RepositoryArtifactsBuildDirectory) -f $(NuGetPublishVolatileFeed)" + Command="$(DotNetPath) $(PackagePublisherNetCoreApp) -d $(RepositoryArtifactsBuildDirectory) -f $(NuGetPublishVolatileFeed)" Condition="'$(PublishPackages)'=='true' AND '@(RepositoryNupkgs)' != ''" /> <Message Text="============ Done building $(RepositoryToBuild) ============" Importance="High" /> </Target> - <Target Name="_PinVersions"> + <Target Name="_PinVersions" DependsOnTargets="_FindDotNetPath"> + <PropertyGroup> <PinToolBinary>$(RepositoryRoot)tools\PinVersions\bin\$(Configuration)\netcoreapp1.1\PinVersions.dll</PinToolBinary> - <PinVersionArgs>$(DotNetPath) $(PinToolBinary) --graph-specs-root "$(_RestoreGraphSpecsDirectory) " -s "$(UniverseBuildDir) " "$(BuildRepositoryRoot) "</PinVersionArgs> + <PinVersionArgs>$(DotNetPath) $(PinToolBinary) --graph-specs-root "$(_RestoreGraphSpecsDirectory) " -s "$(BuildDir) " "$(BuildRepositoryRoot) "</PinVersionArgs> <PinVersionArgs Condition="Exists('$(_DependencyPackagesDirectory)')">$(PinVersionArgs) -s "$(_DependencyPackagesDirectory) "</PinVersionArgs> </PropertyGroup> diff --git a/build/repo.targets b/build/repo.targets index 7aa7207cf22..2aa28e05ab3 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -1,8 +1,9 @@ <Project> + <Import Project="RepositoryBuild.targets" /> + <PropertyGroup> <NuGetPublishVolatileFeed>https://dotnet.myget.org/F/aspnetcore-volatile-dev/api/v2/package</NuGetPublishVolatileFeed> - <_BuildGraphFile>$(BuildDir)BuildGraph.proj</_BuildGraphFile> <_CloneRepositoryRoot>$(RepositoryRoot).r\</_CloneRepositoryRoot> <_DependencyBuildDirectory>$(RepositoryRoot).deps\build\</_DependencyBuildDirectory> <_DependencyPackagesDirectory>$(_DependencyBuildDirectory)</_DependencyPackagesDirectory> @@ -33,7 +34,7 @@ <RemoveDir Directories="$(_CloneRepositoryRoot)" Condition="Exists('$(_CloneRepositoryRoot)')" /> </Target> - <Target Name="_FilterRepositories"> + <Target Name="_PrepareRepositories"> <ItemGroup Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)'!=''"> <_RepositoriesToInclude Include="$(KOREBUILD_REPOSITORY_INCLUDE)" /> <Repository @@ -49,10 +50,12 @@ <Error Text="KOREBUILD_REPOSITORY_EXCLUDE AND KOREBUILD_REPOSITORY_INCLUDE are specified." Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)' != '' AND '$(KOREBUILD_REPOSITORY_EXCLUDE)' != ''" /> - <Message Text="%(Repository.CloneUrl)" /> + <ItemGroup> + <Repository Update="%(Identity)" RepositoryPath="$(_CloneRepositoryRoot)%(Identity)" /> + </ItemGroup> </Target> - <Target Name="CloneRepositories" DependsOnTargets="_FilterRepositories"> + <Target Name="CloneRepositories" DependsOnTargets="_PrepareRepositories"> <ItemGroup> <_CloneRepository Include="$(MSBuildProjectFullPath)"> <AdditionalProperties> @@ -72,6 +75,7 @@ <MSBuild Projects="@(_CloneRepository)" Targets="_CloneRepository" BuildInParallel="$(BuildInParallel)" /> + </Target> <Target Name="_CloneRepository"> @@ -107,45 +111,9 @@ </Target> <Target Name="BuildRepositories" - DependsOnTargets="_FilterRepositories;_FindDotNetPath;_GenerateRestoreGraphSpecs;_GenerateBuildGraph;_UpdateNuGetConfig;_CreateRepositoriesListWithCommits"> - - <PropertyGroup> - <!-- If there are duplicate properties, the properties which are defined later in the order would override the earlier ones --> - <RepositoryBuildArguments>$(RepositoryBuildArguments) /p:BuildNumber=$(BuildNumber) /p:Configuration=$(Configuration)</RepositoryBuildArguments> - - <_BuildRepositoryProperties> - UniverseBuildDir=$(BuildDir); - UniverseMSBuildDir=$(ArtifactsDir)msbuild; - BuildInParallel=$(BuildInParallel); - Configuration=$(Configuration); - DotNetPath=$(DotNetPath); - KoreBuildDirectory=$(MSBuildProjectDirectory)\; - KoreBuildProject=$(MSBuildProjectFile); - RepositoryRoot=$(RepositoryRoot); - _BuildGraphFile=$(_BuildGraphFile); - _CloneRepositoryRoot=$(_CloneRepositoryRoot); - _DependencyPackagesDirectory=$(_DependencyPackagesDirectory); - _RepositoryBuildTargets=$(_RepositoryBuildTargets); - RepositoryBuildArguments=$(RepositoryBuildArguments); - _RestoreGraphSpecsDirectory=$(_RestoreGraphSpecsDirectory); - PackagePublisherPath=$(PackagePublisherNetCoreApp) - </_BuildRepositoryProperties> - - <_BuildRepositoryProperties Condition="'$(PublishPackages)'=='true'"> - $(_BuildRepositoryProperties); - APIKey=$(APIKey); - NuGetPublishVolatileFeed=$(NuGetPublishVolatileFeed); - PublishPackages=$(PublishPackages) - </_BuildRepositoryProperties> - </PropertyGroup> - - <MSBuild - Projects="$(MSBuildThisFileDirectory)RepositoryBuild.targets" - Targets="BuildRepositories" - Properties="$(_BuildRepositoryProperties)" /> - </Target> + DependsOnTargets="_PrepareRepositories;_FindDotNetPath;_CreateRepositoriesListWithCommits;_UpdateNuGetConfig;_GenerateBuildGraph;_BuildRepositories" /> - <Target Name="_GenerateRestoreGraphSpecs" DependsOnTargets="_FindDotNetPath"> + <Target Name="_PrepareRestoreGraphSpecs" DependsOnTargets="_PrepareRepositories"> <ItemGroup> <Solution Include="$(_CloneRepositoryRoot)%(Repository.Identity)\*.sln"> <Repository>%(Repository.Identity)</Repository> @@ -154,22 +122,26 @@ <Solution> <AdditionalProperties>RestoreGraphOutputPath=$(_RestoreGraphSpecsDirectory)%(Solution.Repository)\%(Solution.FileName)%(Solution.Extension).json</AdditionalProperties> </Solution> + + <GraphSpecInputs Include=" + @(Solution); + $(_CloneRepositoryRoot)**\*.csproj; + $(_CloneRepositoryRoot)**\dependencies.props" /> + <GraphSpecOutputs Include="$(_RestoreGraphSpecsDirectory)%(Solution.Repository)\%(Solution.FileName)%(Solution.Extension).json" /> </ItemGroup> + </Target> + <Target Name="_GenerateRestoreGraphSpecs" DependsOnTargets="_PrepareRestoreGraphSpecs" Inputs="@(GraphSpecInputs)" Outputs="@(GraphSpecOutputs)"> <MSBuild Projects="@(Solution)" Targets="GenerateRestoreGraphFile" BuildInParallel="$(BuildInParallel)" /> </Target> - <Target Name="_GenerateBuildGraph" DependsOnTargets="_FindDotNetPath"> - <PropertyGroup> - <BuildGrapArgs>$(DotNetPath) run -r "$(_CloneRepositoryRoot) " --graph-specs-root "$(_RestoreGraphSpecsDirectory) " "$(_BuildGraphFile)"</BuildGrapArgs> - <BuildGrapArgs Condition="'$(BuildGraphOf)'!=''">$(BuildGrapArgs) --start-at $(BuildGraphOf)</BuildGrapArgs> - </PropertyGroup> - <Exec - Command="$(BuildGrapArgs)" - WorkingDirectory="$(RepositoryRoot)tools\BuildGraph\" /> + <Target Name="_GenerateBuildGraph" DependsOnTargets="_GenerateRestoreGraphSpecs"> + <RepoTasks.CalculateBuildGraph Repositories="@(Repository)" StartGraphAt="$(BuildGraphOf)" PackageSpecsDirectory="$(_RestoreGraphSpecsDirectory)"> + <Output TaskParameter="RepositoriesToBuildInOrder" ItemName="RepositoryToBuildInOrder" /> + </RepoTasks.CalculateBuildGraph> </Target> <Target Name="_UpdateNuGetConfig"> @@ -216,16 +188,14 @@ --> <_CloneUrl>$([System.Environment]::GetEnvironmentVariable("vcsroot.%(Repository.Identity).url"))</_CloneUrl> <_CommitHash>$([System.Environment]::GetEnvironmentVariable("build.vcs.number.%(Repository.Identity)"))</_CommitHash> - - <RepositoryCloneDirectory>$(_CloneRepositoryRoot)%(Repository.Identity)</RepositoryCloneDirectory> </PropertyGroup> <Warning Text="%(Repository.Identity) has not been cloned." - Condition="!Exists('$(RepositoryCloneDirectory)')" /> + Condition="!Exists('%(Repository.RepositoryPath)')" /> <GetGitCommitInfo - WorkingDirectory="$(RepositoryCloneDirectory)" - Condition="'$(_CommitHash)'=='' AND Exists('$(RepositoryCloneDirectory)')"> + WorkingDirectory="%(Repository.RepositoryPath)" + Condition="'$(_CommitHash)'=='' AND Exists('%(Repository.RepositoryPath)')"> <Output TaskParameter="CommitHash" PropertyName="_CommitHash" /> </GetGitCommitInfo> diff --git a/build/tasks/BuildGraph/CalculateBuildGraph.cs b/build/tasks/BuildGraph/CalculateBuildGraph.cs new file mode 100644 index 00000000000..6e1dc6de2b4 --- /dev/null +++ b/build/tasks/BuildGraph/CalculateBuildGraph.cs @@ -0,0 +1,65 @@ +// 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; } + + [Output] + public ITaskItem[] RepositoriesToBuildInOrder { get; set; } + + /// <summary> + /// The repository at which to root the graph at + /// </summary> + public string StartGraphAt { get; set; } + + /// <summary> + /// Directory that contains the package spec files. + /// </summary> + [Required] + public string PackageSpecsDirectory { get; set; } + + public override bool Execute() + { + var graphSpecProvider = new DependencyGraphSpecProvider(PackageSpecsDirectory.Trim()); + + var repositoryPaths = Repositories.Select(r => r.GetMetadata("RepositoryPath")).ToList(); + var repositories = Repository.ReadAllRepositories(repositoryPaths, graphSpecProvider); + + var graph = GraphBuilder.Generate(repositories, StartGraphAt); + var repositoriesWithOrder = new List<(ITaskItem repository, int order)>(); + foreach (var repositoryTaskItem in Repositories) + { + var repositoryName = repositoryTaskItem.ItemSpec; + var graphNodeRepository = graph.First(g => g.Repository.Name == repositoryName); + 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/BuildGraph/DependencyGraphSpecProvider.cs b/build/tasks/BuildGraph/DependencyGraphSpecProvider.cs new file mode 100644 index 00000000000..805033c1c2e --- /dev/null +++ b/build/tasks/BuildGraph/DependencyGraphSpecProvider.cs @@ -0,0 +1,21 @@ +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"); + return DependencyGraphSpec.Load(outputFile); + } + } +} diff --git a/tools/BuildGraph/GraphBuilder.cs b/build/tasks/BuildGraph/GraphBuilder.cs similarity index 92% rename from tools/BuildGraph/GraphBuilder.cs rename to build/tasks/BuildGraph/GraphBuilder.cs index 0cf9fc7f241..81993354332 100644 --- a/tools/BuildGraph/GraphBuilder.cs +++ b/build/tasks/BuildGraph/GraphBuilder.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace BuildGraph +namespace RepoTools.BuildGraph { public static class GraphBuilder { @@ -19,7 +19,7 @@ namespace BuildGraph foreach (var project in repositories.SelectMany(r => r.AllProjects)) { var thisProjectRepositoryNode = graphNodes[project.Repository]; - if (root != null && string.Equals(root, project.Repository.Name, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(root) && string.Equals(root, project.Repository.Name, StringComparison.OrdinalIgnoreCase)) { searchRoot = thisProjectRepositoryNode; } @@ -58,4 +58,4 @@ namespace BuildGraph } } } -} \ No newline at end of file +} diff --git a/tools/BuildGraph/GraphNode.cs b/build/tasks/BuildGraph/GraphNode.cs similarity index 92% rename from tools/BuildGraph/GraphNode.cs rename to build/tasks/BuildGraph/GraphNode.cs index 236ff6aee5d..8c2a023ab2e 100644 --- a/tools/BuildGraph/GraphNode.cs +++ b/build/tasks/BuildGraph/GraphNode.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Diagnostics; -namespace BuildGraph +namespace RepoTools.BuildGraph { [DebuggerDisplay("{Repository.Name}")] public class GraphNode diff --git a/tools/BuildGraph/Project.cs b/build/tasks/BuildGraph/Project.cs similarity index 93% rename from tools/BuildGraph/Project.cs rename to build/tasks/BuildGraph/Project.cs index af8761e8292..10a821a336b 100644 --- a/tools/BuildGraph/Project.cs +++ b/build/tasks/BuildGraph/Project.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; -namespace BuildGraph +namespace RepoTools.BuildGraph { [DebuggerDisplay("{Name}")] public class Project @@ -20,4 +20,4 @@ namespace BuildGraph public ISet<string> PackageReferences { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase); } -} \ No newline at end of file +} diff --git a/tools/BuildGraph/Repository.cs b/build/tasks/BuildGraph/Repository.cs similarity index 79% rename from tools/BuildGraph/Repository.cs rename to build/tasks/BuildGraph/Repository.cs index e8893d7ff87..c71ade8555c 100644 --- a/tools/BuildGraph/Repository.cs +++ b/build/tasks/BuildGraph/Repository.cs @@ -6,9 +6,8 @@ using System.Linq; using System.Threading.Tasks; using NuGet.LibraryModel; using NuGet.ProjectModel; -using UniverseTools; -namespace BuildGraph +namespace RepoTools.BuildGraph { [DebuggerDisplay("{Name}")] public class Repository : IEquatable<Repository> @@ -26,25 +25,17 @@ namespace BuildGraph public IEnumerable<Project> AllProjects => Projects.Concat(SupportProjects); - public static IList<Repository> ReadAllRepositories(string repositoriesRoot, DependencyGraphSpecProvider provider) + public static IList<Repository> ReadAllRepositories(IList<string> repositoryPaths, DependencyGraphSpecProvider provider) { - var directories = new DirectoryInfo(repositoriesRoot).GetDirectories(); - var repositories = new Repository[directories.Length]; + var repositories = new Repository[repositoryPaths.Count]; - var sw = Stopwatch.StartNew(); - Parallel.For(0, directories.Length, new ParallelOptions { MaxDegreeOfParallelism = 6 }, i => + Parallel.For(0, repositoryPaths.Count, 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); + var repositoryPath = repositoryPaths[i]; + var repositoryName = Path.GetFileName(repositoryPath); + var repository = Read(provider, repositoryName, repositoryPath); 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; } @@ -58,7 +49,8 @@ namespace BuildGraph var repository = new Repository(name); ReadSharedSourceProjects(Path.Combine(repositoryPath, "shared"), repository, repository.Projects); - var srcDirectory = Path.Combine(repositoryPath, "src"); + var srcDirectory = Path.GetFullPath(Path.Combine(repositoryPath, "src")) + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); var solutionFiles = Directory.EnumerateFiles(repositoryPath, "*.sln"); foreach (var file in solutionFiles) @@ -67,7 +59,8 @@ namespace BuildGraph var projects = spec.Projects.OrderBy(p => p.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference ? 0 : 1); foreach (var specProject in projects) { - var projectPath = Path.GetFullPath(specProject.FilePath); + var projectPath = Path.GetFullPath(specProject.FilePath) + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); var projectGroup = projectPath.StartsWith(srcDirectory, StringComparison.OrdinalIgnoreCase) ? repository.Projects : @@ -126,4 +119,4 @@ namespace BuildGraph } } } -} \ No newline at end of file +} diff --git a/tools/BuildGraph/TopologicalSort.cs b/build/tasks/BuildGraph/TopologicalSort.cs similarity index 97% rename from tools/BuildGraph/TopologicalSort.cs rename to build/tasks/BuildGraph/TopologicalSort.cs index 308d9eef772..4d362be3e4c 100644 --- a/tools/BuildGraph/TopologicalSort.cs +++ b/build/tasks/BuildGraph/TopologicalSort.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace BuildGraph +namespace RepoTools.BuildGraph { public class TopologicalSort : IComparer<GraphNode> { diff --git a/build/tasks/RepoTasks.csproj b/build/tasks/RepoTasks.csproj new file mode 100644 index 00000000000..d0f925d5d18 --- /dev/null +++ b/build/tasks/RepoTasks.csproj @@ -0,0 +1,13 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <Import Project="$(RepoTasksSdkPath)\Sdk.props" Condition="'$(RepoTasksSdkPath)' != '' "/> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="NuGet.ProjectModel" Version="4.0.0" /> + </ItemGroup> + + <Import Project="$(RepoTasksSdkPath)\Sdk.targets" Condition="'$(RepoTasksSdkPath)' != '' "/> +</Project> diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks new file mode 100644 index 00000000000..b858cdc4aa2 --- /dev/null +++ b/build/tasks/RepoTasks.tasks @@ -0,0 +1,7 @@ +<Project> + <PropertyGroup> + <_RepoTaskAssembly>$(MSBuildThisFileDirectory)bin\publish\RepoTasks.dll</_RepoTaskAssembly> + </PropertyGroup> + + <UsingTask TaskName="RepoTasks.CalculateBuildGraph" AssemblyFile="$(_RepoTaskAssembly)" /> +</Project> \ No newline at end of file diff --git a/tools/BuildGraph/BuildGraph.csproj b/tools/BuildGraph/BuildGraph.csproj deleted file mode 100644 index f330542012d..00000000000 --- a/tools/BuildGraph/BuildGraph.csproj +++ /dev/null @@ -1,16 +0,0 @@ -<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> \ No newline at end of file diff --git a/tools/BuildGraph/DGMLFormatter.cs b/tools/BuildGraph/DGMLFormatter.cs deleted file mode 100644 index 23ea409cb1c..00000000000 --- a/tools/BuildGraph/DGMLFormatter.cs +++ /dev/null @@ -1,56 +0,0 @@ -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")); - } - } -} \ No newline at end of file diff --git a/tools/BuildGraph/GraphFormatter.cs b/tools/BuildGraph/GraphFormatter.cs deleted file mode 100644 index 878dacd4fe6..00000000000 --- a/tools/BuildGraph/GraphFormatter.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace BuildGraph -{ - public abstract class GraphFormatter - { - public abstract void Format(IList<GraphNode> nodes, string outputPath); - } -} \ No newline at end of file diff --git a/tools/BuildGraph/MSBuildGraphFormatter.cs b/tools/BuildGraph/MSBuildGraphFormatter.cs deleted file mode 100644 index 4867ff217e9..00000000000 --- a/tools/BuildGraph/MSBuildGraphFormatter.cs +++ /dev/null @@ -1,23 +0,0 @@ -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()); - } - } -} \ No newline at end of file diff --git a/tools/BuildGraph/Program.cs b/tools/BuildGraph/Program.cs deleted file mode 100644 index 3271204a7c5..00000000000 --- a/tools/BuildGraph/Program.cs +++ /dev/null @@ -1,84 +0,0 @@ -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 graphRoot = app.Option("--start-at", - "Calculate the build graph starting at the specified repo. (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, graphRoot.Value()); - 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); - } - } -} \ No newline at end of file -- GitLab