示例#1
0
        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,
            });
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
 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);
     }
 }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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;
        }
示例#8
0
        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);
        }
示例#9
0
        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,
            });
        }
示例#10
0
        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,
            });
        }
示例#11
0
        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);
        }
示例#12
0
        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);
            }
        }
示例#13
0
        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);
        }
示例#14
0
        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;
        }
示例#15
0
        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;
            }
        }
示例#16
0
        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);
        }
示例#17
0
        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);
        }
示例#18
0
        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;
        }
示例#19
0
        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;
            }
        }
示例#20
0
        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;
        }
示例#21
0
        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
            });
        }
示例#22
0
        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,
            };
        }
示例#23
0
        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;
        }
示例#24
0
        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,
            };
        }
示例#25
0
        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;
        }
示例#26
0
        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;
        }
示例#27
0
        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);
        }
示例#28
0
        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);
            }
        }
示例#29
0
        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);
        }
示例#30
0
        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);
        }
示例#31
0
        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;
        }