public void DnuPackagesAddOverwritesInstalledPackageWhenShasDoNotMatch(string flavor, string os, string architecture) { var runtimeHomeDir = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); using (var tempSamplesDir = TestUtils.PrepareTemporarySamplesFolder(runtimeHomeDir)) { var projectFilePath = Path.Combine(tempSamplesDir, ProjectName, Runtime.Project.ProjectFileName); var packagesDir = Path.Combine(tempSamplesDir, PackagesDirName); var packagePathResolver = new DefaultPackagePathResolver(packagesDir); var nuspecPath = packagePathResolver.GetManifestFilePath(ProjectName, ProjectVersion); SetProjectDescription(projectFilePath, "Old"); BuildPackage(tempSamplesDir, runtimeHomeDir); string stdOut; var exitCode = DnuPackagesAddOutputPackage(tempSamplesDir, runtimeHomeDir, out stdOut); Assert.Equal(0, exitCode); Assert.Contains($"Installing {ProjectName}.{ProjectVersion}", stdOut); var lastInstallTime = new FileInfo(nuspecPath).LastWriteTimeUtc; SetProjectDescription(projectFilePath, "New"); BuildPackage(tempSamplesDir, runtimeHomeDir); exitCode = DnuPackagesAddOutputPackage(tempSamplesDir, runtimeHomeDir, out stdOut); Assert.Equal(0, exitCode); Assert.Contains($"Overwriting {ProjectName}.{ProjectVersion}", stdOut); var xDoc = XDocument.Load(packagePathResolver.GetManifestFilePath(ProjectName, ProjectVersion)); var actualDescription = xDoc.Root.Descendants() .Single(x => string.Equals(x.Name.LocalName, "description")).Value; Assert.Equal("New", actualDescription); Assert.NotEqual(lastInstallTime, new FileInfo(nuspecPath).LastWriteTimeUtc); } }
public void DnuPackagesAddSkipsInstalledPackageWhenShasMatch(string flavor, string os, string architecture) { var runtimeHomeDir = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); using (var tempSamplesDir = TestUtils.PrepareTemporarySamplesFolder(runtimeHomeDir)) { var projectFilePath = Path.Combine(tempSamplesDir, ProjectName, Runtime.Project.ProjectFileName); var packagesDir = Path.Combine(tempSamplesDir, PackagesDirName); var packagePathResolver = new DefaultPackagePathResolver(packagesDir); var nuspecPath = packagePathResolver.GetManifestFilePath(ProjectName, ProjectVersion); BuildPackage(tempSamplesDir, runtimeHomeDir); string stdOut; var exitCode = DnuPackagesAddOutputPackage(tempSamplesDir, runtimeHomeDir, out stdOut); Assert.Equal(0, exitCode); Assert.Contains($"Installing {ProjectName}.{ProjectVersion}", stdOut); var lastInstallTime = new FileInfo(nuspecPath).LastWriteTimeUtc; exitCode = DnuPackagesAddOutputPackage(tempSamplesDir, runtimeHomeDir, out stdOut); Assert.Equal(0, exitCode); Assert.Contains($"{ProjectName}.{ProjectVersion} already exists", stdOut); Assert.Equal(lastInstallTime, new FileInfo(nuspecPath).LastWriteTimeUtc); } }
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, "*" + 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); }); }
private bool PrunePackages(PublishRoot root) { var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); // Special cases (for backwards compat) var specialFolders = new List <string> { "native", "InteropAssemblies", "redist" }; if (!root.NoSource) { // 'shared' folder is build time dependency, so we only copy it when deploying with source specialFolders.Add("shared"); } var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName)); var format = new LockFileFormat(); root.LockFile = format.Read(lockFilePath); var keep = new HashSet <string>(); foreach (var target in root.LockFile.Targets) { foreach (var library in target.Libraries) { var packagesDir = resolver.GetInstallPath(library.Name, library.Version); var manifest = resolver.GetManifestFilePath(library.Name, library.Version); keep.Add(manifest); foreach (var path in library.RuntimeAssemblies) { keep.Add(CombinePath(packagesDir, path)); } foreach (var path in library.CompileTimeAssemblies) { keep.Add(CombinePath(packagesDir, path)); } foreach (var path in library.NativeLibraries) { keep.Add(CombinePath(packagesDir, path)); } foreach (var specialFolder in specialFolders) { var specialFolderPath = CombinePath(packagesDir, specialFolder); if (!Directory.Exists(specialFolderPath)) { continue; } keep.AddRange(Directory.EnumerateFiles(specialFolderPath, "*.*", SearchOption.AllDirectories)); } } } foreach (var package in root.Packages) { var packageDir = resolver.GetInstallPath(package.Library.Name, package.Library.Version); var packageFiles = Directory.EnumerateFiles(packageDir, "*.*", SearchOption.AllDirectories); foreach (var file in packageFiles) { if (!keep.Contains(file)) { File.Delete(file); } } root.Operations.DeleteEmptyFolders(packageDir); } return(true); }
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); }); } } }
internal static async Task InstallFromStream( Stream stream, LibraryIdentity library, string packagesDirectory, IReport information, string packageHash = null) { 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 _ => { if (string.IsNullOrEmpty(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(); Manifest manifest = null; using (var nuspecStream = File.OpenRead(nuspecFile)) { manifest = Manifest.ReadFrom(nuspecStream, validateSchema: false); manifest.Metadata.Id = library.Name; manifest.Metadata.Version = library.Version; } // 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); }); }
internal static async Task InstallFromStream( Stream stream, LibraryIdentity library, string packagesDirectory, ILogger log) { 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)) { log.LogInformation($"Installing {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)) { await stream.CopyToAsync(nupkgStream); nupkgStream.Seek(0, SeekOrigin.Begin); ExtractPackage(targetPath, nupkgStream); } // DNU REFACTORING TODO: delete the hacky FixNuSpecIdCasing() and uncomment logic below after we // have implementation of NuSpecFormatter.Read() // Fixup the casing of the nuspec on disk to match what we expect var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + ManifestExtension).Single(); FixNuSpecIdCasing(nuspecFile, targetNuspec, library.Name); /*var actualNuSpecName = Path.GetFileName(nuspecFile); * var expectedNuSpecName = Path.GetFileName(targetNuspec); * * if (!string.Equals(actualNuSpecName, expectedNuSpecName, StringComparison.Ordinal)) * { * MetadataBuilder metadataBuilder = null; * var nuspecFormatter = new NuSpecFormatter(); * using (var nuspecStream = File.OpenRead(nuspecFile)) * { * metadataBuilder = nuspecFormatter.Read(nuspecStream); * // REVIEW: any way better hardcoding "id"? * metadataBuilder.SetMetadataValue("id", library.Name); * } * * // Delete the previous nuspec file * File.Delete(nuspecFile); * * // Write the new manifest * using (var targetNuspecStream = File.OpenWrite(targetNuspec)) * { * nuspecFormatter.Save(metadataBuilder, targetNuspecStream); * } * }*/ stream.Seek(0, SeekOrigin.Begin); string packageHash; using (var sha512 = SHA512.Create()) { packageHash = Convert.ToBase64String(sha512.ComputeHash(stream)); } // 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(hashPath, packageHash); } return(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); }); }