private async Task <GraphItem> FindLibraryEntry(RestoreContext context, LibraryRange libraryRange) { _report.WriteLine(string.Format("Attempting to resolve dependency {0} {1}", libraryRange.Name.Bold(), libraryRange.VersionRange)); Task <WalkProviderMatch> task; lock (context.MatchCache) { if (!context.MatchCache.TryGetValue(libraryRange, out task)) { task = FindLibraryMatch(context, libraryRange); context.MatchCache[libraryRange] = task; } } var match = await task; if (match == null) { return(null); } var dependencies = await match.Provider.GetDependencies(match, context.FrameworkName); return(new GraphItem { Match = match, Dependencies = dependencies, }); }
private async Task <WalkProviderMatch> FindLibraryByVersion(RestoreContext context, LibraryRange libraryRange, IEnumerable <IWalkProvider> providers) { if (libraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { // Don't optimize the non http path for floating versions or we'll miss things return(await FindLibrary(libraryRange, providers, provider => provider.FindLibrary(libraryRange, context.FrameworkName))); } // Try the non http sources first var nonHttpMatch = await FindLibrary(libraryRange, providers.Where(p => !p.IsHttp), provider => provider.FindLibrary(libraryRange, context.FrameworkName)); // If we found an exact match then use it if (nonHttpMatch != null && nonHttpMatch.Library.Version.Equals(libraryRange.VersionRange.MinVersion)) { return(nonHttpMatch); } // Otherwise try the http sources var httpMatch = await FindLibrary(libraryRange, providers.Where(p => p.IsHttp), provider => provider.FindLibrary(libraryRange, context.FrameworkName)); // Pick the best match of the 2 if (VersionUtility.ShouldUseConsidering( nonHttpMatch?.Library?.Version, httpMatch?.Library.Version, libraryRange.VersionRange)) { return(httpMatch); } return(nonHttpMatch); }
public async Task <WalkProviderMatch> FindLibraryByName(RestoreContext context, string name, IEnumerable <IWalkProvider> providers) { foreach (var provider in providers) { var match = await provider.FindLibraryByName(name, context.FrameworkName); if (match != null) { return(match); } } return(null); }
public Task <GraphItem> FindLibraryCached(RestoreContext context, Library library) { lock (context.FindLibraryCache) { Task <GraphItem> task; if (!context.FindLibraryCache.TryGetValue(library, out task)) { task = FindLibraryEntry(context, library); context.FindLibraryCache[library] = task; } return(task); } }
public async Task <GraphNode> CreateGraphNode(RestoreContext context, Library library, Func <string, bool> predicate) { var sw = new Stopwatch(); sw.Start(); var node = new GraphNode { Library = library, Item = await FindLibraryCached(context, library), }; if (node.Item != null) { if (node.Library != null && node.Library.Version != null && node.Library.Version.IsSnapshot) { node.Library = node.Item.Match.Library; lock (context.FindLibraryCache) { if (!context.FindLibraryCache.ContainsKey(node.Library)) { context.FindLibraryCache[node.Library] = Task.FromResult(node.Item); } } } var tasks = new List <Task <GraphNode> >(); var dependencies = node.Item.Dependencies ?? Enumerable.Empty <LibraryDependency>(); foreach (var dependency in dependencies) { if (predicate(dependency.Name)) { tasks.Add(CreateGraphNode(context, dependency.Library, ChainPredicate(predicate, node.Item, dependency))); } } while (tasks.Any()) { var task = await Task.WhenAny(tasks); tasks.Remove(task); var dependency = await task; node.Dependencies.Add(dependency); } } return(node); }
private async Task <WalkProviderMatch> FindProjectMatch(RestoreContext context, string name) { var libraryRange = new LibraryRange(name, frameworkReference: false); foreach (var provider in context.ProjectLibraryProviders) { var match = await provider.FindLibrary(libraryRange, context.FrameworkName, includeUnlisted : false); if (match != null) { return(match); } } return(null); }
public async Task<GraphNode> CreateGraphNode(RestoreContext context, LibraryRange libraryRange, Func<string, bool> predicate) { var sw = new Stopwatch(); sw.Start(); var node = new GraphNode { LibraryRange = libraryRange, Item = await FindLibraryCached(context, libraryRange), }; if (node.Item != null) { if (node.LibraryRange.VersionRange != null && node.LibraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { lock (context.FindLibraryCache) { if (!context.FindLibraryCache.ContainsKey(node.LibraryRange)) { context.FindLibraryCache[node.LibraryRange] = Task.FromResult(node.Item); } } } var tasks = new List<Task<GraphNode>>(); var dependencies = node.Item.Dependencies ?? Enumerable.Empty<LibraryDependency>(); foreach (var dependency in dependencies) { if (predicate(dependency.Name)) { tasks.Add(CreateGraphNode(context, dependency.LibraryRange, ChainPredicate(predicate, node.Item, dependency))); } } while (tasks.Any()) { var task = await Task.WhenAny(tasks); tasks.Remove(task); var dependency = await task; node.Dependencies.Add(dependency); } } return node; }
private async Task <WalkProviderMatch> FindProjectMatch(RestoreContext context, string name) { var libraryRange = new LibraryRange { Name = name }; foreach (var provider in context.ProjectLibraryProviders) { var match = await provider.FindLibrary(libraryRange, context.FrameworkName); if (match != null) { return(match); } } return(null); }
private async Task <GraphItem> FindLibraryEntry(RestoreContext context, LibraryRange libraryRange) { _report.WriteLine(string.Format("Attempting to resolve dependency {0} {1}", libraryRange.Name.Bold(), libraryRange.VersionRange)); var match = await FindLibraryMatch(context, libraryRange); if (match == null) { return(null); } var dependencies = await match.Provider.GetDependencies(match, context.FrameworkName); return(new GraphItem { Match = match, Dependencies = dependencies, }); }
public async Task <GraphItem> FindLibraryEntry(RestoreContext context, Library library) { _report.WriteLine(string.Format("Attempting to resolve dependency {0} >= {1}", library.Name.Bold(), library.Version)); var match = await FindLibraryMatch(context, library); if (match == null) { // Report.WriteLine(string.Format("Unable to find '{1}' of package '{0}'", library.Name, library.Version)); return(null); } var dependencies = await match.Provider.GetDependencies(match, context.FrameworkName); //Report.WriteLine(string.Format("Resolved {0} {1}", match.Library.Name, match.Library.Version)); return(new GraphItem { Match = match, Dependencies = dependencies, }); }
private async Task <WalkProviderMatch> FindLibraryByVersion(RestoreContext context, Library library, IEnumerable <IWalkProvider> providers) { List <Task <WalkProviderMatch> > tasks = new List <Task <WalkProviderMatch> >(); foreach (var provider in providers) { tasks.Add(provider.FindLibraryByVersion(library, context.FrameworkName)); } var matches = await Task.WhenAll(tasks); WalkProviderMatch bestMatch = null; foreach (var match in matches) { if (VersionUtility.ShouldUseConsidering( current: (bestMatch == null || bestMatch.Library == null) ? null : bestMatch.Library.Version, considering: (match == null || match.Library == null) ? null : match.Library.Version, ideal: library.Version)) { bestMatch = match; } } return(bestMatch); }
public async Task <WalkProviderMatch> FindLibraryMatch(RestoreContext context, Library library) { var projectMatch = await FindLibraryByName(context, library.Name, context.ProjectLibraryProviders); if (projectMatch != null) { return(projectMatch); } if (library.Version == null) { return(null); } if (library.IsGacOrFrameworkReference) { return(null); } if (library.Version.IsSnapshot) { var remoteMatch = await FindLibraryBySnapshot(context, library, context.RemoteLibraryProviders); if (remoteMatch == null) { var localMatch = await FindLibraryBySnapshot(context, library, context.LocalLibraryProviders); return(localMatch); } else { var localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(remoteMatch.Library.Version)) { return(localMatch); } return(remoteMatch); } } else { var localMatch = await FindLibraryByVersion(context, library, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(library.Version)) { return(localMatch); } var remoteMatch = await FindLibraryByVersion(context, library, context.RemoteLibraryProviders); if (remoteMatch != null && localMatch == null) { localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); } if (localMatch != null && remoteMatch != null) { if (VersionUtility.ShouldUseConsidering( current: localMatch.Library.Version, considering: remoteMatch.Library.Version, ideal: library.Version)) { return(remoteMatch); } else { return(localMatch); } } return(localMatch ?? remoteMatch); } }
private async Task <bool> RestoreForProject(LocalPackageRepository localRepository, string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); Project project; if (!Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } Func <string, string> getVariable = key => { return(null); }; ScriptExecutor.Execute(project, "prerestore", getVariable); var projectDirectory = project.ProjectDirectory; var restoreOperations = new RestoreOperations { Report = Reports.Information }; var projectProviders = new List <IWalkProvider>(); var localProviders = new List <IWalkProvider>(); var remoteProviders = new List <IWalkProvider>(); var contexts = new List <RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( new ProjectResolver( projectDirectory, rootDirectory)))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory, new EmptyFrameworkResolver()))); var allSources = SourceProvider.LoadPackageSources(); var enabledSources = Sources.Any() ? Enumerable.Empty <PackageSource>() : allSources.Where(s => s.IsEnabled); var addedSources = Sources.Concat(FallbackSources).Select( value => allSources.FirstOrDefault(source => CorrectName(value, source)) ?? new PackageSource(value)); var effectiveSources = enabledSources.Concat(addedSources).Distinct().ToList(); foreach (var source in effectiveSources) { if (new Uri(source.Source).IsFile) { remoteProviders.Add( new RemoteWalkProvider( new PackageFolder( source.Source, Reports.Verbose))); } else { remoteProviders.Add( new RemoteWalkProvider( new PackageFeed( source.Source, source.UserName, source.Password, NoCache, Reports.Verbose))); } } foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.TargetFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } var tasks = new List <Task <GraphNode> >(); foreach (var context in contexts) { tasks.Add(restoreOperations.CreateGraphNode(context, new Library { Name = project.Name, Version = project.Version }, _ => true)); } var graphs = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List <GraphItem>(); var missingItems = new List <Library>(); ForEach(graphs, node => { if (node == null || node.Library == null) { return; } if (node.Item == null || node.Item.Match == null) { if (node.Library.Version != null && !missingItems.Contains(node.Library)) { missingItems.Add(node.Library); Reports.Information.WriteLine(string.Format("Unable to locate {0} >= {1}", node.Library.Name.Red().Bold(), node.Library.Version)); success = false; } return; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isAdded = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isAdded && isRemote) { installItems.Add(node.Item); } }); var dependencies = new Dictionary <Library, string>(); // If there is a global.json file specified, we should do SHA value verification var globalJsonFileSpecified = !string.IsNullOrEmpty(GlobalJsonFile); JToken dependenciesNode = null; if (globalJsonFileSpecified) { var globalJson = JObject.Parse(File.ReadAllText(GlobalJsonFile)); dependenciesNode = globalJson["dependencies"]; if (dependenciesNode != null) { dependencies = dependenciesNode .OfType <JProperty>() .ToDictionary(d => new Library() { Name = d.Name, Version = SemanticVersion.Parse(d.Value.Value <string>("version")) }, d => d.Value.Value <string>("sha")); } } var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); using (var sha512 = SHA512.Create()) { foreach (var item in installItems) { var library = item.Match.Library; var memStream = new MemoryStream(); await item.Match.Provider.CopyToAsync(item.Match, memStream); memStream.Seek(0, SeekOrigin.Begin); var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(memStream)); string expectedSHA; if (dependencies.TryGetValue(library, out expectedSHA)) { if (!string.Equals(expectedSHA, nupkgSHA, StringComparison.Ordinal)) { Reports.Information.WriteLine( string.Format("SHA of downloaded package {0} doesn't match expected value.".Red().Bold(), library.ToString())); success = false; continue; } } else { // Report warnings only when given global.json contains "dependencies" if (globalJsonFileSpecified && dependenciesNode != null) { Reports.Information.WriteLine( string.Format("Expected SHA of package {0} doesn't exist in given global.json file.".Yellow().Bold(), library.ToString())); } } Reports.Information.WriteLine(string.Format("Installing {0} {1}", library.Name.Bold(), library.Version)); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var hashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock => { // If this is the first process trying to install the target nupkg, go ahead // After this process successfully installs the package, all other processes // waiting on this lock don't need to install it again if (createdNewLock) { Directory.CreateDirectory(targetPath); using (var stream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) { await item.Match.Provider.CopyToAsync(item.Match, stream); stream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, stream); } File.WriteAllText(hashPath, nupkgSHA); } return(0); }); } } ScriptExecutor.Execute(project, "postrestore", getVariable); ScriptExecutor.Execute(project, "prepare", getVariable); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); // Print the dependency graph if (success) { var graphNum = contexts.Count; for (int i = 0; i < graphNum; i++) { PrintDependencyGraph(graphs[i], contexts[i].FrameworkName); } } return(success); }
private async Task<WalkProviderMatch> FindProjectMatch(RestoreContext context, string name) { var libraryRange = new LibraryRange(name, frameworkReference: false); foreach (var provider in context.ProjectLibraryProviders) { var match = await provider.FindLibrary(libraryRange, context.FrameworkName, includeUnlisted: false); if (match != null) { return match; } } return null; }
public Task<GraphItem> FindLibraryCached(RestoreContext context, LibraryRange libraryRange) { lock (context.FindLibraryCache) { Task<GraphItem> task; if (!context.FindLibraryCache.TryGetValue(libraryRange, out task)) { task = FindLibraryEntry(context, libraryRange); context.FindLibraryCache[libraryRange] = task; } return task; } }
private async Task <bool> RestoreForProject(string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); var projectFolder = Path.GetDirectoryName(projectJsonPath); var projectLockFilePath = Path.Combine(projectFolder, LockFileFormat.LockFileName); Runtime.Project project; if (!Runtime.Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } var lockFile = await ReadLockFile(projectLockFilePath); var useLockFile = false; if (Lock == false && Unlock == false && lockFile != null && lockFile.Islocked) { useLockFile = true; } if (useLockFile && !lockFile.IsValidForProject(project)) { // Exhibit the same behavior as if it has been run with "dnu restore --lock" Reports.Information.WriteLine("Updating the invalid lock file with {0}", "dnu restore --lock".Yellow().Bold()); useLockFile = false; Lock = true; } Func <string, string> getVariable = key => { return(null); }; if (!ScriptExecutor.Execute(project, "prerestore", getVariable)) { ErrorMessages.GetOrAdd("prerestore", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } var projectDirectory = project.ProjectDirectory; var projectResolver = new ProjectResolver(projectDirectory, rootDirectory); var packageRepository = new PackageRepository(packagesDirectory); var restoreOperations = new RestoreOperations(Reports.Verbose); var projectProviders = new List <IWalkProvider>(); var localProviders = new List <IWalkProvider>(); var remoteProviders = new List <IWalkProvider>(); var contexts = new List <RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( projectResolver))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver(packageRepository))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources( SourceProvider, FeedOptions.Sources, FeedOptions.FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); var tasks = new List <Task <GraphNode> >(); if (useLockFile) { Reports.Information.WriteLine(string.Format("Following lock file {0}", projectLockFilePath.White().Bold())); var context = new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); foreach (var lockFileLibrary in lockFile.Libraries) { var projectLibrary = new LibraryRange { Name = lockFileLibrary.Name, VersionRange = new SemanticVersionRange { MinVersion = lockFileLibrary.Version, MaxVersion = lockFileLibrary.Version, IsMaxInclusive = true, VersionFloatBehavior = SemanticVersionFloatBehavior.None, } }; tasks.Add(restoreOperations.CreateGraphNode(context, projectLibrary, _ => false)); } } else { foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } foreach (var context in contexts) { var projectLibrary = new LibraryRange { Name = project.Name, VersionRange = new SemanticVersionRange(project.Version) }; tasks.Add(restoreOperations.CreateGraphNode(context, projectLibrary, _ => true)); } } var graphs = await Task.WhenAll(tasks); foreach (var graph in graphs) { Reduce(graph); } if (!useLockFile) { var runtimeFormatter = new RuntimeFileFormatter(); var projectRuntimeFile = runtimeFormatter.ReadRuntimeFile(projectJsonPath); if (projectRuntimeFile.Runtimes.Any()) { var runtimeTasks = new List <Task <GraphNode> >(); foreach (var pair in contexts.Zip(graphs, (context, graph) => new { context, graph })) { var runtimeFileTasks = new List <Task <RuntimeFile> >(); ForEach(pair.graph, node => { var match = node?.Item?.Match; if (match == null) { return; } runtimeFileTasks.Add(match.Provider.GetRuntimes(node.Item.Match, pair.context.FrameworkName)); }); var libraryRuntimeFiles = await Task.WhenAll(runtimeFileTasks); var runtimeFiles = new List <RuntimeFile> { projectRuntimeFile }; runtimeFiles.AddRange(libraryRuntimeFiles.Where(file => file != null)); foreach (var runtimeName in projectRuntimeFile.Runtimes.Keys) { var runtimeSpecs = new List <RuntimeSpec>(); FindRuntimeSpecs( runtimeName, runtimeFiles, runtimeSpecs, _ => false); var runtimeContext = new RestoreContext { FrameworkName = pair.context.FrameworkName, ProjectLibraryProviders = pair.context.ProjectLibraryProviders, LocalLibraryProviders = pair.context.LocalLibraryProviders, RemoteLibraryProviders = pair.context.RemoteLibraryProviders, RuntimeName = runtimeName, RuntimeSpecs = runtimeSpecs }; var projectLibrary = new LibraryRange { Name = project.Name, VersionRange = new SemanticVersionRange(project.Version) }; Reports.Information.WriteLine(string.Format("Graph for {0} on {1}", runtimeContext.FrameworkName, runtimeContext.RuntimeName)); runtimeTasks.Add(restoreOperations.CreateGraphNode(runtimeContext, projectLibrary, _ => true)); } } var runtimeGraphs = await Task.WhenAll(runtimeTasks); foreach (var runtimeGraph in runtimeGraphs) { Reduce(runtimeGraph); } graphs = graphs.Concat(runtimeGraphs).ToArray(); } } var graphItems = new List <GraphItem>(); var installItems = new List <GraphItem>(); var missingItems = new HashSet <LibraryRange>(); ForEach(graphs, node => { if (node == null || node.LibraryRange == null || node.Disposition == GraphNode.DispositionType.Rejected) { return; } if (node.Item == null || node.Item.Match == null) { if (!node.LibraryRange.IsGacOrFrameworkReference && node.LibraryRange.VersionRange != null && missingItems.Add(node.LibraryRange)) { var errorMessage = string.Format("Unable to locate {0} {1}", node.LibraryRange.Name.Red().Bold(), node.LibraryRange.VersionRange); ErrorMessages.GetOrAdd(projectJsonPath, _ => new List <string>()).Add(errorMessage); Reports.Error.WriteLine(errorMessage); success = false; } return; } if (!string.Equals(node.Item.Match.Library.Name, node.LibraryRange.Name, StringComparison.Ordinal)) { // Fix casing of the library name to be installed node.Item.Match.Library.Name = node.LibraryRange.Name; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isInstallItem = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isInstallItem && isRemote) { installItems.Add(node.Item); } var isGraphItem = graphItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isGraphItem) { graphItems.Add(node.Item); } }); await InstallPackages(installItems, packagesDirectory, packageFilter : (library, nupkgSHA) => true); if (!useLockFile) { Reports.Information.WriteLine(string.Format("Writing lock file {0}", projectLockFilePath.White().Bold())); // Collect target frameworks var frameworks = new HashSet <FrameworkName>(); foreach (var item in graphItems) { Runtime.Project dependencyProject; if (projectProviders.Contains(item.Match.Provider) && projectResolver.TryResolveProject(item.Match.Library.Name, out dependencyProject)) { frameworks.AddRange(dependencyProject.GetTargetFrameworks().Select(t => t.FrameworkName)); } } WriteLockFile(projectLockFilePath, project, graphItems, new PackageRepository(packagesDirectory), frameworks); } if (!ScriptExecutor.Execute(project, "postrestore", getVariable)) { ErrorMessages.GetOrAdd("postrestore", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } if (!ScriptExecutor.Execute(project, "prepare", getVariable)) { ErrorMessages.GetOrAdd("prepare", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); return(success); }
private async Task <bool> RestoreFromGlobalJson(string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", Path.GetFullPath(GlobalJsonFile).Bold())); var sw = new Stopwatch(); sw.Start(); var restoreOperations = new RestoreOperations(Reports.Information); var localProviders = new List <IWalkProvider>(); var remoteProviders = new List <IWalkProvider>(); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources(SourceProvider, Sources, FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); var context = new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = new List <IWalkProvider>(), LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; var dependencies = new Dictionary <Library, string>(); JToken dependenciesNode = null; var globalJson = JObject.Parse(File.ReadAllText(GlobalJsonFile)); dependenciesNode = globalJson["dependencies"]; if (dependenciesNode != null) { dependencies = dependenciesNode .OfType <JProperty>() .ToDictionary(d => new Library() { Name = d.Name, Version = SemanticVersion.Parse(d.Value.Value <string>("version")) }, d => d.Value.Value <string>("sha")); } var libsToRestore = new List <Library>(dependencies.Keys); var tasks = new List <Task <GraphItem> >(); foreach (var lib in libsToRestore) { tasks.Add(restoreOperations.FindLibraryCached(context, new Library { Name = lib.Name, Version = lib.Version })); } var resolvedItems = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List <GraphItem>(); var missingItems = new List <Library>(); for (int i = 0; i < resolvedItems.Length; i++) { var item = resolvedItems[i]; var lib = libsToRestore[i]; if (item == null || item.Match == null || item.Match.Library.Version != lib.Version) { missingItems.Add(lib); Reports.Error.WriteLine(string.Format("Unable to locate {0} {1}", lib.Name.Red().Bold(), lib.Version)); success = false; continue; } var isRemote = remoteProviders.Contains(item.Match.Provider); var isAdded = installItems.Any(x => x.Match.Library == item.Match.Library); if (!isAdded && isRemote) { installItems.Add(item); } } await InstallPackages(installItems, packagesDirectory, packageFilter : (library, nupkgSHA) => { string expectedSHA = dependencies[library]; if (!string.Equals(expectedSHA, nupkgSHA, StringComparison.Ordinal)) { Reports.Error.WriteLine( string.Format("SHA of downloaded package {0} doesn't match expected value.".Red().Bold(), library.ToString())); success = false; return(false); } return(true); }); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); return(success); }
private async Task<WalkProviderMatch> FindLibraryByVersion(RestoreContext context, LibraryRange libraryRange, IEnumerable<IWalkProvider> providers) { if (libraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { // Don't optimize the non http path for floating versions or we'll miss things return await FindLibrary(libraryRange, providers, provider => provider.FindLibrary(libraryRange, context.FrameworkName)); } // Try the non http sources first var nonHttpMatch = await FindLibrary(libraryRange, providers.Where(p => !p.IsHttp), provider => provider.FindLibrary(libraryRange, context.FrameworkName)); // If we found an exact match then use it if (nonHttpMatch != null && nonHttpMatch.Library.Version.Equals(libraryRange.VersionRange.MinVersion)) { return nonHttpMatch; } // Otherwise try the http sources var httpMatch = await FindLibrary(libraryRange, providers.Where(p => p.IsHttp), provider => provider.FindLibrary(libraryRange, context.FrameworkName)); // Pick the best match of the 2 if (VersionUtility.ShouldUseConsidering( nonHttpMatch?.Library?.Version, httpMatch?.Library.Version, libraryRange.VersionRange)) { return httpMatch; } return nonHttpMatch; }
private async Task<WalkProviderMatch> FindLibraryMatch(RestoreContext context, LibraryRange libraryRange) { var projectMatch = await FindProjectMatch(context, libraryRange.Name); if (projectMatch != null) { return projectMatch; } if (libraryRange.VersionRange == null) { return null; } if (libraryRange.IsGacOrFrameworkReference) { return null; } if (libraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { // For snapshot dependencies, get the version remotely first. var remoteMatch = await FindLibraryByVersion(context, libraryRange, context.RemoteLibraryProviders); if (remoteMatch == null) { // If there was nothing remotely, use the local match (if any) var localMatch = await FindLibraryByVersion(context, libraryRange, context.LocalLibraryProviders); return localMatch; } else { // Try to see if the specific version found on the remote exists locally. This avoids any unnecessary // remote access incase we already have it in the cache/local packages folder. var localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(remoteMatch.Library.Version)) { // If we have a local match, and it matches the version *exactly* then use it. return localMatch; } // We found something locally, but it wasn't an exact match // for the resolved remote match. return remoteMatch; } } else { // Check for the specific version locally. var localMatch = await FindLibraryByVersion(context, libraryRange, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(libraryRange.VersionRange.MinVersion)) { // We have an exact match so use it. return localMatch; } // Either we found a local match but it wasn't the exact version, or // we didn't find a local match. var remoteMatch = await FindLibraryByVersion(context, libraryRange, context.RemoteLibraryProviders); if (remoteMatch != null && localMatch == null) { // There wasn't any local match for the specified version but there was a remote match. // See if that version exists locally. localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); } if (localMatch != null && remoteMatch != null) { // We found a match locally and remotely, so pick the better version // in relation to the specified version. if (VersionUtility.ShouldUseConsidering( current: localMatch.Library.Version, considering: remoteMatch.Library.Version, ideal: libraryRange.VersionRange)) { return remoteMatch; } else { return localMatch; } } // Prefer local over remote generally. return localMatch ?? remoteMatch; } }
private async Task<WalkProviderMatch> FindProjectMatch(RestoreContext context, string name) { var libraryRange = new LibraryRange { Name = name }; foreach (var provider in context.ProjectLibraryProviders) { var match = await provider.FindLibrary(libraryRange, context.FrameworkName); if (match != null) { return match; } } return null; }
private async Task <TargetContext> CreateGraphNode(RestoreOperations restoreOperations, RestoreContext context, LibraryRange libraryRange, Func <object, bool> predicate) { var node = await restoreOperations.CreateGraphNode(context, libraryRange, predicate); return(new TargetContext { RestoreContext = context, Root = node }); }
private async Task<GraphItem> FindLibraryEntry(RestoreContext context, LibraryRange libraryRange) { _report.WriteLine(string.Format("Attempting to resolve dependency {0} {1}", libraryRange.Name.Bold(), libraryRange.VersionRange)); var match = await FindLibraryMatch(context, libraryRange); if (match == null) { return null; } var dependencies = await match.Provider.GetDependencies(match, context.FrameworkName); return new GraphItem { Match = match, Dependencies = dependencies, }; }
private async Task<bool> RestoreFromGlobalJson(string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", Path.GetFullPath(GlobalJsonFile).Bold())); var sw = new Stopwatch(); sw.Start(); var restoreOperations = new RestoreOperations(Reports.Information); var localProviders = new List<IWalkProvider>(); var remoteProviders = new List<IWalkProvider>(); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources(SourceProvider, Sources, FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); var context = new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = new List<IWalkProvider>(), LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; GlobalSettings globalSettings; GlobalSettings.TryGetGlobalSettings(GlobalJsonFile, out globalSettings); var libsToRestore = globalSettings.PackageHashes.Keys.ToList(); var tasks = new List<Task<GraphItem>>(); foreach (var library in libsToRestore) { tasks.Add(restoreOperations.FindLibraryCached(context, library)); } var resolvedItems = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List<GraphItem>(); var missingItems = new List<Library>(); for (int i = 0; i < resolvedItems.Length; i++) { var item = resolvedItems[i]; var library = libsToRestore[i]; if (item == null || item.Match == null || item.Match.Library.Version != library.Version) { missingItems.Add(library); Reports.Error.WriteLine(string.Format("Unable to locate {0} {1}", library.Name.Red().Bold(), library.Version)); success = false; continue; } var isRemote = remoteProviders.Contains(item.Match.Provider); var isAdded = installItems.Any(x => x.Match.Library == item.Match.Library); if (!isAdded && isRemote) { installItems.Add(item); } } await InstallPackages(installItems, packagesDirectory, packageFilter: (library, nupkgSHA) => { string expectedSHA = globalSettings.PackageHashes[library]; if (!string.Equals(expectedSHA, nupkgSHA, StringComparison.Ordinal)) { Reports.Error.WriteLine( string.Format("SHA of downloaded package {0} doesn't match expected value.".Red().Bold(), library.ToString())); success = false; return false; } return true; }); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); return success; }
private async Task<GraphItem> FindLibraryEntry(RestoreContext context, LibraryRange libraryRange) { _report.WriteLine(string.Format("Attempting to resolve dependency {0} {1}", libraryRange.Name.Bold(), libraryRange.VersionRange)); Task<WalkProviderMatch> task; lock (context.MatchCache) { if (!context.MatchCache.TryGetValue(libraryRange, out task)) { task = FindLibraryMatch(context, libraryRange); context.MatchCache[libraryRange] = task; } } var match = await task; if (match == null) { return null; } var dependencies = await match.Provider.GetDependencies(match, context.FrameworkName); return new GraphItem { Match = match, Dependencies = dependencies, }; }
public async Task<GraphNode> CreateGraphNode(RestoreContext context, LibraryRange libraryRange, Func<string, bool> predicate) { var sw = new Stopwatch(); sw.Start(); var node = new GraphNode { LibraryRange = libraryRange, Item = await FindLibraryCached(context, libraryRange), }; if (node.Item != null) { if (node.LibraryRange.VersionRange != null && node.LibraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { lock (context.GraphItemCache) { if (!context.GraphItemCache.ContainsKey(node.LibraryRange)) { context.GraphItemCache[node.LibraryRange] = Task.FromResult(node.Item); } } } var tasks = new List<Task<GraphNode>>(); var dependencies = node.Item.Dependencies ?? Enumerable.Empty<LibraryDependency>(); foreach (var dependency in dependencies) { if (predicate(dependency.Name)) { tasks.Add(CreateGraphNode(context, dependency.LibraryRange, ChainPredicate(predicate, node.Item, dependency))); if (context.RuntimeSpecs != null) { foreach (var runtimeSpec in context.RuntimeSpecs) { DependencySpec dependencyMapping; if (runtimeSpec.Dependencies.TryGetValue(dependency.Name, out dependencyMapping)) { foreach (var dependencyImplementation in dependencyMapping.Implementations.Values) { tasks.Add(CreateGraphNode( context, new LibraryRange(dependencyImplementation.Name, frameworkReference: false) { VersionRange = VersionUtility.ParseVersionRange(dependencyImplementation.Version) }, ChainPredicate(predicate, node.Item, dependency))); } break; } } } } } while (tasks.Any()) { var task = await Task.WhenAny(tasks); tasks.Remove(task); var dependency = await task; node.Dependencies.Add(dependency); } } return node; }
private async Task<bool> RestoreForProject(LocalPackageRepository localRepository, string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); Project project; if (!Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } Func<string, string> getVariable = key => { return null; }; ScriptExecutor.Execute(project, "prerestore", getVariable); var projectDirectory = project.ProjectDirectory; var restoreOperations = new RestoreOperations { Report = Reports.Information }; var projectProviders = new List<IWalkProvider>(); var localProviders = new List<IWalkProvider>(); var remoteProviders = new List<IWalkProvider>(); var contexts = new List<RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( new ProjectResolver( projectDirectory, rootDirectory)))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory, new EmptyFrameworkResolver()))); var allSources = SourceProvider.LoadPackageSources(); var enabledSources = Sources.Any() ? Enumerable.Empty<PackageSource>() : allSources.Where(s => s.IsEnabled); var addedSources = Sources.Concat(FallbackSources).Select( value => allSources.FirstOrDefault(source => CorrectName(value, source)) ?? new PackageSource(value)); var effectiveSources = enabledSources.Concat(addedSources).Distinct().ToList(); foreach (var source in effectiveSources) { if (new Uri(source.Source).IsFile) { remoteProviders.Add( new RemoteWalkProvider( new PackageFolder( source.Source, Reports.Verbose))); } else { remoteProviders.Add( new RemoteWalkProvider( new PackageFeed( source.Source, source.UserName, source.Password, NoCache, Reports.Verbose))); } } foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.TargetFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } var tasks = new List<Task<GraphNode>>(); foreach (var context in contexts) { tasks.Add(restoreOperations.CreateGraphNode(context, new Library { Name = project.Name, Version = project.Version }, _ => true)); } var graphs = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List<GraphItem>(); var missingItems = new List<Library>(); ForEach(graphs, node => { if (node == null || node.Library == null) { return; } if (node.Item == null || node.Item.Match == null) { if (node.Library.Version != null && !missingItems.Contains(node.Library)) { missingItems.Add(node.Library); Reports.Information.WriteLine(string.Format("Unable to locate {0} >= {1}", node.Library.Name.Red().Bold(), node.Library.Version)); success = false; } return; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isAdded = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isAdded && isRemote) { installItems.Add(node.Item); } }); var dependencies = new Dictionary<Library, string>(); // If there is a global.json file specified, we should do SHA value verification var globalJsonFileSpecified = !string.IsNullOrEmpty(GlobalJsonFile); JToken dependenciesNode = null; if (globalJsonFileSpecified) { var globalJson = JObject.Parse(File.ReadAllText(GlobalJsonFile)); dependenciesNode = globalJson["dependencies"]; if (dependenciesNode != null) { dependencies = dependenciesNode .OfType<JProperty>() .ToDictionary(d => new Library() { Name = d.Name, Version = SemanticVersion.Parse(d.Value.Value<string>("version")) }, d => d.Value.Value<string>("sha")); } } var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory); using (var sha512 = SHA512.Create()) { foreach (var item in installItems) { var library = item.Match.Library; var memStream = new MemoryStream(); await item.Match.Provider.CopyToAsync(item.Match, memStream); memStream.Seek(0, SeekOrigin.Begin); var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(memStream)); string expectedSHA; if (dependencies.TryGetValue(library, out expectedSHA)) { if (!string.Equals(expectedSHA, nupkgSHA, StringComparison.Ordinal)) { Reports.Information.WriteLine( string.Format("SHA of downloaded package {0} doesn't match expected value.".Red().Bold(), library.ToString())); success = false; continue; } } else { // Report warnings only when given global.json contains "dependencies" if (globalJsonFileSpecified && dependenciesNode != null) { Reports.Information.WriteLine( string.Format("Expected SHA of package {0} doesn't exist in given global.json file.".Yellow().Bold(), library.ToString())); } } Reports.Information.WriteLine(string.Format("Installing {0} {1}", library.Name.Bold(), library.Version)); var targetPath = packagePathResolver.GetInstallPath(library.Name, library.Version); var targetNupkg = packagePathResolver.GetPackageFilePath(library.Name, library.Version); var hashPath = packagePathResolver.GetHashPath(library.Name, library.Version); // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple // processes are extracting to the same destination simultaneously await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock => { // If this is the first process trying to install the target nupkg, go ahead // After this process successfully installs the package, all other processes // waiting on this lock don't need to install it again if (createdNewLock) { Directory.CreateDirectory(targetPath); using (var stream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete)) { await item.Match.Provider.CopyToAsync(item.Match, stream); stream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, stream); } File.WriteAllText(hashPath, nupkgSHA); } return 0; }); } } ScriptExecutor.Execute(project, "postrestore", getVariable); ScriptExecutor.Execute(project, "prepare", getVariable); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); // Print the dependency graph if (success) { var graphNum = contexts.Count; for (int i = 0; i < graphNum; i++) { PrintDependencyGraph(graphs[i], contexts[i].FrameworkName); } } return success; }
private async Task <bool> RestoreForProject(string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); var projectFolder = Path.GetDirectoryName(projectJsonPath); var projectLockFilePath = Path.Combine(projectFolder, LockFileFormat.LockFileName); Runtime.Project project; var diagnostics = new List <ICompilationMessage>(); if (!Runtime.Project.TryGetProject(projectJsonPath, out project, diagnostics)) { throw new Exception("TODO: project.json parse error"); } if (diagnostics.HasErrors()) { var errorMessages = diagnostics .Where(x => x.Severity == CompilationMessageSeverity.Error) .Select(x => x.Message); ErrorMessages.GetOrAdd(projectJsonPath, _ => new List <string>()).AddRange(errorMessages); } var lockFile = await ReadLockFile(projectLockFilePath); var useLockFile = false; if (Lock == false && Unlock == false && lockFile != null && lockFile.Islocked) { useLockFile = true; } if (useLockFile && !lockFile.IsValidForProject(project)) { // Exhibit the same behavior as if it has been run with "dnu restore --lock" Reports.Information.WriteLine("Updating the invalid lock file with {0}", "dnu restore --lock".Yellow().Bold()); useLockFile = false; Lock = true; } Func <string, string> getVariable = key => { return(null); }; if (!SkipRestoreEvents) { if (!ScriptExecutor.Execute(project, "prerestore", getVariable)) { ErrorMessages.GetOrAdd("prerestore", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } } var projectDirectory = project.ProjectDirectory; var projectResolver = new ProjectResolver(projectDirectory, rootDirectory); var packageRepository = new PackageRepository(packagesDirectory) { CheckHashFile = CheckHashFile }; var restoreOperations = new RestoreOperations(Reports.Verbose); var projectProviders = new List <IWalkProvider>(); var localProviders = new List <IWalkProvider>(); var remoteProviders = new List <IWalkProvider>(); var contexts = new List <RestoreContext>(); var cache = new Dictionary <LibraryRange, Task <WalkProviderMatch> >(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( projectResolver))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver(packageRepository))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources( Config.Sources, FeedOptions.Sources, FeedOptions.FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); var tasks = new List <Task <TargetContext> >(); if (useLockFile) { Reports.Information.WriteLine(string.Format("Following lock file {0}", projectLockFilePath.White().Bold())); var context = new RestoreContext { FrameworkName = FallbackFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, MatchCache = cache }; contexts.Add(context); foreach (var lockFileLibrary in lockFile.Libraries) { var projectLibrary = new LibraryRange(lockFileLibrary.Name, frameworkReference: false) { VersionRange = new SemanticVersionRange { MinVersion = lockFileLibrary.Version, MaxVersion = lockFileLibrary.Version, IsMaxInclusive = true, VersionFloatBehavior = SemanticVersionFloatBehavior.None, } }; tasks.Add(CreateGraphNode(restoreOperations, context, projectLibrary, _ => false)); } } else { var frameworks = TargetFrameworks.Count == 0 ? project.GetTargetFrameworks().Select(f => f.FrameworkName) : TargetFrameworks; foreach (var frameworkName in frameworks) { var context = new RestoreContext { FrameworkName = frameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, MatchCache = cache }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = FallbackFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, MatchCache = cache }); } foreach (var context in contexts) { var projectLibrary = new LibraryRange(project.Name, frameworkReference: false) { VersionRange = new SemanticVersionRange(project.Version) }; tasks.Add(CreateGraphNode(restoreOperations, context, projectLibrary, _ => true)); } } var targetContexts = await Task.WhenAll(tasks); foreach (var targetContext in targetContexts) { Reduce(targetContext.Root); } if (!useLockFile) { var runtimeFormatter = new RuntimeFileFormatter(); var projectRuntimeFile = runtimeFormatter.ReadRuntimeFile(projectJsonPath); if (projectRuntimeFile.Runtimes.Any()) { var runtimeTasks = new List <Task <TargetContext> >(); foreach (var pair in contexts.Zip(targetContexts, (context, graph) => new { context, graph })) { var runtimeFileTasks = new List <Task <RuntimeFile> >(); ForEach(pair.graph.Root, node => { var match = node?.Item?.Match; if (match == null) { return; } runtimeFileTasks.Add(match.Provider.GetRuntimes(node.Item.Match, pair.context.FrameworkName)); }); var libraryRuntimeFiles = await Task.WhenAll(runtimeFileTasks); var runtimeFiles = new List <RuntimeFile> { projectRuntimeFile }; runtimeFiles.AddRange(libraryRuntimeFiles.Where(file => file != null)); foreach (var runtimeName in projectRuntimeFile.Runtimes.Keys) { var runtimeSpecs = new List <RuntimeSpec>(); FindRuntimeSpecs( runtimeName, runtimeFiles, runtimeSpecs, _ => false); var runtimeContext = new RestoreContext { FrameworkName = pair.context.FrameworkName, ProjectLibraryProviders = pair.context.ProjectLibraryProviders, LocalLibraryProviders = pair.context.LocalLibraryProviders, RemoteLibraryProviders = pair.context.RemoteLibraryProviders, RuntimeName = runtimeName, RuntimeSpecs = runtimeSpecs, MatchCache = cache }; var projectLibrary = new LibraryRange(project.Name, frameworkReference: false) { VersionRange = new SemanticVersionRange(project.Version) }; Reports.Information.WriteLine(string.Format("Graph for {0} on {1}", runtimeContext.FrameworkName, runtimeContext.RuntimeName)); runtimeTasks.Add(CreateGraphNode(restoreOperations, runtimeContext, projectLibrary, _ => true)); } } var runtimeTragetContexts = await Task.WhenAll(runtimeTasks); foreach (var runtimeTargetContext in runtimeTragetContexts) { Reduce(runtimeTargetContext.Root); } targetContexts = targetContexts.Concat(runtimeTragetContexts).ToArray(); } } var graphItems = new List <GraphItem>(); var installItems = new List <GraphItem>(); var missingItems = new HashSet <LibraryRange>(); foreach (var context in targetContexts) { ForEach(context.Root, node => { if (node == null || node.LibraryRange == null) { return; } if (node.Item == null || node.Item.Match == null) { // This is a workaround for #1322. Since we use restore to generate the lock file // after publish, it's possible to fail restore after copying the closure if (!IgnoreMissingDependencies) { if (!node.LibraryRange.IsGacOrFrameworkReference && node.LibraryRange.VersionRange != null && missingItems.Add(node.LibraryRange)) { var errorMessage = string.Format("Unable to locate {0} {1}", node.LibraryRange.Name.Red().Bold(), node.LibraryRange.VersionRange); ErrorMessages.GetOrAdd(projectJsonPath, _ => new List <string>()).Add(errorMessage); Reports.Error.WriteLine(errorMessage); success = false; } } return; } if (!string.Equals(node.Item.Match.Library.Name, node.LibraryRange.Name, StringComparison.Ordinal)) { // Fix casing of the library name to be installed node.Item.Match.Library.Name = node.LibraryRange.Name; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isInstallItem = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isInstallItem && isRemote) { // It's ok to download rejected nodes so we avoid downloading them in the future // The trade off is that subsequent restores avoid going to any remotes installItems.Add(node.Item); } // Don't add rejected nodes since we only want to write reduced nodes // to the lock file if (node.Disposition != GraphNode.DispositionType.Rejected) { var isGraphItem = graphItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isGraphItem) { graphItems.Add(node.Item); } context.Libraries.Add(node.Item.Match.Library); } }); } if (!SkipInstall) { await InstallPackages(installItems, packagesDirectory); } if (!useLockFile) { Reports.Information.WriteLine(string.Format("Writing lock file {0}", projectLockFilePath.White().Bold())); var repository = new PackageRepository(packagesDirectory); WriteLockFile(lockFile, projectLockFilePath, project, graphItems, repository, targetContexts); } if (!SkipRestoreEvents) { if (!ScriptExecutor.Execute(project, "postrestore", getVariable)) { ErrorMessages.GetOrAdd("postrestore", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } if (!ScriptExecutor.Execute(project, "prepare", getVariable)) { ErrorMessages.GetOrAdd("prepare", _ => new List <string>()).Add(ScriptExecutor.ErrorMessage); Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } } Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); return(success); }
private async Task <WalkProviderMatch> FindLibraryMatch(RestoreContext context, LibraryRange libraryRange) { var projectMatch = await FindProjectMatch(context, libraryRange.Name); if (projectMatch != null) { return(projectMatch); } if (libraryRange.VersionRange == null) { return(null); } if (libraryRange.IsGacOrFrameworkReference) { return(null); } if (libraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { // For snapshot dependencies, get the version remotely first. var remoteMatch = await FindLibraryByVersion(context, libraryRange, context.RemoteLibraryProviders); if (remoteMatch == null) { // If there was nothing remotely, use the local match (if any) var localMatch = await FindLibraryByVersion(context, libraryRange, context.LocalLibraryProviders); return(localMatch); } else { // Now check the local repository var localMatch = await FindLibraryByVersion(context, libraryRange, context.LocalLibraryProviders); if (localMatch != null && remoteMatch != null) { // We found a match locally and remotely, so pick the better version // in relation to the specified version. if (VersionUtility.ShouldUseConsidering( current: remoteMatch.Library.Version, considering: localMatch.Library.Version, ideal: libraryRange.VersionRange)) { return(localMatch); } // The remote match is better } // Try to see if the specific version found on the remote exists locally. This avoids any unnecessary // remote access incase we already have it in the cache/local packages folder. localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(remoteMatch.Library.Version)) { // If we have a local match, and it matches the version *exactly* then use it. return(localMatch); } // We found something locally, but it wasn't an exact match // for the resolved remote match. return(remoteMatch); } } else { // Check for the specific version locally. var localMatch = await FindLibraryByVersion(context, libraryRange, context.LocalLibraryProviders); if (localMatch != null && localMatch.Library.Version.Equals(libraryRange.VersionRange.MinVersion)) { // We have an exact match so use it. return(localMatch); } // Either we found a local match but it wasn't the exact version, or // we didn't find a local match. var remoteMatch = await FindLibraryByVersion(context, libraryRange, context.RemoteLibraryProviders); if (remoteMatch != null && localMatch == null) { // There wasn't any local match for the specified version but there was a remote match. // See if that version exists locally. localMatch = await FindLibraryByVersion(context, remoteMatch.Library, context.LocalLibraryProviders); } if (localMatch != null && remoteMatch != null) { // We found a match locally and remotely, so pick the better version // in relation to the specified version. if (VersionUtility.ShouldUseConsidering( current: localMatch.Library.Version, considering: remoteMatch.Library.Version, ideal: libraryRange.VersionRange)) { return(remoteMatch); } else { return(localMatch); } } // Prefer local over remote generally. return(localMatch ?? remoteMatch); } }
private async Task <bool> RestoreForProject(string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); Runtime.Project project; if (!Runtime.Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } Func <string, string> getVariable = key => { return(null); }; ScriptExecutor.Execute(project, "prerestore", getVariable); var projectDirectory = project.ProjectDirectory; var restoreOperations = new RestoreOperations(Reports.Verbose); var projectProviders = new List <IWalkProvider>(); var localProviders = new List <IWalkProvider>(); var remoteProviders = new List <IWalkProvider>(); var contexts = new List <RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( new ProjectResolver( projectDirectory, rootDirectory)))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources(SourceProvider, Sources, FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } var tasks = new List <Task <GraphNode> >(); foreach (var context in contexts) { tasks.Add(restoreOperations.CreateGraphNode(context, new Library { Name = project.Name, Version = project.Version }, _ => true)); } var graphs = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List <GraphItem>(); var missingItems = new HashSet <Library>(); ForEach(graphs, node => { if (node == null || node.Library == null) { return; } if (node.Item == null || node.Item.Match == null) { if (!node.Library.IsGacOrFrameworkReference && node.Library.Version != null && missingItems.Add(node.Library)) { Reports.Error.WriteLine(string.Format("Unable to locate {0} >= {1}", node.Library.Name.Red().Bold(), node.Library.Version)); success = false; } return; } // "kpm restore" is case-sensitive if (!string.Equals(node.Item.Match.Library.Name, node.Library.Name, StringComparison.Ordinal)) { if (missingItems.Add(node.Library)) { Reports.Error.WriteLine("Unable to locate {0} >= {1}. Do you mean {2}?", node.Library.Name.Red().Bold(), node.Library.Version, node.Item.Match.Library.Name.Bold()); success = false; } return; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isAdded = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isAdded && isRemote) { installItems.Add(node.Item); } }); await InstallPackages(installItems, packagesDirectory, packageFilter : (library, nupkgSHA) => true); ScriptExecutor.Execute(project, "postrestore", getVariable); ScriptExecutor.Execute(project, "prepare", getVariable); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); for (int i = 0; i < contexts.Count; i++) { PrintDependencyGraph(graphs[i], contexts[i].FrameworkName); } return(success); }
public async Task <GraphNode> CreateGraphNode(RestoreContext context, LibraryRange libraryRange, Func <string, bool> predicate) { var sw = new Stopwatch(); sw.Start(); var node = new GraphNode { LibraryRange = libraryRange, Item = await FindLibraryCached(context, libraryRange), }; if (node.Item != null) { if (node.LibraryRange.VersionRange != null && node.LibraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None) { lock (context.GraphItemCache) { if (!context.GraphItemCache.ContainsKey(node.LibraryRange)) { context.GraphItemCache[node.LibraryRange] = Task.FromResult(node.Item); } } } var tasks = new List <Task <GraphNode> >(); var dependencies = node.Item.Dependencies ?? Enumerable.Empty <LibraryDependency>(); foreach (var dependency in dependencies) { if (predicate(dependency.Name)) { tasks.Add(CreateGraphNode(context, dependency.LibraryRange, ChainPredicate(predicate, node.Item, dependency))); if (context.RuntimeSpecs != null) { foreach (var runtimeSpec in context.RuntimeSpecs) { DependencySpec dependencyMapping; if (runtimeSpec.Dependencies.TryGetValue(dependency.Name, out dependencyMapping)) { foreach (var dependencyImplementation in dependencyMapping.Implementations.Values) { tasks.Add(CreateGraphNode( context, new LibraryRange(dependencyImplementation.Name, frameworkReference: false) { VersionRange = VersionUtility.ParseVersionRange(dependencyImplementation.Version) }, ChainPredicate(predicate, node.Item, dependency))); } break; } } } } } while (tasks.Any()) { var task = await Task.WhenAny(tasks); tasks.Remove(task); var dependency = await task; node.Dependencies.Add(dependency); } } return(node); }
private async Task<bool> RestoreForProject(string projectJsonPath, string rootDirectory, string packagesDirectory) { var success = true; Reports.Information.WriteLine(string.Format("Restoring packages for {0}", projectJsonPath.Bold())); var sw = new Stopwatch(); sw.Start(); Runtime.Project project; if (!Runtime.Project.TryGetProject(projectJsonPath, out project)) { throw new Exception("TODO: project.json parse error"); } Func<string, string> getVariable = key => { return null; }; if (!ScriptExecutor.Execute(project, "prerestore", getVariable)) { Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } var projectDirectory = project.ProjectDirectory; var restoreOperations = new RestoreOperations(Reports.Verbose); var projectProviders = new List<IWalkProvider>(); var localProviders = new List<IWalkProvider>(); var remoteProviders = new List<IWalkProvider>(); var contexts = new List<RestoreContext>(); projectProviders.Add( new LocalWalkProvider( new ProjectReferenceDependencyProvider( new ProjectResolver( projectDirectory, rootDirectory)))); localProviders.Add( new LocalWalkProvider( new NuGetDependencyResolver( packagesDirectory))); var effectiveSources = PackageSourceUtils.GetEffectivePackageSources(SourceProvider, Sources, FallbackSources); AddRemoteProvidersFromSources(remoteProviders, effectiveSources); foreach (var configuration in project.GetTargetFrameworks()) { var context = new RestoreContext { FrameworkName = configuration.FrameworkName, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }; contexts.Add(context); } if (!contexts.Any()) { contexts.Add(new RestoreContext { FrameworkName = ApplicationEnvironment.RuntimeFramework, ProjectLibraryProviders = projectProviders, LocalLibraryProviders = localProviders, RemoteLibraryProviders = remoteProviders, }); } var tasks = new List<Task<GraphNode>>(); foreach (var context in contexts) { var projectLibrary = new LibraryRange { Name = project.Name, VersionRange = new SemanticVersionRange(project.Version) }; tasks.Add(restoreOperations.CreateGraphNode(context, projectLibrary, _ => true)); } var graphs = await Task.WhenAll(tasks); Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Resolving complete".Green(), sw.ElapsedMilliseconds)); var installItems = new List<GraphItem>(); var missingItems = new HashSet<LibraryRange>(); ForEach(graphs, node => { if (node == null || node.LibraryRange == null) { return; } if (node.Item == null || node.Item.Match == null) { if (!node.LibraryRange.IsGacOrFrameworkReference && node.LibraryRange.VersionRange != null && missingItems.Add(node.LibraryRange)) { Reports.Error.WriteLine(string.Format("Unable to locate {0} {1}", node.LibraryRange.Name.Red().Bold(), node.LibraryRange.VersionRange)); success = false; } return; } // "kpm restore" is case-sensitive if (!string.Equals(node.Item.Match.Library.Name, node.LibraryRange.Name, StringComparison.Ordinal)) { if (missingItems.Add(node.LibraryRange)) { Reports.Error.WriteLine("Unable to locate {0} {1}. Do you mean {2}?", node.LibraryRange.Name.Red().Bold(), node.LibraryRange.VersionRange, node.Item.Match.Library.Name.Bold()); success = false; } return; } var isRemote = remoteProviders.Contains(node.Item.Match.Provider); var isAdded = installItems.Any(item => item.Match.Library == node.Item.Match.Library); if (!isAdded && isRemote) { installItems.Add(node.Item); } }); await InstallPackages(installItems, packagesDirectory, packageFilter: (library, nupkgSHA) => true); if (!ScriptExecutor.Execute(project, "postrestore", getVariable)) { Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } if (!ScriptExecutor.Execute(project, "prepare", getVariable)) { Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } Reports.Information.WriteLine(string.Format("{0}, {1}ms elapsed", "Restore complete".Green().Bold(), sw.ElapsedMilliseconds)); for (int i = 0; i < contexts.Count; i++) { PrintDependencyGraph(graphs[i], contexts[i].FrameworkName); } return success; }