-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C#: Restore projects and collect dependencies for projects in the same folder sequentially. #16248
Changes from 4 commits
6daf80c
0124b07
131d0b9
181a063
d62e888
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ internal class DependencyContainer | |
/// <summary> | ||
/// Paths to dependencies required for compilation. | ||
/// </summary> | ||
public List<string> Paths { get; } = new(); | ||
public HashSet<string> Paths { get; } = new(); | ||
|
||
/// <summary> | ||
/// Packages that are used as a part of the required dependencies. | ||
|
@@ -68,4 +68,18 @@ public void AddFramework(string framework) | |
Packages.Add(GetPackageName(p)); | ||
} | ||
} | ||
} | ||
|
||
internal static class DependencyContainerExtensions | ||
{ | ||
/// <summary> | ||
/// Flatten a list of containers into a single container. | ||
/// </summary> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: the parameter name should be plural and then the below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could change this to public static DependencyContainer Flatten(this IEnumerable<DependencyContainer> container, DependencyContainer init) => and then replace the |
||
public static DependencyContainer Flatten(this IEnumerable<DependencyContainer> container) => | ||
container.Aggregate(new DependencyContainer(), (acc, c) => | ||
{ | ||
acc.Paths.UnionWith(c.Paths); | ||
acc.Packages.UnionWith(c.Packages); | ||
return acc; | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -144,11 +144,12 @@ public HashSet<AssemblyLookupLocation> Restore() | |
logger.LogError($"Failed to restore Nuget packages with nuget.exe: {exc.Message}"); | ||
} | ||
|
||
var restoredProjects = RestoreSolutions(out var assets1); | ||
var restoredProjects = RestoreSolutions(out var container); | ||
var projects = fileProvider.Projects.Except(restoredProjects); | ||
RestoreProjects(projects, out var assets2); | ||
RestoreProjects(projects, out var containers); | ||
|
||
var dependencies = Assets.GetCompilationDependencies(logger, assets1.Union(assets2)); | ||
containers.Add(container); | ||
var dependencies = containers.Flatten(); | ||
|
||
var paths = dependencies | ||
.Paths | ||
|
@@ -198,14 +199,14 @@ private List<string> GetReachableFallbackNugetFeeds() | |
/// As opposed to RestoreProjects this is not run in parallel using PLINQ | ||
/// as `dotnet restore` on a solution already uses multiple threads for restoring | ||
/// the projects (this can be disabled with the `--disable-parallel` flag). | ||
/// Populates assets with the relative paths to the assets files generated by the restore. | ||
/// Populates dependencies with the relevant dependencies from the assets files generated by the restore. | ||
/// Returns a list of projects that are up to date with respect to restore. | ||
/// </summary> | ||
private IEnumerable<string> RestoreSolutions(out IEnumerable<string> assets) | ||
private IEnumerable<string> RestoreSolutions(out DependencyContainer dependencies) | ||
{ | ||
var successCount = 0; | ||
var nugetSourceFailures = 0; | ||
var assetFiles = new List<string>(); | ||
var assets = new Assets(logger); | ||
var projects = fileProvider.Solutions.SelectMany(solution => | ||
{ | ||
logger.LogInfo($"Restoring solution {solution}..."); | ||
|
@@ -218,10 +219,10 @@ private IEnumerable<string> RestoreSolutions(out IEnumerable<string> assets) | |
{ | ||
nugetSourceFailures++; | ||
} | ||
assetFiles.AddRange(res.AssetsFilePaths); | ||
assets.AddDependenciesRange(res.AssetsFilePaths); | ||
return res.RestoredProjects; | ||
}).ToList(); | ||
assets = assetFiles; | ||
dependencies = assets.Dependencies; | ||
compilationInfoContainer.CompilationInfos.Add(("Successfully restored solution files", successCount.ToString())); | ||
compilationInfoContainer.CompilationInfos.Add(("Failed solution restore with package source error", nugetSourceFailures.ToString())); | ||
compilationInfoContainer.CompilationInfos.Add(("Restored projects through solution files", projects.Count.ToString())); | ||
|
@@ -231,33 +232,42 @@ private IEnumerable<string> RestoreSolutions(out IEnumerable<string> assets) | |
/// <summary> | ||
/// Executes `dotnet restore` on all projects in projects. | ||
/// This is done in parallel for performance reasons. | ||
/// Populates assets with the relative paths to the assets files generated by the restore. | ||
/// Populates dependencies with the relative paths to the assets files generated by the restore. | ||
/// </summary> | ||
/// <param name="projects">A list of paths to project files.</param> | ||
private void RestoreProjects(IEnumerable<string> projects, out IEnumerable<string> assets) | ||
private void RestoreProjects(IEnumerable<string> projects, out List<DependencyContainer> dependencies) | ||
{ | ||
var successCount = 0; | ||
var nugetSourceFailures = 0; | ||
var assetFiles = new List<string>(); | ||
List<DependencyContainer> collectedDependencies = []; | ||
var sync = new object(); | ||
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = DependencyManager.Threads }, project => | ||
var projectGroups = projects.GroupBy(Path.GetDirectoryName); | ||
Parallel.ForEach(projectGroups, new ParallelOptions { MaxDegreeOfParallelism = DependencyManager.Threads }, projectGroup => | ||
{ | ||
logger.LogInfo($"Restoring project {project}..."); | ||
var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true)); | ||
lock (sync) | ||
var assets = new Assets(logger); | ||
foreach (var project in projectGroup) | ||
{ | ||
if (res.Success) | ||
{ | ||
successCount++; | ||
} | ||
if (res.HasNugetPackageSourceError) | ||
logger.LogInfo($"Restoring project {project}..."); | ||
var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true)); | ||
assets.AddDependenciesRange(res.AssetsFilePaths); | ||
lock (sync) | ||
{ | ||
nugetSourceFailures++; | ||
if (res.Success) | ||
{ | ||
successCount++; | ||
} | ||
if (res.HasNugetPackageSourceError) | ||
{ | ||
nugetSourceFailures++; | ||
} | ||
} | ||
assetFiles.AddRange(res.AssetsFilePaths); | ||
} | ||
lock (sync) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're using the |
||
{ | ||
collectedDependencies.Add(assets.Dependencies); | ||
} | ||
}); | ||
assets = assetFiles; | ||
dependencies = collectedDependencies; | ||
compilationInfoContainer.CompilationInfos.Add(("Successfully restored project files", successCount.ToString())); | ||
compilationInfoContainer.CompilationInfos.Add(("Failed project restore with package source error", nugetSourceFailures.ToString())); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We're mixing
asset
andassets
file in comments. I think it should beassets
.