public void Dispose_IsIdempotent() { using (var stream = new TestStream()) using (var result = new DownloadResourceResult(stream)) { result.Dispose(); result.Dispose(); Assert.Equal(1, stream.DisposeCallCount); } }
public void Dispose() { // The task should be awaited before calling dispose if (_result != null) { _result.Dispose(); } }
/// <summary> /// Extracts the lib files to execution directory /// </summary> /// <param name="package"> /// The package to extract /// </param> /// <param name="runtime"> /// The current runtime /// </param> /// <param name="frameworkName"> /// The current framework name /// </param> /// <param name="executionDir"> /// The execution directory to load packages /// </param> /// <param name="logAction">The log writing action</param> /// <returns> /// The list of extracted files /// </returns> private static IEnumerable <string> ExtractPackage( DownloadResourceResult package, string runtime, NuGetFramework frameworkName, string executionDir, Action <string> logAction = null) { try { var id = package.PackageReader.GetIdentity(); var files = NuGetFrameworkUtility.GetNearest(package.PackageReader.GetLibItems(), frameworkName)?.Items.ToList() ?? NuGetFrameworkUtility.GetNearest(package.PackageReader.GetToolItems(), frameworkName)?.Items.ToList(); if (files == null || files.Count == 0) { var collection = new ContentItemCollection(); collection.Load(package.PackageReader.GetFiles()); var conventions = new ManagedCodeConventions(runtimeGraph); var criteria = conventions.Criteria.ForFrameworkAndRuntime( NuGetFramework.ParseFrameworkName( PackageRepositoryExtensions.CurrentRuntime, DefaultFrameworkNameProvider.Instance), runtime); files = collection.FindBestItemGroup(criteria, conventions.Patterns.NativeLibraries)?.Items .Select(i => i.Path).ToList(); if (files == null || files.Count == 0) { files = collection.FindBestItemGroup(criteria, conventions.Patterns.RuntimeAssemblies)?.Items .Select(i => i.Path).ToList(); } if (files == null || files.Count == 0) { return(new string[0]); } else { logAction?.Invoke($"{id.Id}: {string.Join(", ", files)}"); } } foreach (var file in files) { using (var fileStream = File.Create(Path.Combine(executionDir, Path.GetFileName(file) ?? file))) { package.PackageReader.GetStream(file).CopyTo(fileStream); } } return(files.Select(file => Path.GetFileName(file) ?? file)); } finally { package.Dispose(); } }
protected virtual void Dispose(bool disposing) { if (_disposed) { return; } if (disposing) { // The task should be awaited before calling dispose if (_result != null) { _result.Dispose(); } } _disposed = true; }
private List <PSResourceInfo> InstallPackage( IEnumerable <PSResourceInfo> pkgsToInstall, // those found to be required to be installed (includes Dependency packages as well) string repoUrl, PSCredential credential, bool isLocalRepo) { List <PSResourceInfo> pkgsSuccessfullyInstalled = new List <PSResourceInfo>(); int totalPkgs = pkgsToInstall.Count(); // Counters for tracking current package out of total int totalInstalledPkgCount = 0; foreach (PSResourceInfo pkg in pkgsToInstall) { totalInstalledPkgCount++; var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { // Create a temp directory to install to var dir = Directory.CreateDirectory(tempInstallPath); // should check it gets created properly // To delete file attributes from the existing ones get the current file attributes first and use AND (&) operator // with a mask (bitwise complement of desired attributes combination). // TODO: check the attributes and if it's read only then set it // attribute may be inherited from the parent // TODO: are there Linux accommodations we need to consider here? dir.Attributes &= ~FileAttributes.ReadOnly; _cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", pkg.Name)); if (!_quiet) { int activityId = 0; int percentComplete = ((totalInstalledPkgCount * 100) / totalPkgs); string activity = string.Format("Installing {0}...", pkg.Name); string statusDescription = string.Format("{0}% Complete", percentComplete); _cmdletPassedIn.WriteProgress( new ProgressRecord(activityId, activity, statusDescription)); } // Create PackageIdentity in order to download string createFullVersion = pkg.Version.ToString(); if (pkg.IsPrerelease) { createFullVersion = pkg.Version.ToString() + "-" + pkg.PrereleaseLabel; } if (!NuGetVersion.TryParse(createFullVersion, out NuGetVersion pkgVersion)) { var message = String.Format("{0} package could not be installed with error: could not parse package '{0}' version '{1} into a NuGetVersion", pkg.Name, pkg.Version.ToString()); var ex = new ArgumentException(message); var packageIdentityVersionParseError = new ErrorRecord(ex, "psdataFileNotExistError", ErrorCategory.ReadError, null); _cmdletPassedIn.WriteError(packageIdentityVersionParseError); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); continue; } var pkgIdentity = new PackageIdentity(pkg.Name, pkgVersion); var cacheContext = new SourceCacheContext(); if (isLocalRepo) { /* Download from a local repository -- this is slightly different process than from a server */ var localResource = new FindLocalPackagesResourceV2(repoUrl); var resource = new LocalDownloadResource(repoUrl, localResource); // Actually downloading the .nupkg from a local repo var result = resource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); // Create the package extraction context PackageExtractionContext packageExtractionContext = new PackageExtractionContext( packageSaveMode: PackageSaveMode.Nupkg, xmlDocFileSaveMode: PackageExtractionBehavior.XmlDocFileSaveMode, clientPolicyContext: null, logger: NullLogger.Instance); // Extracting from .nupkg and placing files into tempInstallPath result.PackageReader.CopyFiles( destination: tempInstallPath, packageFiles: result.PackageReader.GetFiles(), extractFile: new PackageFileExtractor( result.PackageReader.GetFiles(), packageExtractionContext.XmlDocFileSaveMode).ExtractPackageFile, logger: NullLogger.Instance, token: _cancellationToken); result.Dispose(); } else { /* Download from a non-local repository */ // Set up NuGet API resource for download PackageSource source = new PackageSource(repoUrl); if (credential != null) { string password = new NetworkCredential(string.Empty, credential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repoUrl, credential.UserName, password, true, null); } var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); /* Download from a non-local repository -- ie server */ var downloadResource = repository.GetResourceAsync <DownloadResource>().GetAwaiter().GetResult(); DownloadResourceResult result = null; try { result = downloadResource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); } catch (Exception e) { _cmdletPassedIn.WriteVerbose(string.Format("Error attempting download: '{0}'", e.Message)); } finally { // Need to close the .nupkg if (result != null) { result.Dispose(); } } } _cmdletPassedIn.WriteVerbose(string.Format("Successfully able to download package from source to: '{0}'", tempInstallPath)); // pkgIdentity.Version.Version gets the version without metadata or release labels. string newVersion = pkgIdentity.Version.ToNormalizedString(); string normalizedVersionNoPrereleaseLabel = newVersion; if (pkgIdentity.Version.IsPrerelease) { // eg: 2.0.2 normalizedVersionNoPrereleaseLabel = pkgIdentity.Version.ToNormalizedString().Substring(0, pkgIdentity.Version.ToNormalizedString().IndexOf('-')); } string tempDirNameVersion = isLocalRepo ? tempInstallPath : Path.Combine(tempInstallPath, pkgIdentity.Id.ToLower(), newVersion); var version4digitNoPrerelease = pkgIdentity.Version.Version.ToString(); string moduleManifestVersion = string.Empty; var scriptPath = Path.Combine(tempDirNameVersion, pkg.Name + ".ps1"); var modulePath = Path.Combine(tempDirNameVersion, pkg.Name + ".psd1"); // Check if the package is a module or a script var isModule = File.Exists(modulePath); string installPath; if (_savePkg) { // For save the installation path is what is passed in via -Path installPath = _pathsToInstallPkg.FirstOrDefault(); // If saving as nupkg simply copy the nupkg and move onto next iteration of loop // asNupkg functionality only applies to Save-PSResource if (_asNupkg) { var nupkgFile = pkgIdentity.ToString().ToLower() + ".nupkg"; File.Copy(Path.Combine(tempDirNameVersion, nupkgFile), Path.Combine(installPath, nupkgFile)); _cmdletPassedIn.WriteVerbose(string.Format("'{0}' moved into file path '{1}'", nupkgFile, installPath)); pkgsSuccessfullyInstalled.Add(pkg); continue; } } else { // PSModules: /// ./Modules /// ./Scripts /// _pathsToInstallPkg is sorted by desirability, Find will pick the pick the first Script or Modules path found in the list installPath = isModule ? _pathsToInstallPkg.Find(path => path.EndsWith("Modules", StringComparison.InvariantCultureIgnoreCase)) : _pathsToInstallPkg.Find(path => path.EndsWith("Scripts", StringComparison.InvariantCultureIgnoreCase)); } if (isModule) { var moduleManifest = Path.Combine(tempDirNameVersion, pkgIdentity.Id + ".psd1"); if (!File.Exists(moduleManifest)) { var message = String.Format("{0} package could not be installed with error: Module manifest file: {1} does not exist. This is not a valid PowerShell module.", pkgIdentity.Id, moduleManifest); var ex = new ArgumentException(message); var psdataFileDoesNotExistError = new ErrorRecord(ex, "psdataFileNotExistError", ErrorCategory.ReadError, null); _cmdletPassedIn.WriteError(psdataFileDoesNotExistError); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); continue; } if (!Utils.TryParseModuleManifest(moduleManifest, _cmdletPassedIn, out Hashtable parsedMetadataHashtable)) { // Ran into errors parsing the module manifest file which was found in Utils.ParseModuleManifest() and written. continue; } moduleManifestVersion = parsedMetadataHashtable["ModuleVersion"] as string; // Accept License verification if (!_savePkg && !CallAcceptLicense(pkg, moduleManifest, tempInstallPath, newVersion)) { continue; } // If NoClobber is specified, ensure command clobbering does not happen if (_noClobber && !DetectClobber(pkg.Name, parsedMetadataHashtable)) { continue; } } // Delete the extra nupkg related files that are not needed and not part of the module/script DeleteExtraneousFiles(pkgIdentity, tempDirNameVersion); if (_includeXML) { CreateMetadataXMLFile(tempDirNameVersion, installPath, pkg, isModule); } MoveFilesIntoInstallPath( pkg, isModule, isLocalRepo, tempDirNameVersion, tempInstallPath, installPath, newVersion, moduleManifestVersion, scriptPath); _cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", pkg.Name, installPath)); pkgsSuccessfullyInstalled.Add(pkg); } catch (Exception e) { _cmdletPassedIn.WriteError( new ErrorRecord( new PSInvalidOperationException( message: $"Unable to successfully install package '{pkg.Name}': '{e.Message}'", innerException: e), "InstallPackageFailed", ErrorCategory.InvalidOperation, _cmdletPassedIn)); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); } finally { // Delete the temp directory and all its contents _cmdletPassedIn.WriteVerbose(string.Format("Attempting to delete '{0}'", tempInstallPath)); if (Directory.Exists(tempInstallPath)) { if (!TryDeleteDirectory(tempInstallPath, out ErrorRecord errorMsg)) { _cmdletPassedIn.WriteError(errorMsg); } else { _cmdletPassedIn.WriteVerbose(String.Format("Successfully deleted '{0}'", tempInstallPath)); } } } } return(pkgsSuccessfullyInstalled); }
public static async Task <DownloadResourceResult> GetDownloadResultAsync( HttpSource client, PackageIdentity identity, Uri uri, PackageDownloadContext downloadContext, string globalPackagesFolder, ILogger logger, CancellationToken token) { // Observe the NoCache argument. var directDownload = downloadContext.DirectDownload; DownloadResourceResult packageFromGlobalPackages = null; try { packageFromGlobalPackages = GlobalPackagesFolderUtility.GetPackage( identity, globalPackagesFolder); if (packageFromGlobalPackages != null) { if (!downloadContext.SourceCacheContext.NoCache) { return(packageFromGlobalPackages); } else { // The package already exists in the global packages folder but the caller has requested NoCache, // which means the package in the global packages folder should not be used. In this particular // case, NoCache needs to imply DirectDownload. directDownload = true; packageFromGlobalPackages.Dispose(); } } } catch { packageFromGlobalPackages?.Dispose(); } // Get the package from the source. for (var retry = 0; retry < 3; retry++) { try { return(await client.ProcessStreamAsync( new HttpSourceRequest(uri, logger) { IgnoreNotFounds = true, MaxTries = 1 }, async packageStream => { if (packageStream == null) { return new DownloadResourceResult(DownloadResourceResultStatus.NotFound); } if (directDownload) { return await DirectDownloadAsync( client.PackageSource, identity, packageStream, downloadContext, token); } else { return await GlobalPackagesFolderUtility.AddPackageAsync( client.PackageSource, identity, packageStream, globalPackagesFolder, downloadContext.ParentId, downloadContext.ClientPolicyContext, logger, token); } }, downloadContext.SourceCacheContext, logger, token)); } catch (OperationCanceledException) { return(new DownloadResourceResult(DownloadResourceResultStatus.Cancelled)); } catch (SignatureException) { throw; } catch (Exception ex) when(retry < 2) { var message = string.Format(CultureInfo.CurrentCulture, Strings.Log_ErrorDownloading, identity, uri) + Environment.NewLine + ExceptionUtilities.DisplayMessage(ex); logger.LogWarning(message); } catch (Exception ex) { var message = string.Format(CultureInfo.CurrentCulture, Strings.Log_ErrorDownloading, identity, uri); throw new FatalProtocolException(message, ex); } } throw new InvalidOperationException("Reached an unexpected point in the code"); }
private List <string> InstallPackage(IEnumerable <PSResourceInfo> pkgsToInstall, string repoName, string repoUrl, PSCredential credential, bool isLocalRepo) { List <string> pkgsSuccessfullyInstalled = new List <string>(); foreach (PSResourceInfo p in pkgsToInstall) { var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { // Create a temp directory to install to var dir = Directory.CreateDirectory(tempInstallPath); // should check it gets created properly // To delete file attributes from the existing ones get the current file attributes first and use AND (&) operator // with a mask (bitwise complement of desired attributes combination). // TODO: check the attributes and if it's read only then set it // attribute may be inherited from the parent // TODO: are there Linux accommodations we need to consider here? dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly; _cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", p.Name)); // TODO: add progress bar here // Create PackageIdentity in order to download string createFullVersion = p.Version.ToString(); if (p.IsPrerelease) { createFullVersion = p.Version.ToString() + "-" + p.PrereleaseLabel; } if (!NuGetVersion.TryParse(createFullVersion, out NuGetVersion pkgVersion)) { _cmdletPassedIn.WriteDebug(string.Format("Error parsing package '{0}' version '{1}' into a NuGetVersion", p.Name, p.Version.ToString())); continue; } var pkgIdentity = new PackageIdentity(p.Name, pkgVersion); var cacheContext = new SourceCacheContext(); if (isLocalRepo) { /* Download from a local repository -- this is slightly different process than from a server */ var localResource = new FindLocalPackagesResourceV2(repoUrl); var resource = new LocalDownloadResource(repoUrl, localResource); // Actually downloading the .nupkg from a local repo var result = resource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); if (_asNupkg) // this is Save functionality { DirectoryInfo nupkgPath = new DirectoryInfo(((System.IO.FileStream)result.PackageStream).Name); File.Copy(nupkgPath.FullName, Path.Combine(tempInstallPath, pkgIdentity.Id + pkgIdentity.Version + ".nupkg")); continue; } // Create the package extraction context PackageExtractionContext packageExtractionContext = new PackageExtractionContext( packageSaveMode: PackageSaveMode.Nupkg, xmlDocFileSaveMode: PackageExtractionBehavior.XmlDocFileSaveMode, clientPolicyContext: null, logger: NullLogger.Instance); // Extracting from .nupkg and placing files into tempInstallPath result.PackageReader.CopyFiles( destination: tempInstallPath, packageFiles: result.PackageReader.GetFiles(), extractFile: (new PackageFileExtractor(result.PackageReader.GetFiles(), packageExtractionContext.XmlDocFileSaveMode)).ExtractPackageFile, logger: NullLogger.Instance, token: _cancellationToken); result.Dispose(); } else { /* Download from a non-local repository */ // Set up NuGet API resource for download PackageSource source = new PackageSource(repoUrl); if (credential != null) { string password = new NetworkCredential(string.Empty, credential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repoUrl, credential.UserName, password, true, null); } var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); /* Download from a non-local repository -- ie server */ var downloadResource = repository.GetResourceAsync <DownloadResource>().GetAwaiter().GetResult(); DownloadResourceResult result = null; try { result = downloadResource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); } catch (Exception e) { _cmdletPassedIn.WriteDebug(string.Format("Error attempting download: '{0}'", e.Message)); } finally { // Need to close the .nupkg if (result != null) { result.Dispose(); } } } _cmdletPassedIn.WriteDebug(string.Format("Successfully able to download package from source to: '{0}'", tempInstallPath)); // Prompt if module requires license acceptance (need to read info license acceptance info from the module manifest) // pkgIdentity.Version.Version gets the version without metadata or release labels. string newVersion = pkgIdentity.Version.ToNormalizedString(); // string normalizedVersionNoPrereleaseLabel = newVersion; if (pkgIdentity.Version.IsPrerelease) { // 2.0.2 normalizedVersionNoPrereleaseLabel = pkgIdentity.Version.ToNormalizedString().Substring(0, pkgIdentity.Version.ToNormalizedString().IndexOf('-')); } //p.Version = new System.Version(normalizedVersionNoPrereleaseLabel); string tempDirNameVersion = isLocalRepo ? tempInstallPath : Path.Combine(tempInstallPath, pkgIdentity.Id.ToLower(), newVersion); var version4digitNoPrerelease = pkgIdentity.Version.Version.ToString(); string moduleManifestVersion = string.Empty; var scriptPath = Path.Combine(tempDirNameVersion, (p.Name + ".ps1")); var isScript = File.Exists(scriptPath) ? true : false; if (!isScript) { var moduleManifest = Path.Combine(tempDirNameVersion, pkgIdentity.Id + ".psd1"); var parsedMetadataHashtable = Utils.ParseModuleManifest(moduleManifest, this); moduleManifestVersion = parsedMetadataHashtable["ModuleVersion"] as string; // Accept License verification if (!_savePkg && !CallAcceptLicense(p, moduleManifest, tempInstallPath, newVersion)) { continue; } } // Delete the extra nupkg related files that are not needed and not part of the module/script DeleteExtraneousFiles(tempInstallPath, pkgIdentity, tempDirNameVersion); string installPath; if (_savePkg) { // For save the installation path is what is passed in via -Path installPath = _pathsToInstallPkg.FirstOrDefault(); } else { // PSModules: /// ./Modules /// ./Scripts /// _pathsToInstallPkg is sorted by desirability, Find will pick the pick the first Script or Modules path found in the list installPath = isScript ? _pathsToInstallPkg.Find(path => path.EndsWith("Scripts", StringComparison.InvariantCultureIgnoreCase)) : _pathsToInstallPkg.Find(path => path.EndsWith("Modules", StringComparison.InvariantCultureIgnoreCase)); } if (_includeXML) { CreateMetadataXMLFile(tempDirNameVersion, installPath, repoName, p, isScript); } MoveFilesIntoInstallPath(p, isScript, isLocalRepo, tempDirNameVersion, tempInstallPath, installPath, newVersion, moduleManifestVersion, normalizedVersionNoPrereleaseLabel, version4digitNoPrerelease, scriptPath); _cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", p.Name, installPath)); pkgsSuccessfullyInstalled.Add(p.Name); } catch (Exception e) { _cmdletPassedIn.WriteDebug(string.Format("Unable to successfully install package '{0}': '{1}'", p.Name, e.Message)); } finally { // Delete the temp directory and all its contents _cmdletPassedIn.WriteDebug(string.Format("Attempting to delete '{0}'", tempInstallPath)); if (Directory.Exists(tempInstallPath)) { Directory.Delete(tempInstallPath, true); } } } return(pkgsSuccessfullyInstalled); }