diff --git a/src/code/ArgumentCompleter.cs b/src/code/ArgumentCompleter.cs index 1afd903df..7862dad74 100644 --- a/src/code/ArgumentCompleter.cs +++ b/src/code/ArgumentCompleter.cs @@ -1,5 +1,4 @@ -using System.ComponentModel; -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using Microsoft.PowerShell.PowerShellGet.UtilClasses; diff --git a/src/code/GetHelper.cs b/src/code/GetHelper.cs index 11d31813e..3d6ec1d93 100644 --- a/src/code/GetHelper.cs +++ b/src/code/GetHelper.cs @@ -9,7 +9,6 @@ using System.Management.Automation; using Dbg = System.Diagnostics.Debug; -using static Microsoft.PowerShell.PowerShellGet.UtilClasses.PSResourceInfo; namespace Microsoft.PowerShell.PowerShellGet.Cmdlets { @@ -196,7 +195,7 @@ public PSResourceInfo OutputPackageObject(string pkgPath, Dictionary - - [Cmdlet(VerbsCommon.Get, - "PSResourceRepository")] - public sealed - class GetPSResourceRepository : PSCmdlet + [Cmdlet(VerbsCommon.Get, "PSResourceRepository")] + public sealed class GetPSResourceRepository : PSCmdlet { #region Parameters @@ -40,9 +37,11 @@ protected override void BeginProcessing() { RepositorySettings.CheckRepositoryStore(); } + protected override void ProcessRecord() { - string nameArrayAsString = (Name == null || !Name.Any() || string.Equals(Name[0], "*") || Name[0] == null) ? "all" : string.Join(", ", Name); + string nameArrayAsString = (Name == null || !Name.Any() || string.Equals(Name[0], "*") || Name[0] == null) + ? "all" : string.Join(", ", Name); WriteVerbose(String.Format("reading repository: {0}. Calling Read() API now", nameArrayAsString)); List items = RepositorySettings.Read(Name, out string[] errorList); diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index a3d8a4846..a08011eff 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -286,7 +286,7 @@ private List InstallPackage( bool isLocalRepo) { List pkgsSuccessfullyInstalled = new List(); - foreach (PSResourceInfo p in pkgsToInstall) + foreach (PSResourceInfo pkgInfo in pkgsToInstall) { var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try @@ -300,23 +300,24 @@ private List InstallPackage( // 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)); + _cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", pkgInfo.Name)); // TODO: add progress bar here // Create PackageIdentity in order to download - string createFullVersion = p.Version.ToString(); - if (p.IsPrerelease) + string createFullVersion = pkgInfo.Version.ToString(); + if (pkgInfo.IsPrerelease) { - createFullVersion = p.Version.ToString() + "-" + p.PrereleaseLabel; + createFullVersion = pkgInfo.Version.ToString() + "-" + pkgInfo.PrereleaseLabel; } if (!NuGetVersion.TryParse(createFullVersion, out NuGetVersion pkgVersion)) { - _cmdletPassedIn.WriteVerbose(string.Format("Error parsing package '{0}' version '{1}' into a NuGetVersion", p.Name, p.Version.ToString())); + _cmdletPassedIn.WriteVerbose(string.Format("Error parsing package '{0}' version '{1}' into a NuGetVersion", + pkgInfo.Name, pkgInfo.Version.ToString())); continue; } - var pkgIdentity = new PackageIdentity(p.Name, pkgVersion); + var pkgIdentity = new PackageIdentity(pkgInfo.Name, pkgVersion); var cacheContext = new SourceCacheContext(); if (isLocalRepo) @@ -352,7 +353,9 @@ private List InstallPackage( result.PackageReader.CopyFiles( destination: tempInstallPath, packageFiles: result.PackageReader.GetFiles(), - extractFile: (new PackageFileExtractor(result.PackageReader.GetFiles(), packageExtractionContext.XmlDocFileSaveMode)).ExtractPackageFile, + extractFile: new PackageFileExtractor( + result.PackageReader.GetFiles(), + packageExtractionContext.XmlDocFileSaveMode).ExtractPackageFile, logger: NullLogger.Instance, token: _cancellationToken); result.Dispose(); @@ -409,8 +412,8 @@ private List InstallPackage( 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 modulePath = Path.Combine(tempDirNameVersion, (p.Name + ".psd1")); + var scriptPath = Path.Combine(tempDirNameVersion, pkgInfo.Name + ".ps1"); + var modulePath = Path.Combine(tempDirNameVersion, pkgInfo.Name + ".psd1"); // Check if the package is a module or a script var isModule = File.Exists(modulePath); @@ -436,20 +439,20 @@ private List InstallPackage( moduleManifestVersion = parsedMetadataHashtable["ModuleVersion"] as string; // Accept License verification - if (!_savePkg && !CallAcceptLicense(p, moduleManifest, tempInstallPath, newVersion)) + if (!_savePkg && !CallAcceptLicense(pkgInfo, moduleManifest, tempInstallPath, newVersion)) { continue; } // If NoClobber is specified, ensure command clobbering does not happen - if (_noClobber && !DetectClobber(p.Name, tempDirNameVersion, parsedMetadataHashtable)) + if (_noClobber && !DetectClobber(pkgInfo.Name, parsedMetadataHashtable)) { continue; } } // Delete the extra nupkg related files that are not needed and not part of the module/script - DeleteExtraneousFiles(tempInstallPath, pkgIdentity, tempDirNameVersion); + DeleteExtraneousFiles(pkgIdentity, tempDirNameVersion); string installPath; if (_savePkg) @@ -468,20 +471,29 @@ private List InstallPackage( if (_includeXML) { - CreateMetadataXMLFile(tempDirNameVersion, installPath, repoName, p, isModule); + CreateMetadataXMLFile(tempDirNameVersion, installPath, pkgInfo, isModule); } - MoveFilesIntoInstallPath(p, isModule, isLocalRepo, tempDirNameVersion, tempInstallPath, installPath, newVersion, moduleManifestVersion, normalizedVersionNoPrereleaseLabel, version4digitNoPrerelease, scriptPath); + MoveFilesIntoInstallPath( + pkgInfo, + isModule, + isLocalRepo, + tempDirNameVersion, + tempInstallPath, + installPath, + newVersion, + moduleManifestVersion, + scriptPath); - _cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", p.Name, installPath)); - pkgsSuccessfullyInstalled.Add(p.Name); + _cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", pkgInfo.Name, installPath)); + pkgsSuccessfullyInstalled.Add(pkgInfo.Name); } catch (Exception e) { _cmdletPassedIn.WriteError( new ErrorRecord( new PSInvalidOperationException( - message: $"Unable to successfully install package '{p.Name}': '{e.Message}'", + message: $"Unable to successfully install package '{pkgInfo.Name}': '{e.Message}'", innerException: e), "InstallPackageFailed", ErrorCategory.InvalidOperation, @@ -584,7 +596,7 @@ private bool CallAcceptLicense(PSResourceInfo p, string moduleManifest, string t return success; } - private bool DetectClobber(string pkgName, string tempDirNameVersion, Hashtable parsedMetadataHashtable) + private bool DetectClobber(string pkgName, Hashtable parsedMetadataHashtable) { // Get installed modules, then get all possible paths bool foundClobber = false; @@ -608,10 +620,12 @@ private bool DetectClobber(string pkgName, string tempDirNameVersion, Hashtable duplicateCmdlets = listOfCmdlets.Where(cmdlet => pkg.Includes.Cmdlet.Contains(cmdlet)).ToList(); } + if (pkg.Includes.Command != null && pkg.Includes.Command.Any()) { duplicateCmds = listOfCmdlets.Where(commands => pkg.Includes.Command.Contains(commands, StringComparer.InvariantCultureIgnoreCase)).ToList(); } + if (duplicateCmdlets.Any() || duplicateCmds.Any()) { @@ -634,7 +648,7 @@ private bool DetectClobber(string pkgName, string tempDirNameVersion, Hashtable return foundClobber; } - private void CreateMetadataXMLFile(string dirNameVersion, string installPath, string repoName, PSResourceInfo pkg, bool isModule) + private void CreateMetadataXMLFile(string dirNameVersion, string installPath, PSResourceInfo pkg, bool isModule) { // Script will have a metadata file similar to: "TestScript_InstalledScriptInfo.xml" // Modules will have the metadata file: "PSGetModuleInfo.xml" @@ -654,14 +668,14 @@ private void CreateMetadataXMLFile(string dirNameVersion, string installPath, st } } - private void DeleteExtraneousFiles(string tempInstallPath, PackageIdentity pkgIdentity, string dirNameVersion) + private void DeleteExtraneousFiles(PackageIdentity pkgIdentity, string dirNameVersion) { // Deleting .nupkg SHA file, .nuspec, and .nupkg after unpacking the module var pkgIdString = pkgIdentity.ToString(); - var nupkgSHAToDelete = Path.Combine(dirNameVersion, (pkgIdString + ".nupkg.sha512")); - var nuspecToDelete = Path.Combine(dirNameVersion, (pkgIdentity.Id + ".nuspec")); - var nupkgToDelete = Path.Combine(dirNameVersion, (pkgIdString + ".nupkg")); - var nupkgMetadataToDelete = Path.Combine(dirNameVersion, (pkgIdString + ".nupkg.metadata")); + var nupkgSHAToDelete = Path.Combine(dirNameVersion, pkgIdString + ".nupkg.sha512"); + var nuspecToDelete = Path.Combine(dirNameVersion, pkgIdentity.Id + ".nuspec"); + var nupkgToDelete = Path.Combine(dirNameVersion, pkgIdString + ".nupkg"); + var nupkgMetadataToDelete = Path.Combine(dirNameVersion, pkgIdString + ".nupkg.metadata"); var contentTypesToDelete = Path.Combine(dirNameVersion, "[Content_Types].xml"); var relsDirToDelete = Path.Combine(dirNameVersion, "_rels"); var packageDirToDelete = Path.Combine(dirNameVersion, "package"); @@ -725,7 +739,7 @@ private bool TryDeleteDirectory( } private void MoveFilesIntoInstallPath( - PSResourceInfo p, + PSResourceInfo pkgInfo, bool isModule, bool isLocalRepo, string dirNameVersion, @@ -733,17 +747,15 @@ private void MoveFilesIntoInstallPath( string installPath, string newVersion, string moduleManifestVersion, - string nupkgVersion, - string versionWithoutPrereleaseTag, string scriptPath) { // Creating the proper installation path depending on whether pkg is a module or script - var newPathParent = isModule ? Path.Combine(installPath, p.Name) : installPath; - var finalModuleVersionDir = isModule ? Path.Combine(installPath, p.Name, moduleManifestVersion) : installPath; // versionWithoutPrereleaseTag + var newPathParent = isModule ? Path.Combine(installPath, pkgInfo.Name) : installPath; + var finalModuleVersionDir = isModule ? Path.Combine(installPath, pkgInfo.Name, moduleManifestVersion) : installPath; // If script, just move the files over, if module, move the version directory over var tempModuleVersionDir = (!isModule || isLocalRepo) ? dirNameVersion - : Path.Combine(tempInstallPath, p.Name.ToLower(), newVersion); + : Path.Combine(tempInstallPath, pkgInfo.Name.ToLower(), newVersion); _cmdletPassedIn.WriteVerbose(string.Format("Installation source path is: '{0}'", tempModuleVersionDir)); _cmdletPassedIn.WriteVerbose(string.Format("Installation destination path is: '{0}'", finalModuleVersionDir)); @@ -774,11 +786,12 @@ private void MoveFilesIntoInstallPath( Utils.MoveDirectory(tempModuleVersionDir, finalModuleVersionDir); } } - else { + else + { if (!_savePkg) { // Need to delete old xml files because there can only be 1 per script - var scriptXML = p.Name + "_InstalledScriptInfo.xml"; + var scriptXML = pkgInfo.Name + "_InstalledScriptInfo.xml"; _cmdletPassedIn.WriteVerbose(string.Format("Checking if path '{0}' exists: ", File.Exists(Path.Combine(installPath, "InstalledScriptInfos", scriptXML)))); if (File.Exists(Path.Combine(installPath, "InstalledScriptInfos", scriptXML))) { @@ -790,16 +803,16 @@ private void MoveFilesIntoInstallPath( Utils.MoveFiles(Path.Combine(dirNameVersion, scriptXML), Path.Combine(installPath, "InstalledScriptInfos", scriptXML)); // Need to delete old script file, if that exists - _cmdletPassedIn.WriteVerbose(string.Format("Checking if path '{0}' exists: ", File.Exists(Path.Combine(finalModuleVersionDir, p.Name + ".ps1")))); - if (File.Exists(Path.Combine(finalModuleVersionDir, p.Name + ".ps1"))) + _cmdletPassedIn.WriteVerbose(string.Format("Checking if path '{0}' exists: ", File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1")))); + if (File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1"))) { _cmdletPassedIn.WriteVerbose(string.Format("Deleting script file")); - File.Delete(Path.Combine(finalModuleVersionDir, p.Name + ".ps1")); + File.Delete(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1")); } } - _cmdletPassedIn.WriteVerbose(string.Format("Moving '{0}' to '{1}'", scriptPath, Path.Combine(finalModuleVersionDir, p.Name + ".ps1"))); - Utils.MoveFiles(scriptPath, Path.Combine(finalModuleVersionDir, p.Name + ".ps1")); + _cmdletPassedIn.WriteVerbose(string.Format("Moving '{0}' to '{1}'", scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1"))); + Utils.MoveFiles(scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1")); } } diff --git a/src/code/NuGetLogger.cs b/src/code/NuGetLogger.cs index baa50d42b..d46d4a4d1 100644 --- a/src/code/NuGetLogger.cs +++ b/src/code/NuGetLogger.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using NuGet.Common; using System; using System.Collections.Concurrent; using System.Threading.Tasks; -using NuGet.Common; -// This class is needed for -public class NuGetLogger : ILogger +#region NuGetLogger + +internal class NuGetLogger : ILogger { private readonly ITestOutputHelper _output; @@ -175,9 +176,13 @@ public async Task LogAsync(ILogMessage message) } } +#endregion + +#region ITestOutputHelper + // Summary: // Represents a class which can be used to provide test output. -public interface ITestOutputHelper +internal interface ITestOutputHelper { // Summary: // Adds a line of text to the output. @@ -185,6 +190,7 @@ public interface ITestOutputHelper // message: // The message void WriteLine(string message); + // Summary: // Formats a line of text and adds it to the output. // Parameters: @@ -194,3 +200,5 @@ public interface ITestOutputHelper // The format arguments void WriteLine(string format, params object[] args); } + +#endregion diff --git a/src/code/PSRepositoryInfo.cs b/src/code/PSRepositoryInfo.cs index ade75833e..b1d99eb08 100644 --- a/src/code/PSRepositoryInfo.cs +++ b/src/code/PSRepositoryInfo.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + using System; using System.Management.Automation; diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 4286bab86..8f29930a0 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -57,11 +57,7 @@ public string Path set { - string resolvedPath = string.Empty; - if (!string.IsNullOrEmpty(value)) - { - resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path; - } + string resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path; if (Directory.Exists(resolvedPath)) { @@ -88,18 +84,14 @@ public string DestinationPath set { - string resolvedPath = string.Empty; - if (!string.IsNullOrEmpty(value)) - { - resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path; - } + string resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path; if (Directory.Exists(resolvedPath)) { _destinationPath = resolvedPath; } - else { - // try to create the path + else + { try { Directory.CreateDirectory(value); @@ -175,6 +167,7 @@ public PSCredential ProxyCredential { #endregion #region Method overrides + protected override void BeginProcessing() { // Create a respository story (the PSResourceRepository.xml file) if it does not already exist @@ -184,10 +177,6 @@ protected override void BeginProcessing() protected override void ProcessRecord() { - string moduleManifestOrScriptPath; - FileInfo moduleFileInfo; - Hashtable parsedMetadataHash = new Hashtable(StringComparer.InvariantCultureIgnoreCase); - // Returns the name of the file or the name of the directory, depending on path var pkgFileOrDir = new DirectoryInfo(_path); bool isScript = _path.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase); @@ -198,23 +187,22 @@ protected override void ProcessRecord() WriteVerbose("ShouldProcess is set to false."); return; } - + + string resourceFilePath; + Hashtable parsedMetadataHash = new Hashtable(StringComparer.InvariantCultureIgnoreCase); if (isScript) { - // Get the .psd1 file or .ps1 file - moduleManifestOrScriptPath = pkgFileOrDir.FullName; - moduleFileInfo = new FileInfo(moduleManifestOrScriptPath); + resourceFilePath = pkgFileOrDir.FullName; // Check that script metadata is valid - // ParseScriptMetadata will write non-terminating error if it's unsucessful in parsing - parsedMetadataHash = ParseScriptMetadata(moduleFileInfo); + // ParseScriptMetadata will write non-terminating error if it's unsuccessful in parsing + parsedMetadataHash = ParseScriptMetadata(resourceFilePath); - var message = string.Empty; // Check that the value is valid input // If it does not contain 'Version' or the Version empty or whitespace, write error if (!parsedMetadataHash.ContainsKey("Version") || String.IsNullOrWhiteSpace(parsedMetadataHash["Version"].ToString())) { - message = "No version was provided in the script metadata. Script metadata must specify a version, author and description."; + var message = "No version was provided in the script metadata. Script metadata must specify a version, author and description."; var ex = new ArgumentException(message); var InvalidScriptMetadata = new ErrorRecord(ex, "InvalidScriptMetadata", ErrorCategory.InvalidData, null); WriteError(InvalidScriptMetadata); @@ -223,7 +211,7 @@ protected override void ProcessRecord() } if (!parsedMetadataHash.ContainsKey("Author") || String.IsNullOrWhiteSpace(parsedMetadataHash["Author"].ToString())) { - message = "No author was provided in the script metadata. Script metadata must specify a version, author and description."; + var message = "No author was provided in the script metadata. Script metadata must specify a version, author and description."; var ex = new ArgumentException(message); var InvalidScriptMetadata = new ErrorRecord(ex, "InvalidScriptMetadata", ErrorCategory.InvalidData, null); WriteError(InvalidScriptMetadata); @@ -232,7 +220,7 @@ protected override void ProcessRecord() } if (!parsedMetadataHash.ContainsKey("Description") || String.IsNullOrWhiteSpace(parsedMetadataHash["Description"].ToString())) { - message = "No description was provided in the script metadata. Script metadata must specify a version, author and description."; + var message = "No description was provided in the script metadata. Script metadata must specify a version, author and description."; var ex = new ArgumentException(message); var InvalidScriptMetadata = new ErrorRecord(ex, "InvalidScriptMetadata", ErrorCategory.InvalidData, null); WriteError(InvalidScriptMetadata); @@ -243,15 +231,15 @@ protected override void ProcessRecord() // remove '.ps1' extension from file name _pkgName = pkgFileOrDir.Name.Remove(pkgFileOrDir.Name.Length - 4); } - else { + else + { _pkgName = pkgFileOrDir.Name; - moduleManifestOrScriptPath = System.IO.Path.Combine(_path, _pkgName + ".psd1"); - moduleFileInfo = new FileInfo(moduleManifestOrScriptPath); + resourceFilePath = System.IO.Path.Combine(_path, _pkgName + ".psd1"); // Validate that there's a module manifest - if (!File.Exists(moduleManifestOrScriptPath)) + if (!File.Exists(resourceFilePath)) { - var message = String.Format("No file with a .psd1 extension was found in {0}. Please specify a path to a valid modulemanifest.", moduleManifestOrScriptPath); + var message = String.Format("No file with a .psd1 extension was found in {0}. Please specify a path to a valid modulemanifest.", resourceFilePath); var ex = new ArgumentException(message); var moduleManifestNotFound = new ErrorRecord(ex, "moduleManifestNotFound", ErrorCategory.ObjectNotFound, null); WriteError(moduleManifestNotFound); @@ -260,7 +248,7 @@ protected override void ProcessRecord() } // validate that the module manifest has correct data - if (!IsValidModuleManifest(moduleManifestOrScriptPath)) + if (!IsValidModuleManifest(resourceFilePath)) { return; } @@ -274,7 +262,8 @@ protected override void ProcessRecord() { Directory.CreateDirectory(outputDir); } - catch (Exception e) { + catch (Exception e) + { var ex = new ArgumentException(e.Message); var ErrorCreatingTempDir = new ErrorRecord(ex, "ErrorCreatingTempDir", ErrorCategory.InvalidData, null); WriteError(ErrorCreatingTempDir); @@ -285,16 +274,21 @@ protected override void ProcessRecord() try { - Hashtable dependencies; - // Create a nuspec // Right now parsedMetadataHash will be empty for modules and will contain metadata for scripts + Hashtable dependencies; string nuspec = string.Empty; try { - nuspec = CreateNuspec(outputDir, moduleFileInfo, out dependencies, parsedMetadataHash); + nuspec = CreateNuspec( + outputDir: outputDir, + filePath: resourceFilePath, + isScript: isScript, + parsedMetadataHash: parsedMetadataHash, + requiredModules: out dependencies); } - catch (Exception e) { + catch (Exception e) + { var message = string.Format("Nuspec creation failed: {0}", e.Message); var ex = new ArgumentException(message); var nuspecCreationFailed = new ErrorRecord(ex, "NuspecCreationFailed", ErrorCategory.ObjectNotFound, null); @@ -311,7 +305,7 @@ protected override void ProcessRecord() } // Find repository - PSRepositoryInfo repository = RepositorySettings.Read(new[] { Repository }, out string[] errorList).FirstOrDefault(); + PSRepositoryInfo repository = RepositorySettings.Read(new[] { Repository }, out string[] _).FirstOrDefault(); if (repository == null) { var message = String.Format("The resource repository '{0}' is not a registered. Please run 'Register-PSResourceRepository' in order to publish to this repository.", Repository); @@ -371,7 +365,7 @@ protected override void ProcessRecord() // pack into a nupkg try { - if(!PackNupkg(outputDir, outputNupkgDir, nuspec)) + if (!PackNupkg(outputDir, outputNupkgDir, nuspec)) { return; } @@ -411,7 +405,8 @@ protected override void ProcessRecord() PushNupkg(outputNupkgDir, repository.Name, repositoryUrl); } - finally { + finally + { WriteVerbose(string.Format("Deleting temporary directory '{0}'", outputDir)); Utils.DeleteDirectory(outputDir); } @@ -423,7 +418,7 @@ protected override void ProcessRecord() private bool IsValidModuleManifest(string moduleManifestPath) { - var isValid = false; + var isValid = true; using (System.Management.Automation.PowerShell pwsh = System.Management.Automation.PowerShell.Create()) { // use PowerShell cmdlet Test-ModuleManifest @@ -453,10 +448,7 @@ private bool IsValidModuleManifest(string moduleManifestPath) var ex = new ArgumentException(message); var InvalidModuleManifest = new ErrorRecord(ex, "InvalidModuleManifest", ErrorCategory.InvalidData, null); WriteError(InvalidModuleManifest); - } - else - { - isValid = true; + isValid = false; } } @@ -464,53 +456,30 @@ private bool IsValidModuleManifest(string moduleManifestPath) } private string CreateNuspec( - string outputDir, - FileInfo moduleFileInfo, - out Hashtable requiredModules, - Hashtable parsedMetadataHash) + string outputDir, + string filePath, + bool isScript, + Hashtable parsedMetadataHash, + out Hashtable requiredModules) { WriteVerbose("Creating new nuspec file."); requiredModules = new Hashtable(); - // A script will already have the metadata parsed into the parsedMetadatahash, + // A script will already have the metadata parsed into the parsedMetadatahash, // a module will still need the module manifest to be parsed. - if (moduleFileInfo.Extension.Equals(".psd1", StringComparison.OrdinalIgnoreCase)) + if (!isScript) { - // Parse the module manifest - System.Management.Automation.Language.Token[] tokens; - ParseError[] errors; - var ast = Parser.ParseFile(moduleFileInfo.FullName, out tokens, out errors); - - if (errors.Length > 0) + // Parse the module manifest and *replace* the passed-in metadata with the module manifest metadata. + if (!Utils.TryParseModuleManifest( + moduleFileInfo: filePath, + cmdletPassedIn: this, + parsedMetadataHashtable: out parsedMetadataHash)) { - var message = String.Format("Could not parse '{0}' as a PowerShell data file.", moduleFileInfo.FullName); - var ex = new ArgumentException(message); - var psdataParseError = new ErrorRecord(ex, "psdataParseError", ErrorCategory.ParserError, null); - WriteError(psdataParseError); - return string.Empty; } - else - { - // Must search nested script blocks because 'Tags' are located under 'PrivateData' > 'PSData' - var data = ast.Find(a => a is HashtableAst, true); - if (data != null) - { - parsedMetadataHash = (Hashtable) data.SafeGetValue(); - } - else - { - var message = String.Format("Could not parse as PowerShell data file-- no hashtable root for file '{0}'", moduleFileInfo.FullName); - var ex = new ArgumentException(message); - var psdataParseError = new ErrorRecord(ex, "psdataParseError", ErrorCategory.ParserError, null); - WriteError(psdataParseError); - - return string.Empty; - } - } } - /// now we have parsedMetadatahash to fill out the nuspec information + // now we have parsedMetadatahash to fill out the nuspec information var nameSpaceUri = "http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"; var doc = new XmlDocument(); @@ -528,7 +497,7 @@ private string CreateNuspec( // id is mandatory metadataElementsDictionary.Add("id", _pkgName); - string version = String.Empty; + string version; if (parsedMetadataHash.ContainsKey("moduleversion")) { version = parsedMetadataHash["moduleversion"].ToString(); @@ -608,7 +577,7 @@ private string CreateNuspec( metadataElementsDictionary.Add("copyright", parsedMetadataHash["copyright"].ToString().Trim()); } - string tags = moduleFileInfo.Extension.Equals(".psd1", StringComparison.OrdinalIgnoreCase) ? "PSModule" : "PSScript"; + string tags = isScript ? "PSScript" : "PSModule"; if (parsedMetadataHash.ContainsKey("tags")) { if (parsedMetadataHash["tags"] != null) @@ -742,7 +711,7 @@ private Hashtable ParseRequiredModules(Hashtable parsedMetadataHash) return dependenciesHash; } - private Hashtable ParseScriptMetadata(FileInfo moduleFileInfo) + private Hashtable ParseScriptMetadata(string filePath) { // parse .ps1 - example .ps1 metadata: /* <#PSScriptInfo @@ -769,13 +738,14 @@ Example cmdlet here Hashtable parsedMetadataHash = new Hashtable(StringComparer.InvariantCultureIgnoreCase); // parse comments out - System.Management.Automation.Language.Token[] tokens; - ParseError[] errors; - Parser.ParseFile(moduleFileInfo.FullName, out tokens, out errors); + Parser.ParseFile( + filePath, + out System.Management.Automation.Language.Token[] tokens, + out ParseError[] errors); if (errors.Length > 0) { - var message = String.Format("Could not parse '{0}' as a PowerShell data file.", moduleFileInfo.FullName); + var message = String.Format("Could not parse '{0}' as a PowerShell data file.", filePath); var ex = new ArgumentException(message); var psdataParseError = new ErrorRecord(ex, "psdataParseError", ErrorCategory.ParserError, null); WriteError(psdataParseError); diff --git a/src/code/RegisterPSResourceRepository.cs b/src/code/RegisterPSResourceRepository.cs index 11cb8a861..821f05688 100644 --- a/src/code/RegisterPSResourceRepository.cs +++ b/src/code/RegisterPSResourceRepository.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Generic; using System.Management.Automation; + using Dbg = System.Diagnostics.Debug; namespace Microsoft.PowerShell.PowerShellGet.Cmdlets diff --git a/src/code/RepositorySettings.cs b/src/code/RepositorySettings.cs index 529e56186..511c9d651 100644 --- a/src/code/RepositorySettings.cs +++ b/src/code/RepositorySettings.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Management.Automation; using System.Xml.Linq; -using static System.Environment; + using Dbg = System.Diagnostics.Debug; namespace Microsoft.PowerShell.PowerShellGet.UtilClasses @@ -19,19 +19,24 @@ namespace Microsoft.PowerShell.PowerShellGet.UtilClasses /// internal static class RepositorySettings - { - /// - /// File name for a user's repository store file is 'PSResourceRepository.xml' - /// The repository store file's location is currently only at '%LOCALAPPDATA%\PowerShellGet' for the user account. - /// + { + #region Members + + // File name for a user's repository store file is 'PSResourceRepository.xml' + // The repository store file's location is currently only at '%LOCALAPPDATA%\PowerShellGet' for the user account. private const string PSGalleryRepoName = "PSGallery"; private const string PSGalleryRepoURL = "https://www.powershellgallery.com/api/v2"; private const int defaultPriority = 50; private const bool defaultTrusted = false; private const string RepositoryFileName = "PSResourceRepository.xml"; - private static readonly string RepositoryPath = Path.Combine(Environment.GetFolderPath(SpecialFolder.LocalApplicationData), "PowerShellGet"); + private static readonly string RepositoryPath = Path.Combine(Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData), "PowerShellGet"); private static readonly string FullRepositoryPath = Path.Combine(RepositoryPath, RepositoryFileName); + #endregion + + #region Public methods + /// /// Check if repository store xml file exists, if not then create /// @@ -305,6 +310,10 @@ public static List Read(string[] repoNames, out string[] error return reposToReturn.ToList(); } + #endregion + + #region Private methods + private static XElement FindRepositoryElement(XDocument doc, string name) { return doc.Descendants("Repository").Where( @@ -313,5 +322,7 @@ private static XElement FindRepositoryElement(XDocument doc, string name) name, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); } + + #endregion } } diff --git a/src/code/SavePSResource.cs b/src/code/SavePSResource.cs index 9c8b292f7..64e9e98bc 100644 --- a/src/code/SavePSResource.cs +++ b/src/code/SavePSResource.cs @@ -192,7 +192,7 @@ protected override void ProcessRecord() #endregion - #region Methods + #region Private methods private void ProcessSaveHelper(string[] pkgNames, bool pkgPrerelease, string[] pkgRepository) { diff --git a/src/code/SetPSResourceRepository.cs b/src/code/SetPSResourceRepository.cs index 49ed8d272..a2144e3e1 100644 --- a/src/code/SetPSResourceRepository.cs +++ b/src/code/SetPSResourceRepository.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.PowerShell.PowerShellGet.UtilClasses; using System; using System.Collections; using System.Collections.Generic; -using Dbg = System.Diagnostics.Debug; using System.Management.Automation; -using Microsoft.PowerShell.PowerShellGet.UtilClasses; + +using Dbg = System.Diagnostics.Debug; namespace Microsoft.PowerShell.PowerShellGet.Cmdlets { @@ -17,8 +18,7 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets "PSResourceRepository", DefaultParameterSetName = NameParameterSet, SupportsShouldProcess = true)] - public sealed - class SetPSResourceRepository : PSCmdlet + public sealed class SetPSResourceRepository : PSCmdlet { #region Members @@ -89,7 +89,8 @@ public SwitchParameter Trusted #endregion - #region Methods + #region Private methods + protected override void BeginProcessing() { RepositorySettings.CheckRepositoryStore(); @@ -190,6 +191,7 @@ private PSRepositoryInfo UpdateRepositoryStoreHelper(string repoName, Uri repoUr { return null; } + return RepositorySettings.Update(repoName, repoUrl, repoPriority, _trustedNullable); } diff --git a/src/code/UninstallPSResource.cs b/src/code/UninstallPSResource.cs index 1b627a3d4..4c2be49d9 100644 --- a/src/code/UninstallPSResource.cs +++ b/src/code/UninstallPSResource.cs @@ -1,15 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +using NuGet.Versioning; +using Microsoft.PowerShell.PowerShellGet.UtilClasses; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Management.Automation; -using System.Threading; -using NuGet.Versioning; -using Microsoft.PowerShell.PowerShellGet.UtilClasses; - namespace Microsoft.PowerShell.PowerShellGet.Cmdlets { @@ -20,6 +19,7 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets public sealed class UninstallPSResource : PSCmdlet { #region Parameters + /// /// Specifies the exact names of resources to uninstall. /// A comma-separated list of module names is accepted. The resource name must match the resource name in the repository. @@ -47,17 +47,21 @@ public sealed class UninstallPSResource : PSCmdlet [Parameter(ParameterSetName = NameParameterSet)] [Parameter(ParameterSetName = InputObjectParameterSet)] public SwitchParameter Force { get; set; } + #endregion #region Members + private const string NameParameterSet = "NameParameterSet"; private const string InputObjectParameterSet = "InputObjectParameterSet"; public static readonly string OsPlatform = System.Runtime.InteropServices.RuntimeInformation.OSDescription; VersionRange _versionRange; List _pathsToSearch = new List(); + #endregion - #region Methods + #region Method overrides + protected override void BeginProcessing() { _pathsToSearch = Utils.GetAllResourcePaths(this); @@ -139,6 +143,9 @@ protected override void ProcessRecord() } } + #endregion + + #region Private methods private bool UninstallPkgHelper() { @@ -155,7 +162,7 @@ private bool UninstallPkgHelper() // ./Scripts/TestScript.ps1 // note that the xml file is located in ./Scripts/InstalledScriptInfos, eg: ./Scripts/InstalledScriptInfos/TestScript_InstalledScriptInfo.xml - string pkgName = string.Empty; + string pkgName; foreach (string pkgPath in getHelper.FilterPkgPathsByVersion(_versionRange, dirsToDelete)) { pkgName = Utils.GetInstalledPackageName(pkgPath); @@ -230,7 +237,8 @@ private bool UninstallModuleHelper(string pkgPath, string pkgName, out ErrorReco Utils.DeleteDirectory(dir.Parent.FullName); } } - catch (Exception e) { + catch (Exception e) + { // write error var exMessage = String.Format("Parent directory '{0}' could not be deleted: {1}", dir.Parent.FullName, e.Message); var ex = new ArgumentException(exMessage); @@ -238,7 +246,8 @@ private bool UninstallModuleHelper(string pkgPath, string pkgName, out ErrorReco errRecord = ErrorDeletingParentDirectory; } } - catch (Exception err) { + catch (Exception err) + { // write error var exMessage = String.Format("Directory '{0}' could not be deleted: {1}", dir.FullName, err.Message); var ex = new ArgumentException(exMessage); @@ -281,7 +290,8 @@ private bool UninstallScriptHelper(string pkgPath, string pkgName, out ErrorReco errRecord = ErrorDeletingScriptMetadataFile; } } - catch (Exception err){ + catch (Exception err) + { var exMessage = String.Format("Script '{0}' could not be deleted: {1}", pkgPath, err.Message); var ex = new ArgumentException(exMessage); var ErrorDeletingScript = new ErrorRecord(ex, "ErrorDeletingScript", ErrorCategory.PermissionDenied, null); @@ -313,7 +323,8 @@ private bool CheckIfDependency(string pkgName, out ErrorRecord errRecord) p => ((ReadOnlyCollection)p.Properties["RequiredModules"].Value).Where( rm => rm.Name.Equals(pkgName, StringComparison.InvariantCultureIgnoreCase)).Any()); } - catch (Exception e) { + catch (Exception e) + { var exMessage = String.Format("Error checking if resource is a dependency: {0}. If you would still like to uninstall, rerun the command with -Force", e.Message); var ex = new ArgumentException(exMessage); var DependencyCheckError = new ErrorRecord(ex, "DependencyCheckError", ErrorCategory.OperationStopped, null); @@ -333,8 +344,10 @@ private bool CheckIfDependency(string pkgName, out ErrorRecord errRecord) return true; } } + return false; } + #endregion } } diff --git a/src/code/UnregisterPSResourceRepository.cs b/src/code/UnregisterPSResourceRepository.cs index 2d984fc12..bf7647082 100644 --- a/src/code/UnregisterPSResourceRepository.cs +++ b/src/code/UnregisterPSResourceRepository.cs @@ -30,7 +30,7 @@ class UnregisterPSResourceRepository : PSCmdlet #endregion - #region Methods + #region Method overrides protected override void BeginProcessing() { diff --git a/src/code/UpdatePSResource.cs b/src/code/UpdatePSResource.cs index 90fcb0ea0..86b811888 100644 --- a/src/code/UpdatePSResource.cs +++ b/src/code/UpdatePSResource.cs @@ -16,7 +16,6 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets /// It updates an already installed package based on the -Name parameter argument. /// It does not return an object. Other parameters allow the package to be updated to be further filtered. /// - [Cmdlet(VerbsData.Update, "PSResource", SupportsShouldProcess = true)] diff --git a/src/code/Utils.cs b/src/code/Utils.cs index d2cf24b03..c861e6a17 100644 --- a/src/code/Utils.cs +++ b/src/code/Utils.cs @@ -4,14 +4,12 @@ using System; using System.Collections; using System.Collections.Generic; -using static System.Environment; using System.IO; using System.Linq; using System.Management.Automation; using System.Management.Automation.Language; using System.Runtime.InteropServices; using NuGet.Versioning; -using System.Globalization; namespace Microsoft.PowerShell.PowerShellGet.UtilClasses { @@ -425,13 +423,13 @@ private static void GetStandardPlatformPaths( if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { string powerShellType = (psCmdlet.Host.Version >= PSVersion6) ? "PowerShell" : "WindowsPowerShell"; - myDocumentsPath = Path.Combine(Environment.GetFolderPath(SpecialFolder.MyDocuments), powerShellType); - programFilesPath = Path.Combine(Environment.GetFolderPath(SpecialFolder.ProgramFiles), powerShellType); + myDocumentsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), powerShellType); + programFilesPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), powerShellType); } else { // paths are the same for both Linux and macOS - myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(SpecialFolder.LocalApplicationData), "powershell"); + myDocumentsPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "powershell"); programFilesPath = System.IO.Path.Combine("/usr", "local", "share", "powershell"); } } @@ -453,9 +451,10 @@ public static bool TryParseModuleManifest( if (moduleFileInfo.EndsWith(".psd1", StringComparison.OrdinalIgnoreCase)) { // Parse the module manifest - System.Management.Automation.Language.Token[] tokens; - ParseError[] errors; - var ast = Parser.ParseFile(moduleFileInfo, out tokens, out errors); + var ast = Parser.ParseFile( + moduleFileInfo, + out Token[] tokens, + out ParseError[] errors); if (errors.Length > 0) {