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, "*" + 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; }); }
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; }); }
private bool PrunePackages(PublishRoot root) { var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); // Special cases (for backwards compat) var specialFolders = new List<string> { "native", "InteropAssemblies", "redist", "runtimes" }; 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 path in library.ResourceAssemblies) { 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; }
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; }); }