Пример #1
0
        internal static async Task InstallFromStream(Stream stream, Library library, string packagesDirectory,
                                                     SHA512 sha512)
        {
            var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory);

            var targetPath   = packagePathResolver.GetInstallPath(library.Name, library.Version);
            var targetNuspec = packagePathResolver.GetManifestFilePath(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 nupkgStream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete))
                    {
                        await stream.CopyToAsync(nupkgStream);
                        nupkgStream.Seek(0, SeekOrigin.Begin);

                        ExtractPackage(targetPath, nupkgStream);
                    }

                    // Fixup the casing of the nuspec on disk to match what we expect
                    var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single();

                    if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal))
                    {
                        Manifest manifest = null;
                        using (var nuspecStream = File.OpenRead(nuspecFile))
                        {
                            manifest             = Manifest.ReadFrom(nuspecStream, validateSchema: false);
                            manifest.Metadata.Id = library.Name;
                        }

                        // Delete the previous nuspec file
                        File.Delete(nuspecFile);

                        // Write the new manifest
                        using (var targetNuspecStream = File.OpenWrite(targetNuspec))
                        {
                            manifest.Save(targetNuspecStream);
                        }
                    }

                    stream.Seek(0, SeekOrigin.Begin);
                    var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(stream));
                    File.WriteAllText(hashPath, nupkgSHA);
                }

                return(0);
            });
        }
Пример #2
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);
        }
Пример #3
0
        private async Task InstallPackages(List <GraphItem> installItems, string packagesDirectory, Func <Library, string, bool> packageFilter)
        {
            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));

                    bool shouldInstall = packageFilter(library, nupkgSHA);
                    if (!shouldInstall)
                    {
                        continue;
                    }

                    Reports.Information.WriteLine(string.Format("Installing {0} {1}", library.Name.Bold(), library.Version));

                    var targetPath   = packagePathResolver.GetInstallPath(library.Name, library.Version);
                    var targetNuspec = packagePathResolver.GetManifestFilePath(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);
                            }

                            // Fixup the casing of the nuspec on disk to match what we expect
                            var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + Constants.ManifestExtension).Single();

                            if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal))
                            {
                                Manifest manifest = null;
                                using (var stream = File.OpenRead(nuspecFile))
                                {
                                    manifest             = Manifest.ReadFrom(stream, validateSchema: false);
                                    manifest.Metadata.Id = library.Name;
                                }

                                // Delete the previous nuspec file
                                File.Delete(nuspecFile);

                                // Write the new manifest
                                using (var stream = File.OpenWrite(targetNuspec))
                                {
                                    manifest.Save(stream);
                                }
                            }

                            // Ensure the manifest file name matches
                            File.WriteAllText(hashPath, nupkgSHA);
                        }

                        return(0);
                    });
                }
            }
        }
