/// <summary> /// Returns the path to all referenced xprojs by using the package spec resolver. /// This will return references for ALL TxMs. Filtering based on the nearest TxM /// is needed to apply these results. /// </summary> /// <param name="filePath">Full path to the .xproj file.</param> public static List <string> GetProjectReferences(string filePath) { if (filePath == null) { throw new ArgumentNullException(nameof(filePath)); } var output = new List <string>(); if (filePath.EndsWith(XProjExtension, StringComparison.OrdinalIgnoreCase)) { var dir = Path.GetDirectoryName(filePath); var jsonPath = Path.Combine(dir, PackageSpec.PackageSpecFileName); // Ignore invalid projects with no project.json if (File.Exists(jsonPath)) { var projectName = Path.GetFileNameWithoutExtension(filePath); var spec = JsonPackageSpecReader.GetPackageSpec(projectName, jsonPath); var resolver = new PackageSpecResolver(spec); // combine all dependencies // This will include references for every TxM, these will have to be filtered later var dependencies = new HashSet <LibraryDependency>(); dependencies.UnionWith(spec.Dependencies.Where(d => IsProjectReference(d))); dependencies.UnionWith(spec.TargetFrameworks .SelectMany(f => f.Dependencies) .Where(d => IsProjectReference(d))); // Attempt to look up each dependency foreach (var dependency in dependencies) { PackageSpec childSpec; if (resolver.TryResolvePackageSpec(dependency.Name, out childSpec)) { var fileInfo = new FileInfo(childSpec.FilePath); // dir/ProjectName.xproj var xprojPath = Path.Combine( fileInfo.DirectoryName, fileInfo.Directory.Name + XProjExtension); output.Add(xprojPath); } } } } return(output); }
public async Task<RestoreResult> ExecuteAsync(RestoreRequest request) { if (request.Project.TargetFrameworks.Count == 0) { _log.LogError("The project does not specify any target frameworks!"); return new RestoreResult(success: false, restoreGraphs: Enumerable.Empty<RestoreTargetGraph>()); } var projectLockFilePath = string.IsNullOrEmpty(request.LockFilePath) ? Path.Combine(request.Project.BaseDirectory, LockFileFormat.LockFileName) : request.LockFilePath; _log.LogInformation($"Restoring packages for '{request.Project.FilePath}'"); _log.LogWarning("TODO: Read and use lock file"); // Load repositories var projectResolver = new PackageSpecResolver(request.Project); var nugetRepository = Repository.Factory.GetCoreV3(request.PackagesDirectory); var context = new RemoteWalkContext(); ExternalProjectReference exterenalProjectReference = null; if (request.ExternalProjects.Any()) { exterenalProjectReference = new ExternalProjectReference( request.Project.Name, request.Project.FilePath, request.ExternalProjects.Select(p => p.Name)); } context.ProjectLibraryProviders.Add( new LocalDependencyProvider( new PackageSpecReferenceDependencyProvider(projectResolver, exterenalProjectReference))); if (request.ExternalProjects != null) { context.ProjectLibraryProviders.Add( new LocalDependencyProvider( new ExternalProjectReferenceDependencyProvider(request.ExternalProjects))); } context.LocalLibraryProviders.Add( new SourceRepositoryDependencyProvider(nugetRepository, _log)); foreach (var provider in request.Sources.Select(s => CreateProviderFromSource(s, request.NoCache))) { context.RemoteLibraryProviders.Add(provider); } var remoteWalker = new RemoteDependencyWalker(context); var projectRange = new LibraryRange() { Name = request.Project.Name, VersionRange = new VersionRange(request.Project.Version), TypeConstraint = LibraryTypes.Project }; // Resolve dependency graphs var frameworks = request.Project.TargetFrameworks.Select(f => f.FrameworkName).ToList(); var graphs = new List<RestoreTargetGraph>(); var frameworkTasks = new List<Task<RestoreTargetGraph>>(); foreach (var framework in frameworks) { frameworkTasks.Add(WalkDependencies(projectRange, framework, remoteWalker, context)); } graphs.AddRange(await Task.WhenAll(frameworkTasks)); if (graphs.Any(g => g.InConflict)) { _log.LogError("Failed to resolve conflicts"); return new RestoreResult(success: false, restoreGraphs: graphs); } // Install the runtime-agnostic packages var allInstalledPackages = new HashSet<LibraryIdentity>(); var localRepository = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false); await InstallPackages(graphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency); // Resolve runtime dependencies var runtimeGraphs = new List<RestoreTargetGraph>(); if (request.Project.RuntimeGraph.Runtimes.Count > 0) { var runtimeTasks = new List<Task<RestoreTargetGraph[]>>(); foreach (var graph in graphs) { runtimeTasks.Add(WalkRuntimeDependencies(projectRange, graph, request.Project.RuntimeGraph, remoteWalker, context, localRepository)); } foreach (var runtimeSpecificGraphs in await Task.WhenAll(runtimeTasks)) { runtimeGraphs.AddRange(runtimeSpecificGraphs); } graphs.AddRange(runtimeGraphs); if (runtimeGraphs.Any(g => g.InConflict)) { _log.LogError("Failed to resolve conflicts"); return new RestoreResult(success: false, restoreGraphs: graphs); } // Install runtime-specific packages await InstallPackages(runtimeGraphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency); } else { _log.LogVerbose("Skipping runtime dependency walk, no runtimes defined in project.json"); } // Build the lock file var repository = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false); var lockFile = CreateLockFile(request.Project, graphs, repository); var lockFileFormat = new LockFileFormat(); lockFileFormat.Write(projectLockFilePath, lockFile); // Generate Targets/Props files WriteTargetsAndProps(request.Project, graphs, repository); return new RestoreResult(true, graphs, lockFile); }
/// <summary> /// Create a <see cref="RuntimeHostBuilder"/> for the project in the specified /// <paramref name="projectDirectory"/>, using the default configuration. /// </summary> /// <remarks> /// This method will throw if the project.json file cannot be found in the /// specified folder. If a project.lock.json file is present in the directory /// it will be loaded. /// </remarks> /// <param name="projectDirectory">The directory of the project to host</param> public static RuntimeHostBuilder ForProjectDirectory(string projectDirectory, NuGetFramework runtimeFramework, IServiceProvider services) { if (string.IsNullOrEmpty(projectDirectory)) { throw new ArgumentNullException(nameof(projectDirectory)); } if (runtimeFramework == null) { throw new ArgumentNullException(nameof(runtimeFramework)); } var log = RuntimeLogging.Logger<RuntimeHostBuilder>(); var hostBuilder = new RuntimeHostBuilder(); // Load the Project var projectResolver = new PackageSpecResolver(projectDirectory); PackageSpec packageSpec; if (projectResolver.TryResolvePackageSpec(GetProjectName(projectDirectory), out packageSpec)) { log.LogVerbose($"Loaded project {packageSpec.Name}"); hostBuilder.Project = new Project(packageSpec); } hostBuilder.GlobalSettings = projectResolver.GlobalSettings; // Load the Lock File if present LockFile lockFile; if (TryReadLockFile(projectDirectory, out lockFile)) { log.LogVerbose($"Loaded lock file"); hostBuilder.LockFile = lockFile; } // Set the framework and other components hostBuilder.TargetFramework = runtimeFramework; hostBuilder.Services = services; hostBuilder.PackagePathResolver = new PackagePathResolver( ResolveRepositoryPath(hostBuilder.GlobalSettings), GetCachePaths()); log.LogVerbose("Registering PackageSpecReferenceDependencyProvider"); hostBuilder.DependencyProviders.Add(new PackageSpecReferenceDependencyProvider(projectResolver)); if (hostBuilder.LockFile != null) { log.LogVerbose("Registering LockFileDependencyProvider"); hostBuilder.DependencyProviders.Add(new LockFileDependencyProvider(hostBuilder.LockFile)); } log.LogVerbose("Registering ReferenceAssemblyDependencyProvider"); var referenceResolver = new FrameworkReferenceResolver(); hostBuilder.DependencyProviders.Add(new ReferenceAssemblyDependencyProvider(referenceResolver)); // GAC resolver goes here! :) return hostBuilder; }