Пример #4
0
        internal static async Task InstallFromStream(
            Stream stream,
            Library library,
            string packagesDirectory,
            IReport information)
        {
            var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory);

            var targetPath     = packagePathResolver.GetInstallPath(library.Name, library.Version);
            var targetNuspec   = packagePathResolver.GetManifestFilePath(library.Name, library.Version);
            var targetNupkg    = packagePathResolver.GetPackageFilePath(library.Name, library.Version);
            var targetHashPath = 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, action : async _ =>
            {
                string packageHash;
                using (var sha512 = SHA512.Create())
                {
                    packageHash = Convert.ToBase64String(sha512.ComputeHash(stream));
                }

                var actionName           = "Installing";
                var installedPackageHash = string.Empty;
                if (File.Exists(targetHashPath) && File.Exists(targetNuspec))
                {
                    installedPackageHash = File.ReadAllText(targetHashPath);
                    actionName           = "Overwriting";
                }

                if (string.Equals(packageHash, installedPackageHash, StringComparison.Ordinal))
                {
                    information.WriteLine($"{library.Name}.{library.Version} already exists");
                }
                else
                {
                    information.WriteLine($"{actionName} {library.Name}.{library.Version}");

                    Directory.CreateDirectory(targetPath);
                    using (var nupkgStream = new FileStream(
                               targetNupkg,
                               FileMode.Create,
                               FileAccess.ReadWrite,
                               FileShare.ReadWrite | FileShare.Delete,
                               bufferSize: 4096,
                               useAsync: true))
                    {
                        stream.Seek(0, SeekOrigin.Begin);
                        await stream.CopyToAsync(nupkgStream);
                        nupkgStream.Seek(0, SeekOrigin.Begin);

                        ExtractPackage(targetPath, nupkgStream);
                    }

                    // Fixup the casing of the nuspec on disk to match what we expect
                    var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single();

                    if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal))
                    {
                        Manifest manifest = null;
                        using (var nuspecStream = File.OpenRead(nuspecFile))
                        {
                            manifest             = Manifest.ReadFrom(nuspecStream, validateSchema: false);
                            manifest.Metadata.Id = library.Name;
                        }

                        // Delete the previous nuspec file
                        File.Delete(nuspecFile);

                        // Write the new manifest
                        using (var targetNuspecStream = File.OpenWrite(targetNuspec))
                        {
                            manifest.Save(targetNuspecStream);
                        }
                    }

                    // Note: PackageRepository relies on the hash file being written out as the final operation as part of a package install
                    // to assume a package was fully installed.
                    File.WriteAllText(targetHashPath, packageHash);
                }

                return(0);
            });
        }
Пример #5
0
        internal static async Task InstallFromStream(Stream stream,
                                                     Library library,
                                                     string packagesDirectory,
                                                     SHA512 sha512,
                                                     bool performingParallelInstalls = false)
        {
            var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory);

            var targetPath   = packagePathResolver.GetInstallPath(library.Name, library.Version);
            var targetNuspec = packagePathResolver.GetManifestFilePath(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 && !File.Exists(targetNupkg))
                {
                    var extractPath = targetPath;
                    if (performingParallelInstalls)
                    {
                        // Extracting to the {id}/{version} has an issue with concurrent installs - when a package has been partially
                        // extracted, the Restore Operation can inadvertly conclude the package is available locally and proceed to read
                        // partially written package contents. To avoid this we'll extract the package to a sibling directory and Move it
                        // to the target path.
                        extractPath = Path.Combine(Path.GetDirectoryName(targetPath), Path.GetRandomFileName());
                        targetNupkg = Path.Combine(extractPath, Path.GetFileName(targetNupkg));
                    }

                    var extractDirectory = Directory.CreateDirectory(extractPath);
                    using (var nupkgStream = new FileStream(
                               targetNupkg,
                               FileMode.Create,
                               FileAccess.ReadWrite,
                               FileShare.ReadWrite | FileShare.Delete,
                               bufferSize: 4096,
                               useAsync: true))
                    {
                        await stream.CopyToAsync(nupkgStream);
                        nupkgStream.Seek(0, SeekOrigin.Begin);

                        ExtractPackage(extractPath, nupkgStream);
                    }

                    // Fixup the casing of the nuspec on disk to match what we expect
                    var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + NuGet.Constants.ManifestExtension).Single();

                    if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal))
                    {
                        Manifest manifest = null;
                        using (var nuspecStream = File.OpenRead(nuspecFile))
                        {
                            manifest             = Manifest.ReadFrom(nuspecStream, validateSchema: false);
                            manifest.Metadata.Id = library.Name;
                        }

                        // Delete the previous nuspec file
                        File.Delete(nuspecFile);

                        // Write the new manifest
                        using (var targetNuspecStream = File.OpenWrite(targetNuspec))
                        {
                            manifest.Save(targetNuspecStream);
                        }
                    }

                    stream.Seek(0, SeekOrigin.Begin);
                    var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(stream));
                    File.WriteAllText(hashPath, nupkgSHA);

                    if (performingParallelInstalls)
                    {
                        extractDirectory.MoveTo(targetPath);
                    }
                }

                return(0);
            });
        }