diff --git a/src/PowerShellGet.psd1 b/src/PowerShellGet.psd1
index 4029ab2bf..b98d29797 100644
--- a/src/PowerShellGet.psd1
+++ b/src/PowerShellGet.psd1
@@ -21,10 +21,13 @@
'Register-PSResourceRepository',
'Save-PSResource',
'Set-PSResourceRepository',
+ 'New-PSScriptFileInfo',
'Publish-PSResource',
+ 'Test-PSScriptFileInfo',
'Uninstall-PSResource',
'Unregister-PSResourceRepository',
- 'Update-PSResource')
+ 'Update-PSResource',
+ 'Update-PSScriptFileInfo')
VariablesToExport = 'PSGetPath'
AliasesToExport = @('inmo', 'fimo', 'upmo', 'pumo')
diff --git a/src/code/NewPSScriptFileInfo.cs b/src/code/NewPSScriptFileInfo.cs
new file mode 100644
index 000000000..8061688a1
--- /dev/null
+++ b/src/code/NewPSScriptFileInfo.cs
@@ -0,0 +1,259 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Management.Automation;
+using Microsoft.PowerShell.Commands;
+using Microsoft.PowerShell.PowerShellGet.UtilClasses;
+
+namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
+{
+ ///
+ /// Creates a new .ps1 file with script information required for publishing a script.
+ ///
+ [Cmdlet(VerbsCommon.New, "PSScriptFileInfo")]
+ public sealed class NewPSScriptFileInfo : PSCmdlet
+ {
+ #region Parameters
+
+ ///
+ /// The path the .ps1 script info file will be created at.
+ ///
+ [Parameter(Position = 0, Mandatory = true)]
+ [ValidateNotNullOrEmpty]
+ public string FilePath { get; set; }
+
+ ///
+ /// The version of the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Version { get; set; }
+
+ ///
+ /// The author of the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Author { get; set; }
+
+ ///
+ /// The description of the script.
+ ///
+ [Parameter(Mandatory = true)]
+ [ValidateNotNullOrEmpty()]
+ public string Description { get; set; }
+
+ ///
+ /// A unique identifier for the script. The GUID can be used to distinguish among scripts with the same name.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public Guid Guid { get; set; }
+
+ ///
+ /// The name of the company owning the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string CompanyName { get; set; }
+
+ ///
+ /// The copyright statement for the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Copyright { get; set; }
+
+ ///
+ /// The list of modules required by the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public Hashtable[] RequiredModules { get; set; }
+
+ ///
+ /// The list of external module dependencies taken by this script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] ExternalModuleDependencies { get; set; }
+
+ ///
+ /// The list of scripts required by the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] RequiredScripts { get; set; }
+
+ ///
+ /// The list of external script dependencies taken by this script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] ExternalScriptDependencies { get; set; }
+
+ ///
+ /// The tags associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] Tags { get; set; }
+
+ ///
+ /// The Uri for the project associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string ProjectUri { get; set; }
+
+ ///
+ /// The Uri for the license associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string LicenseUri { get; set; }
+
+ ///
+ /// The Uri for the icon associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string IconUri { get; set; }
+
+ ///
+ /// The release notes for the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string ReleaseNotes { get; set; }
+
+ ///
+ /// The private data associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string PrivateData { get; set; }
+
+ ///
+ /// If used with Path parameter and .ps1 file specified at the path exists, it rewrites the file.
+ ///
+ [Parameter]
+ public SwitchParameter Force { get; set; }
+
+ #endregion
+
+ #region Methods
+
+ protected override void EndProcessing()
+ {
+ // validate Uri related parameters passed in as strings
+ Uri projectUri = null;
+ if (!String.IsNullOrEmpty(ProjectUri) && !Utils.TryCreateValidUri(uriString: ProjectUri,
+ cmdletPassedIn: this,
+ uriResult: out projectUri,
+ errorRecord: out ErrorRecord projectErrorRecord))
+ {
+ ThrowTerminatingError(projectErrorRecord);
+ }
+
+ Uri licenseUri = null;
+ if (!String.IsNullOrEmpty(LicenseUri) && !Utils.TryCreateValidUri(uriString: LicenseUri,
+ cmdletPassedIn: this,
+ uriResult: out licenseUri,
+ errorRecord: out ErrorRecord licenseErrorRecord))
+ {
+ ThrowTerminatingError(licenseErrorRecord);
+ }
+
+ Uri iconUri = null;
+ if (!String.IsNullOrEmpty(IconUri) && !Utils.TryCreateValidUri(uriString: IconUri,
+ cmdletPassedIn: this,
+ uriResult: out iconUri,
+ errorRecord: out ErrorRecord iconErrorRecord))
+ {
+ ThrowTerminatingError(iconErrorRecord);
+ }
+
+ if (!FilePath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
+ {
+ var exMessage = "Path needs to end with a .ps1 file. Example: C:/Users/john/x/MyScript.ps1";
+ var ex = new ArgumentException(exMessage);
+ var InvalidPathError = new ErrorRecord(ex, "InvalidPath", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidPathError);
+ }
+
+ var resolvedFilePath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(FilePath);
+ if (String.IsNullOrEmpty(resolvedFilePath))
+ {
+ var exMessage = "Error: Could not resolve provided Path argument into a single path.";
+ var ex = new PSArgumentException(exMessage);
+ var InvalidPathArgumentError = new ErrorRecord(ex, "InvalidPathArgumentError", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidPathArgumentError);
+ }
+
+ if (File.Exists(resolvedFilePath) && !Force)
+ {
+ // .ps1 file at specified location already exists and Force parameter isn't used to rewrite the file
+ var exMessage = ".ps1 file at specified path already exists. Specify a different location or use -Force parameter to overwrite the .ps1 file.";
+ var ex = new ArgumentException(exMessage);
+ var ScriptAtPathAlreadyExistsError = new ErrorRecord(ex, "ScriptAtPathAlreadyExists", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(ScriptAtPathAlreadyExistsError);
+ }
+
+ ModuleSpecification[] validatedRequiredModuleSpecifications = new ModuleSpecification[]{};
+ if (RequiredModules != null && RequiredModules.Length > 0)
+ {
+ if (!Utils.TryCreateModuleSpecification(
+ moduleSpecHashtables: RequiredModules,
+ out validatedRequiredModuleSpecifications,
+ out ErrorRecord[] moduleSpecErrors))
+ {
+ foreach (ErrorRecord err in moduleSpecErrors)
+ {
+ WriteError(err);
+ }
+
+ return;
+ }
+ }
+
+ PSScriptFileInfo scriptInfo = new PSScriptFileInfo(
+ version: Version,
+ guid: Guid,
+ author: Author,
+ companyName: CompanyName,
+ copyright: Copyright,
+ tags: Tags,
+ licenseUri: licenseUri,
+ projectUri: projectUri,
+ iconUri: iconUri,
+ requiredModules: validatedRequiredModuleSpecifications,
+ externalModuleDependencies: ExternalModuleDependencies,
+ requiredScripts: RequiredScripts,
+ externalScriptDependencies: ExternalScriptDependencies,
+ releaseNotes: ReleaseNotes,
+ privateData: PrivateData,
+ description: Description,
+ endOfFileContents: String.Empty);
+
+ if (!scriptInfo.TryCreateScriptFileInfoString(
+ pSScriptFileString: out string psScriptFileContents,
+ errors: out ErrorRecord[] errors))
+ {
+ foreach (ErrorRecord err in errors)
+ {
+ WriteError(err);
+ }
+
+ return;
+ }
+
+ File.WriteAllText(resolvedFilePath, psScriptFileContents);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/code/PSScriptFileInfo.cs b/src/code/PSScriptFileInfo.cs
new file mode 100644
index 000000000..065c3aef0
--- /dev/null
+++ b/src/code/PSScriptFileInfo.cs
@@ -0,0 +1,1183 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Management.Automation;
+using System.Management.Automation.Language;
+using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
+using System.Linq;
+using System.Collections.ObjectModel;
+using Microsoft.PowerShell.Commands;
+using NuGet.Versioning;
+
+namespace Microsoft.PowerShell.PowerShellGet.UtilClasses
+{
+ ///
+ /// This class contains information for a PSScriptFileInfo (representing a .ps1 file contents).
+ ///
+ public sealed class PSScriptFileInfo
+ {
+
+ #region Properties
+
+ ///
+ /// the version of the script.
+ ///
+ public NuGetVersion Version { get; private set; }
+
+ ///
+ /// the GUID for the script.
+ ///
+ public Guid Guid { get; private set; }
+
+ ///
+ /// the author for the script.
+ ///
+ public string Author { get; private set; }
+
+ ///
+ /// the name of the company owning the script.
+ ///
+ public string CompanyName { get; private set; }
+
+ ///
+ /// the copyright statement for the script.
+ ///
+ public string Copyright { get; private set; }
+
+ ///
+ /// the tags for the script.
+ ///
+ public string[] Tags { get; private set; }
+
+ ///
+ /// the Uri for the license of the script.
+ ///
+ public Uri LicenseUri { get; private set; }
+
+ ///
+ /// the Uri for the project relating to the script.
+ ///
+ public Uri ProjectUri { get; private set; }
+
+ ///
+ /// the Uri for the icon relating to the script.
+ ///
+ public Uri IconUri { get; private set; }
+
+ ///
+ /// The list of modules required by the script.
+ /// Hashtable keys: GUID, MaxVersion, ModuleName (Required), RequiredVersion, Version.
+ ///
+ public ModuleSpecification[] RequiredModules { get; private set; } = new ModuleSpecification[]{};
+
+ ///
+ /// the list of external module dependencies for the script.
+ ///
+ public string[] ExternalModuleDependencies { get; private set; } = new string[]{};
+
+ ///
+ /// the list of required scripts for the parent script.
+ ///
+ public string[] RequiredScripts { get; private set; } = new string[]{};
+
+ ///
+ /// the list of external script dependencies for the script.
+ ///
+ public string[] ExternalScriptDependencies { get; private set; } = new string[]{};
+
+ ///
+ /// the release notes relating to the script.
+ ///
+ public string ReleaseNotes { get; private set; } = String.Empty;
+
+ ///
+ /// The private data associated with the script.
+ ///
+ public string PrivateData { get; private set; }
+
+ ///
+ /// The description of the script.
+ ///
+ public string Description { get; private set; }
+
+ ///
+ /// End of file contents for the .ps1 file.
+ ///
+ public string EndOfFileContents { get; private set; } = String.Empty;
+
+ ///
+ /// The synopsis of the script.
+ ///
+ public string Synopsis { get; private set; }
+
+ ///
+ /// The example(s) relating to the script's usage.
+ ///
+ public string[] Example { get; private set; } = new string[]{};
+
+ ///
+ /// The inputs to the script.
+ ///
+ public string[] Inputs { get; private set; } = new string[]{};
+
+ ///
+ /// The outputs to the script.
+ ///
+ public string[] Outputs { get; private set; } = new string[]{};
+
+ ///
+ /// The notes for the script.
+ ///
+ public string[] Notes { get; private set; } = new string[]{};
+
+ ///
+ /// The links for the script.
+ ///
+ public string[] Links { get; private set; } = new string[]{};
+
+ ///
+ /// The components for the script.
+ ///
+ public string[] Component { get; private set; } = new string[]{};
+
+ ///
+ /// The roles for the script.
+ ///
+ public string[] Role { get; private set; } = new string[]{};
+
+ ///
+ /// The functionality components for the script.
+ ///
+ public string[] Functionality { get; private set; } = new string[]{};
+
+ #endregion
+
+ #region Private Members
+
+ private const string signatureStartString = "# SIG # Begin signature block";
+
+ #endregion
+
+ #region Constructor
+
+ private PSScriptFileInfo() {}
+ public PSScriptFileInfo(
+ string version,
+ Guid guid,
+ string author,
+ string companyName,
+ string copyright,
+ string[] tags,
+ Uri licenseUri,
+ Uri projectUri,
+ Uri iconUri,
+ ModuleSpecification[] requiredModules,
+ string[] externalModuleDependencies,
+ string[] requiredScripts,
+ string[] externalScriptDependencies,
+ string releaseNotes,
+ string privateData,
+ string description,
+ string endOfFileContents)
+ {
+ if (String.IsNullOrEmpty(author))
+ {
+ author = Environment.UserName;
+ }
+
+ Version = !String.IsNullOrEmpty(version) ? new NuGetVersion (version) : new NuGetVersion("1.0.0.0");
+ Guid = (guid == null || guid == Guid.Empty) ? Guid.NewGuid() : guid;
+ Author = !String.IsNullOrEmpty(author) ? author : Environment.UserName;
+ CompanyName = companyName;
+ Copyright = copyright;
+ Tags = tags ?? Utils.EmptyStrArray;
+ LicenseUri = licenseUri;
+ ProjectUri = projectUri;
+ IconUri = iconUri;
+ RequiredModules = requiredModules ?? new ModuleSpecification[]{};
+ ExternalModuleDependencies = externalModuleDependencies ?? Utils.EmptyStrArray;
+ RequiredScripts = requiredScripts ?? Utils.EmptyStrArray;
+ ExternalScriptDependencies = externalScriptDependencies ?? Utils.EmptyStrArray;
+ ReleaseNotes = releaseNotes;
+ PrivateData = privateData;
+ Description = description;
+ EndOfFileContents = endOfFileContents;
+ }
+
+ #endregion
+
+ #region Internal Static Methods
+
+ internal static bool TryParseScriptFile2(
+ string scriptFileInfoPath,
+ out Hashtable parsedScriptMetadata,
+ out ErrorRecord error
+ )
+ {
+ parsedScriptMetadata = new Hashtable();
+ error = null;
+
+ string[] fileContents = File.ReadAllLines(scriptFileInfoPath);
+ List psScriptInfoCommentContent = new List();
+ List helpInfoCommentContent = new List();
+ List requiresContent = new List();
+ string[] remainingFileContentArray;
+
+ bool gotEndToPSSCriptInfoContent = false;
+ bool gotEndToHelpInfoContent = false;
+
+ int i = 0;
+ int endOfFileContentsStartIndex = 0;
+ while (i < fileContents.Length)
+ {
+ string line = fileContents[i];
+
+ if (line.StartsWith("<#PSScriptInfo"))
+ {
+ int j = i + 1; // start at the next line
+ // keep grabbing lines until we get to closing #>
+ while (j < fileContents.Length)
+ {
+ string blockLine = fileContents[j];
+ if (blockLine.StartsWith("#>"))
+ {
+ gotEndToPSSCriptInfoContent = true;
+ i = j + 1;
+ break;
+ }
+
+ psScriptInfoCommentContent.Add(blockLine);
+ j++;
+ }
+
+ if (!gotEndToPSSCriptInfoContent)
+ {
+ var message = String.Format("Could not parse '{0}' as a PowerShell script file due to missing the closing '#>' for <#PSScriptInfo comment block", scriptFileInfoPath);
+ var ex = new InvalidOperationException(message);
+ error = new ErrorRecord(ex, "MissingEndBracketToPSScriptInfoParseError", ErrorCategory.ParserError, null);
+ return false;
+ }
+ }
+ else if (line.StartsWith("<#"))
+ {
+ // we assume the next comment block should be the help comment block (containing description)
+ // keep grabbing lines until we get to closing #>
+ int j = i + 1;
+ while (j < fileContents.Length)
+ {
+ string blockLine = fileContents[j];
+ if (blockLine.StartsWith("#>"))
+ {
+ gotEndToHelpInfoContent = true;
+ i = j + 1;
+ endOfFileContentsStartIndex = i;
+ break;
+ }
+
+ helpInfoCommentContent.Add(blockLine);
+ j++;
+ }
+
+ if (!gotEndToHelpInfoContent)
+ {
+ var message = String.Format("Could not parse '{0}' as a PowerShell script file due to missing the closing '#>' for HelpInfo comment block", scriptFileInfoPath);
+ var ex = new InvalidOperationException(message);
+ error = new ErrorRecord(ex, "MissingEndBracketToHelpInfoCommentParseError", ErrorCategory.ParserError, null);
+ return false;
+ }
+ }
+ else if (line.StartsWith("#Requires"))
+ {
+ requiresContent.Add(line);
+ i++;
+ }
+ else if (endOfFileContentsStartIndex != 0)
+ {
+ break;
+ }
+ else
+ {
+ // this would be newlines between blocks, or if there was other (unexpected) data between PSScriptInfo, Requires, and HelpInfo blocks
+ i++;
+ }
+ }
+
+ if (endOfFileContentsStartIndex != 0 && (endOfFileContentsStartIndex < fileContents.Length))
+ {
+ // from this line to fileContents.Length is the endOfFileContents
+ // save it to append to end of file during Update
+ remainingFileContentArray = new string[fileContents.Length - endOfFileContentsStartIndex];
+ Array.Copy(fileContents, endOfFileContentsStartIndex, remainingFileContentArray, 0, (fileContents.Length - endOfFileContentsStartIndex));
+ }
+
+ return true;
+ }
+
+ ///
+ /// Parses content of .ps1 file into a hashtable.
+ ///
+ internal static bool TryParseScriptFile(
+ string scriptFileInfoPath,
+ out Hashtable parsedScriptMetadata,
+ out string endOfFileContents,
+ out ErrorRecord[] errors)
+ {
+ errors = new ErrorRecord[]{};
+ parsedScriptMetadata = new Hashtable(StringComparer.InvariantCultureIgnoreCase);
+ endOfFileContents = String.Empty;
+ List errorsList = new List();
+
+ // Parse the script file
+ var ast = Parser.ParseFile(
+ scriptFileInfoPath,
+ out Token[] tokens,
+ out ParseError[] parserErrors);
+
+ if (parserErrors.Length > 0)
+ {
+ bool parseSuccessful = true;
+ foreach (ParseError err in parserErrors)
+ {
+ // we ignore WorkFlowNotSupportedInPowerShellCore errors, as this is common in scripts currently on PSGallery
+ if (!String.Equals(err.ErrorId, "WorkflowNotSupportedInPowerShellCore", StringComparison.OrdinalIgnoreCase))
+ {
+ var message = String.Format("Could not parse '{0}' as a PowerShell script file due to {1}.", scriptFileInfoPath, err.Message);
+ var ex = new InvalidOperationException(message);
+ var psScriptFileParseError = new ErrorRecord(ex, err.ErrorId, ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptFileParseError);
+ parseSuccessful = false;
+ }
+ }
+
+ if (!parseSuccessful)
+ {
+ errors = errorsList.ToArray();
+ return parseSuccessful;
+ }
+ }
+
+ if (ast == null)
+ {
+ var parseFileException = new InvalidOperationException(
+ message: "Cannot parse .ps1 file", innerException: new ParseException(
+ message: "Parsed AST was null for .ps1 file"));
+ var astCouldNotBeCreatedError = new ErrorRecord(parseFileException, "ASTCouldNotBeCreated", ErrorCategory.ParserError, null);
+
+ errorsList.Add(astCouldNotBeCreatedError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ // Get .DESCRIPTION property (required property), by accessing the Help block which contains .DESCRIPTION
+ CommentHelpInfo scriptCommentInfo = ast.GetHelpContent();
+ if (scriptCommentInfo == null)
+ {
+ var message = String.Format("PSScript file is missing the required Description comment block in the script contents.");
+ var ex = new ArgumentException(message);
+ var psScriptMissingHelpContentCommentBlockError = new ErrorRecord(ex, "PSScriptMissingHelpContentCommentBlock", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptMissingHelpContentCommentBlockError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ if (!String.IsNullOrEmpty(scriptCommentInfo.Description) && !scriptCommentInfo.Description.Contains("<#") && !scriptCommentInfo.Description.Contains("#>"))
+ {
+ parsedScriptMetadata.Add("DESCRIPTION", scriptCommentInfo.Description);
+ }
+ else
+ {
+ var message = String.Format("PSScript is missing the required Description property or Description value contains '<#' or '#>' which is invalid");
+ var ex = new ArgumentException(message);
+ var psScriptMissingDescriptionOrInvalidPropertyError = new ErrorRecord(ex, "psScriptDescriptionMissingOrInvalidDescription", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptMissingDescriptionOrInvalidPropertyError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ // get .REQUIREDMODULES property, by accessing the System.Management.Automation.Language.ScriptRequirements object ScriptRequirements.RequiredModules property
+ ScriptRequirements parsedScriptRequirements = ast.ScriptRequirements;
+ ReadOnlyCollection parsedModules = new List().AsReadOnly();
+
+ if (parsedScriptRequirements != null && parsedScriptRequirements.RequiredModules != null)
+ {
+ parsedModules = parsedScriptRequirements.RequiredModules;
+ parsedScriptMetadata.Add("REQUIREDMODULES", parsedModules);
+ }
+
+ // Get the block/group comment beginning with <#PSScriptInfo
+ // this contains other script properties, including AUTHOR, VERSION, GUID (which are required properties)
+ List commentTokens = tokens.Where(a => a.Kind == TokenKind.Comment).ToList();
+ string commentPattern = @"^<#PSScriptInfo";
+ Regex rg = new Regex(commentPattern);
+
+ Token psScriptInfoCommentToken = commentTokens.Where(a => rg.IsMatch(a.Extent.Text)).FirstOrDefault();
+ if (psScriptInfoCommentToken == null)
+ {
+ var message = String.Format("PSScriptInfo comment was missing or could not be parsed");
+ var ex = new ArgumentException(message);
+ var psCommentMissingError = new ErrorRecord(ex, "psScriptInfoCommentMissingError", ErrorCategory.ParserError, null);
+ errorsList.Add(psCommentMissingError);
+
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ /**
+ should now have a Token with text like this:
+
+ <#PSScriptInfo
+
+ .VERSION 1.0
+
+ .GUID 3951be04-bd06-4337-8dc3-a620bf539fbd
+
+ .AUTHOR
+
+ .COMPANYNAME
+
+ .COPYRIGHT
+
+ .TAGS
+
+ .LICENSEURI
+
+ .PROJECTURI
+
+ .ICONURI
+
+ .EXTERNALMODULEDEPENDENCIES
+
+ .REQUIREDSCRIPTS
+
+ .EXTERNALSCRIPTDEPENDENCIES
+
+ .RELEASENOTES
+
+
+ .PRIVATEDATA
+
+ #>
+ */
+
+ string[] newlineDelimeters = new string[]{"\r\n", "\n"};
+ string[] commentLines = psScriptInfoCommentToken.Text.Split(newlineDelimeters, StringSplitOptions.RemoveEmptyEntries);
+ string keyName = String.Empty;
+ string value = String.Empty;
+
+ /**
+ If comment line count is not more than two, it doesn't have the any metadata property and
+ comment block would look like:
+
+ <#PSScriptInfo
+ #>
+
+ */
+
+ if (commentLines.Count() <= 2)
+ {
+ var message = String.Format("PSScriptInfo comment block is empty and did not contain any metadata");
+ var ex = new ArgumentException(message);
+ var psScriptInfoCommentEmptyError = new ErrorRecord(ex, "psScriptInfoCommentEmpty", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptInfoCommentEmptyError);
+
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ GetMetadataFromCommentLines(commentLines, ref parsedScriptMetadata);
+
+ // get end of file contents
+ string[] totalFileContents = File.ReadAllLines(scriptFileInfoPath);
+ var contentAfterAndIncludingDescription = totalFileContents.SkipWhile(x => !x.Contains(".DESCRIPTION")).ToList();
+ endOfFileContents = String.Join("\n", contentAfterAndIncludingDescription.SkipWhile(x => !x.Contains("#>")).Skip(1).ToArray());
+
+ return true;
+ }
+
+ ///
+ /// Takes hashtable (containing parsed .ps1 file content properties) and validates required properties are present.
+ ///
+ private static bool TryValidateScript(
+ Hashtable parsedScriptMetadata,
+ out ErrorRecord[] errors)
+ {
+ // required properties for script file (.ps1 file) are: Author, Version, Guid, Description
+ // Description gets validated in TryParseScript() when getting the property
+
+ List errorsList = new List();
+
+ if (!parsedScriptMetadata.ContainsKey("VERSION") || String.IsNullOrEmpty((string) parsedScriptMetadata["VERSION"]))
+ {
+ var message = String.Format("PSScript file is missing the required Version property");
+ var ex = new ArgumentException(message);
+ var psScriptMissingVersionError = new ErrorRecord(ex, "psScriptMissingVersion", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptMissingVersionError);
+ }
+
+ if (!parsedScriptMetadata.ContainsKey("AUTHOR") || String.IsNullOrEmpty((string) parsedScriptMetadata["AUTHOR"]))
+ {
+ var message = String.Format("PSScript file is missing the required Author property");
+ var ex = new ArgumentException(message);
+ var psScriptMissingAuthorError = new ErrorRecord(ex, "psScriptMissingAuthor", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptMissingAuthorError);
+ }
+
+ if (!parsedScriptMetadata.ContainsKey("GUID") || String.IsNullOrEmpty((string) parsedScriptMetadata["GUID"]))
+ {
+ var message = String.Format("PSScript file is missing the required Guid property");
+ var ex = new ArgumentException(message);
+ var psScriptMissingGuidError = new ErrorRecord(ex, "psScriptMissingGuid", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptMissingGuidError);
+ }
+
+ errors = errorsList.ToArray();
+ return (errors.Length == 0);
+ }
+
+ ///
+ /// Tests the contents of the .ps1 file at the provided path.
+ ///
+ internal static bool TryParseScriptIntoPSScriptInfo(
+ string scriptFileInfoPath,
+ out PSScriptFileInfo parsedScript,
+ out ErrorRecord[] errors,
+ out string[] verboseMsgs)
+ {
+ parsedScript = null;
+ errors = new ErrorRecord[]{};
+ verboseMsgs = new string[]{};
+ List errorsList = new List();
+ List verboseMsgsList = new List();
+
+ if (!scriptFileInfoPath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
+ {
+ var message = String.Format("File passed in: {0} does not have a .ps1 extension as required", scriptFileInfoPath);
+ var ex = new ArgumentException(message);
+ var psScriptFileParseError = new ErrorRecord(ex, "ps1FileRequiredError", ErrorCategory.ParserError, null);
+ errorsList.Add(psScriptFileParseError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ if (!TryParseScriptFile(
+ scriptFileInfoPath: scriptFileInfoPath,
+ parsedScriptMetadata: out Hashtable parsedScriptMetadata,
+ endOfFileContents: out string endofFileContents,
+ errors: out ErrorRecord[] parseErrors
+ ))
+ {
+ errorsList.AddRange(parseErrors);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ TryParseScriptFile2(scriptFileInfoPath, out Hashtable _, out ErrorRecord _);
+
+ // at this point we've parsed into hashtable, now validate hashtable has properties we need:
+ // Author, Version, Guid, Description (but Description is already validated)
+
+ if (!TryValidateScript(
+ parsedScriptMetadata: parsedScriptMetadata,
+ errors: out ErrorRecord[] validationErrors))
+ {
+ errorsList.AddRange(validationErrors);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ // at this point, we've parsed into hashtable AND validated we have all required properties for .ps1
+ // now create instance of and populate PSScriptFileInfo
+ try
+ {
+ char[] spaceDelimeter = new char[]{' '};
+
+ Guid parsedGuid = new Guid((string) parsedScriptMetadata["GUID"]);
+ string parsedVersion = (string) parsedScriptMetadata["VERSION"];
+ string parsedAuthor = (string) parsedScriptMetadata["AUTHOR"];
+ string parsedDescription = (string) parsedScriptMetadata["DESCRIPTION"];
+
+
+ string parsedCompanyName = (string) parsedScriptMetadata["COMPANYNAME"] ?? String.Empty;
+ string parsedCopyright = (string) parsedScriptMetadata["COPYRIGHT"] ?? String.Empty;
+ string parsedPrivateData = (string) parsedScriptMetadata["PRIVATEDATA"] ?? String.Empty;
+ string parsedReleaseNotes = (string) parsedScriptMetadata["RELEASENOTES"] ?? String.Empty;
+
+ string[] parsedTags = Utils.GetStringArrayFromString(spaceDelimeter, (string) parsedScriptMetadata["TAGS"]);
+ string[] parsedExternalModuleDependencies = Utils.GetStringArrayFromString(spaceDelimeter, (string) parsedScriptMetadata["EXTERNALMODULEDEPENDENCIES"]);
+ string[] parsedRequiredScripts = Utils.GetStringArrayFromString(spaceDelimeter, (string) parsedScriptMetadata["REQUIREDSCRIPTS"]);
+ string[] parsedExternalScriptDependencies = Utils.GetStringArrayFromString(spaceDelimeter, (string) parsedScriptMetadata["EXTERNALSCRIPTDEPENDENCIES"]);
+
+ ReadOnlyCollection parsedModules = (ReadOnlyCollection) parsedScriptMetadata["REQUIREDMODULES"] ??
+ new ReadOnlyCollection(new List());
+
+ ModuleSpecification[] parsedModulesArray = parsedModules.Count() == 0 ? new ModuleSpecification[]{} : parsedModules.ToArray();
+
+ Uri parsedLicenseUri = null;
+ if (!String.IsNullOrEmpty((string) parsedScriptMetadata["LICENSEURI"]))
+ {
+ if (!Uri.TryCreate((string) parsedScriptMetadata["LICENSEURI"], UriKind.Absolute, out parsedLicenseUri))
+ {
+ verboseMsgsList.Add($"LicenseUri property {(string) parsedScriptMetadata["LICENSEURI"]} could not be created as a Uri");
+ }
+ }
+
+ Uri parsedProjectUri = null;
+ if (!String.IsNullOrEmpty((string) parsedScriptMetadata["PROJECTURI"]))
+ {
+ if (!Uri.TryCreate((string) parsedScriptMetadata["PROJECTURI"], UriKind.Absolute, out parsedProjectUri))
+ {
+ verboseMsgsList.Add($"ProjectUri property {(string) parsedScriptMetadata["PROJECTURI"]} could not be created as Uri");
+ }
+ }
+
+ Uri parsedIconUri = null;
+ if (!String.IsNullOrEmpty((string) parsedScriptMetadata["ICONURI"]))
+ {
+ if (!Uri.TryCreate((string) parsedScriptMetadata["ICONURI"], UriKind.Absolute, out parsedIconUri))
+ {
+ verboseMsgsList.Add($"IconUri property {(string) parsedScriptMetadata["ICONURI"]} could not be created as Uri");
+ }
+ }
+
+ // parsedScriptMetadata should contain all keys, but values may be empty (i.e empty array, String.empty)
+ parsedScript = new PSScriptFileInfo(
+ version: parsedVersion,
+ guid: parsedGuid,
+ author: parsedAuthor,
+ companyName: parsedCompanyName,
+ copyright: parsedCopyright,
+ tags: parsedTags,
+ licenseUri: parsedLicenseUri,
+ projectUri: parsedProjectUri,
+ iconUri: parsedIconUri,
+ requiredModules: parsedModulesArray,
+ externalModuleDependencies: parsedExternalModuleDependencies,
+ requiredScripts: parsedRequiredScripts,
+ externalScriptDependencies: parsedExternalScriptDependencies,
+ releaseNotes: parsedReleaseNotes,
+ privateData: parsedPrivateData,
+ description: parsedDescription,
+ endOfFileContents: endofFileContents);
+ }
+ catch (Exception e)
+ {
+ var message = String.Format("PSScriptFileInfo object could not be created from passed in file due to {0}", e.Message);
+ var ex = new ArgumentException(message);
+ var PSScriptFileInfoObjectNotCreatedFromFileError = new ErrorRecord(ex, "PSScriptFileInfoObjectNotCreatedFromFile", ErrorCategory.ParserError, null);
+ errorsList.Add(PSScriptFileInfoObjectNotCreatedFromFileError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Updates the contents of the .ps1 file at the provided path with the properties provided
+ /// and writes new updated script file contents to a string and updates the original PSScriptFileInfo object.
+ ///
+ internal static bool TryUpdateScriptFileContents(
+ PSScriptFileInfo scriptInfo,
+ out string updatedPSScriptFileContents,
+ out ErrorRecord[] errors,
+ string version,
+ Guid guid,
+ string author,
+ string companyName,
+ string copyright,
+ string[] tags,
+ Uri licenseUri,
+ Uri projectUri,
+ Uri iconUri,
+ ModuleSpecification[] requiredModules,
+ string[] externalModuleDependencies,
+ string[] requiredScripts,
+ string[] externalScriptDependencies,
+ string releaseNotes,
+ string privateData,
+ string description)
+ {
+ updatedPSScriptFileContents = String.Empty;
+ errors = new ErrorRecord[]{};
+ List errorsList = new List();
+
+ if (scriptInfo == null)
+ {
+ throw new ArgumentNullException(nameof(scriptInfo));
+ }
+
+ // create new PSScriptFileInfo with updated fields
+ if (!String.IsNullOrEmpty(version))
+ {
+ if (!NuGetVersion.TryParse(version, out NuGetVersion updatedVersion))
+ {
+ var message = String.Format("Version provided for update could not be parsed successfully into NuGetVersion");
+ var ex = new ArgumentException(message);
+ var versionParseIntoNuGetVersionError = new ErrorRecord(ex, "VersionParseIntoNuGetVersion", ErrorCategory.ParserError, null);
+ errorsList.Add(versionParseIntoNuGetVersionError);
+ errors = errorsList.ToArray();
+ return false;
+ }
+ scriptInfo.Version = updatedVersion;
+ }
+
+ if (guid != Guid.Empty)
+ {
+ scriptInfo.Guid = guid;
+ }
+
+ if (!String.IsNullOrEmpty(author))
+ {
+ scriptInfo.Author = author;
+ }
+
+ if (!String.IsNullOrEmpty(companyName)){
+ scriptInfo.CompanyName = companyName;
+ }
+
+ if (!String.IsNullOrEmpty(copyright)){
+ scriptInfo.Copyright = copyright;
+ }
+
+ if (tags != null && tags.Length != 0){
+ scriptInfo.Tags = tags;
+ }
+
+ if (licenseUri != null && !licenseUri.Equals(default(Uri))){
+ scriptInfo.LicenseUri = licenseUri;
+ }
+
+ if (projectUri != null && !projectUri.Equals(default(Uri))){
+ scriptInfo.ProjectUri = projectUri;
+ }
+
+ if (iconUri != null && !iconUri.Equals(default(Uri))){
+ scriptInfo.IconUri = iconUri;
+ }
+
+ if (requiredModules != null && requiredModules.Length != 0){
+ scriptInfo.RequiredModules = requiredModules;
+ }
+
+ if (externalModuleDependencies != null && externalModuleDependencies.Length != 0){
+ scriptInfo.ExternalModuleDependencies = externalModuleDependencies;
+ }
+
+ if (requiredScripts != null && requiredScripts.Length != 0)
+ {
+ scriptInfo.RequiredScripts = requiredScripts;
+ }
+
+ if (externalScriptDependencies != null && externalScriptDependencies.Length != 0){
+ scriptInfo.ExternalScriptDependencies = externalScriptDependencies;
+ }
+
+ if (!String.IsNullOrEmpty(releaseNotes))
+ {
+ scriptInfo.ReleaseNotes = releaseNotes;
+ }
+
+ if (!String.IsNullOrEmpty(privateData))
+ {
+ scriptInfo.PrivateData = privateData;
+ }
+
+ if (!String.IsNullOrEmpty(description))
+ {
+ scriptInfo.Description = description;
+ }
+
+ // create string contents for .ps1 file
+ if (!scriptInfo.TryCreateScriptFileInfoString(
+ pSScriptFileString: out string psScriptFileContents,
+ errors: out ErrorRecord[] createFileContentErrors))
+ {
+ errorsList.AddRange(createFileContentErrors);
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+ updatedPSScriptFileContents = psScriptFileContents;
+ return true;
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Create .ps1 file contents as a string from PSScriptFileInfo object's properties
+ /// end of file contents are not yet added to the string contents of the file.
+ ///
+ internal bool TryCreateScriptFileInfoString(
+ out string pSScriptFileString, // this is the string with the contents we want to put in the new ps1 file
+ out ErrorRecord[] errors)
+ {
+ errors = new ErrorRecord[]{};
+ List errorsList = new List();
+
+ pSScriptFileString = String.Empty;
+ bool fileContentsSuccessfullyCreated = false;
+
+ // this string/block is required
+ // this can only have one error (i.e Author or Version is missing)
+ if (!GetPSScriptInfoString(
+ pSScriptInfoString: out string psScriptInfoCommentString,
+ out ErrorRecord[] scriptInfoErrors))
+ {
+ if (scriptInfoErrors.Length != 0)
+ {
+ errors = scriptInfoErrors.ToArray();
+ }
+
+ return fileContentsSuccessfullyCreated;
+ }
+
+ pSScriptFileString = psScriptInfoCommentString;
+
+ // populating this block is not required to fulfill .ps1 script requirements.
+ // this won't report any errors.
+ GetRequiresString(psRequiresString: out string psRequiresString);
+ if (!String.IsNullOrEmpty(psRequiresString))
+ {
+ pSScriptFileString += "\n";
+ pSScriptFileString += psRequiresString;
+ }
+
+ // this string/block will contain Description, which is required
+ // this can only have one error (i.e Description is missing)
+ if (!GetScriptCommentHelpInfo(
+ psHelpInfo: out string psHelpInfo,
+ error: out ErrorRecord commentHelpInfoError))
+ {
+ if (commentHelpInfoError != null)
+ {
+ errorsList.Add(commentHelpInfoError);
+ errors = errorsList.ToArray();
+ }
+
+ pSScriptFileString = String.Empty;
+ return fileContentsSuccessfullyCreated;
+ }
+
+ pSScriptFileString += "\n"; // need a newline after last #> and before <# for script comment block
+ // or else not recongnized as a valid comment help info block when parsing the created ps1 later
+ pSScriptFileString += "\n" + psHelpInfo;
+
+ // at this point either:
+ // have a new script being created without endOfFileContents, or
+ // have a script being updated, and contains no Signature, or contains a Signature but -RemoveSignature was used with cmdlet
+ if (!String.IsNullOrEmpty(EndOfFileContents))
+ {
+ RemoveSignatureString();
+ pSScriptFileString += "\n" + EndOfFileContents;
+ }
+
+ fileContentsSuccessfullyCreated = true;
+ return fileContentsSuccessfullyCreated;
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ ///
+ /// Used when creating .ps1 file's contents.
+ /// This creates the <#PSScriptInfo ... #> comment string.
+ ///
+ private bool GetPSScriptInfoString(
+ out string pSScriptInfoString,
+ out ErrorRecord[] errors)
+ {
+ List errorsList = new List();
+ bool pSScriptInfoSuccessfullyCreated = false;
+ pSScriptInfoString = String.Empty;
+
+ /**
+ PSScriptInfo comment will be in following format:
+ <#PSScriptInfo
+ .VERSION 1.0
+ .GUID 544238e3-1751-4065-9227-be105ff11636
+ .AUTHOR manikb
+ .COMPANYNAME Microsoft Corporation
+ .COPYRIGHT (c) 2015 Microsoft Corporation. All rights reserved.
+ .TAGS Tag1 Tag2 Tag3
+ .LICENSEURI https://contoso.com/License
+ .PROJECTURI https://contoso.com/
+ .ICONURI https://contoso.com/Icon
+ .EXTERNALMODULEDEPENDENCIES ExternalModule1
+ .REQUIREDSCRIPTS Start-WFContosoServer,Stop-ContosoServerScript
+ .EXTERNALSCRIPTDEPENDENCIES Stop-ContosoServerScript
+ .RELEASENOTES
+ contoso script now supports following features
+ Feature 1
+ Feature 2
+ Feature 3
+ Feature 4
+ Feature 5
+ .PRIVATEDATA
+ #>
+ */
+
+ if (String.IsNullOrEmpty(Author))
+ {
+ var exMessage = "Author is missing when creating PSScriptComment info block";
+ var ex = new ArgumentException(exMessage);
+ var authorMissingWhenCreatingPSScriptCommentError = new ErrorRecord(ex, "authorMissingWhenCreatingPSScriptComment", ErrorCategory.InvalidArgument, null);
+ errorsList.Add(authorMissingWhenCreatingPSScriptCommentError);
+ pSScriptInfoSuccessfullyCreated = false;
+ }
+
+ if (String.IsNullOrEmpty(Author))
+ {
+ var exMessage = "Version is missing when creating PSScriptComment info block";
+ var ex = new ArgumentException(exMessage);
+ var versionMissingWhenCreatingPSScriptCommentError = new ErrorRecord(ex, "versionMissingWhenCreatingPSScriptComment", ErrorCategory.InvalidArgument, null);
+ errorsList.Add(versionMissingWhenCreatingPSScriptCommentError);
+ pSScriptInfoSuccessfullyCreated = false;
+ }
+
+ if (String.IsNullOrEmpty(Author))
+ {
+ var exMessage = "Description is missing when creating PSScriptComment info block";
+ var ex = new ArgumentException(exMessage);
+ var descriptionMissingWhenCreatingPSScriptCommentError = new ErrorRecord(ex, "descriptionMissingWhenCreatingPSScriptComment", ErrorCategory.InvalidArgument, null);
+ errorsList.Add(descriptionMissingWhenCreatingPSScriptCommentError);
+ pSScriptInfoSuccessfullyCreated = false;
+ }
+
+ if (Guid == Guid.Empty)
+ {
+ var exMessage = "Guid is missing when creating PSScriptComment info block";
+ var ex = new ArgumentException(exMessage);
+ var guidMissingWhenCreatingPSScriptCommentError = new ErrorRecord(ex, "guidMissingWhenCreatingPSScriptComment", ErrorCategory.InvalidArgument, null);
+ errorsList.Add(guidMissingWhenCreatingPSScriptCommentError);
+ pSScriptInfoSuccessfullyCreated = false;
+ }
+
+ if (pSScriptInfoSuccessfullyCreated)
+ {
+ errors = errorsList.ToArray();
+ return false;
+ }
+
+
+ List psScriptInfoLines = new List();
+
+ psScriptInfoLines.Add("<#PSScriptInfo");
+ psScriptInfoLines.Add(String.Format(".VERSION {0}", Version.ToString()));
+ psScriptInfoLines.Add(String.Format(".GUID {0}", Guid.ToString()));
+ psScriptInfoLines.Add(String.Format(".AUTHOR {0}", Author));
+ psScriptInfoLines.Add(String.Format(".COMPANYNAME {0}", CompanyName));
+ psScriptInfoLines.Add(String.Format(".COPYRIGHT {0}", Copyright));
+ psScriptInfoLines.Add(String.Format(".TAGS {0}", String.Join(" ", Tags)));
+ psScriptInfoLines.Add(String.Format(".LICENSEURI {0}", LicenseUri == null ? String.Empty : LicenseUri.ToString()));
+ psScriptInfoLines.Add(String.Format(".PROJECTURI {0}", ProjectUri == null ? String.Empty : ProjectUri.ToString()));
+ psScriptInfoLines.Add(String.Format(".ICONURI {0}", IconUri == null ? String.Empty : IconUri.ToString()));
+ psScriptInfoLines.Add(String.Format(".EXTERNALMODULEDEPENDENCIES {0}", String.Join(" ", ExternalModuleDependencies)));
+ psScriptInfoLines.Add(String.Format(".REQUIREDSCRIPTS {0}", String.Join(" ", RequiredScripts)));
+ psScriptInfoLines.Add(String.Format(".EXTERNALSCRIPTDEPENDENCIES {0}", String.Join(" ", ExternalScriptDependencies)));
+ psScriptInfoLines.Add(String.Format(".RELEASENOTES\n{0}", ReleaseNotes));
+ psScriptInfoLines.Add(String.Format(".PRIVATEDATA\n{0}", PrivateData));
+ psScriptInfoLines.Add("#>");
+
+ pSScriptInfoString = String.Join("\n\n", psScriptInfoLines);
+ errors = errorsList.ToArray();
+ return true;
+ }
+
+ ///
+ /// Used when creating .ps1 file's contents.
+ /// This creates the #Requires comment string.
+ ///
+ private void GetRequiresString(out string psRequiresString)
+ {
+ psRequiresString = String.Empty;
+
+ if (RequiredModules.Length > 0)
+ {
+ List psRequiresLines = new List();
+ psRequiresLines.Add("\n");
+ foreach (ModuleSpecification moduleSpec in RequiredModules)
+ {
+ psRequiresLines.Add(String.Format("#Requires -Module {0}", moduleSpec.ToString()));
+ }
+
+ psRequiresLines.Add("\n");
+ psRequiresString = String.Join("\n", psRequiresLines);
+ }
+ }
+
+ ///
+ /// Used when creating .ps1 file's contents.
+ /// This creates the help comment string: <# \n .DESCRIPTION{mydescription}\n\n#>
+ ///
+ private bool GetScriptCommentHelpInfo(
+ out string psHelpInfo,
+ out ErrorRecord error)
+ {
+ error = null;
+ psHelpInfo = String.Empty;
+ bool psHelpInfoSuccessfullyCreated = false;
+ List psHelpInfoLines = new List();
+
+ if (String.IsNullOrEmpty(Description))
+ {
+ var exMessage = "PSScript file must contain value for Description. Ensure value for Description is passed in and try again.";
+ var ex = new ArgumentException(exMessage);
+ var PSScriptInfoMissingDescriptionError = new ErrorRecord(ex, "PSScriptInfoMissingDescription", ErrorCategory.InvalidArgument, null);
+ error = PSScriptInfoMissingDescriptionError;
+ return psHelpInfoSuccessfullyCreated;
+ }
+
+ if (StringContainsComment(Description))
+ {
+ var exMessage = "PSScript file's value for Description cannot contain '<#' or '#>'. Pass in a valid value for Description and try again.";
+ var ex = new ArgumentException(exMessage);
+ var DescriptionContainsCommentError = new ErrorRecord(ex, "DescriptionContainsComment", ErrorCategory.InvalidArgument, null);
+ error = DescriptionContainsCommentError;
+ return psHelpInfoSuccessfullyCreated;
+ }
+
+ psHelpInfoSuccessfullyCreated = true;
+ psHelpInfoLines.Add("<#\n");
+ psHelpInfoLines.Add(String.Format(".DESCRIPTION\n{0}", Description));
+
+ if (!String.IsNullOrEmpty(Synopsis))
+ {
+ psHelpInfoLines.Add(String.Format(".SYNOPSIS\n{0}", Synopsis));
+ }
+
+ foreach (string currentExample in Example)
+ {
+ psHelpInfoLines.Add(String.Format(".EXAMPLE\n{0}", currentExample));
+ }
+
+ foreach (string input in Inputs)
+ {
+ psHelpInfoLines.Add(String.Format(".INPUTS\n{0}", input));
+ }
+
+ foreach (string output in Outputs)
+ {
+ psHelpInfoLines.Add(String.Format(".OUTPUTS\n{0}", output));
+ }
+
+ if (Notes.Length > 0)
+ {
+ psHelpInfoLines.Add(String.Format(".NOTES\n{0}", String.Join("\n", Notes)));
+ }
+
+ foreach (string link in Links)
+ {
+ psHelpInfoLines.Add(String.Format(".LINK\n{0}", link));
+ }
+
+ if (Component.Length > 0)
+ {
+ psHelpInfoLines.Add(String.Format(".COMPONENT\n{0}", String.Join("\n", Component)));
+ }
+
+ if (Role.Length > 0)
+ {
+ psHelpInfoLines.Add(String.Format(".ROLE\n{0}", String.Join("\n", Role)));
+ }
+
+ if (Functionality.Length > 0)
+ {
+ psHelpInfoLines.Add(String.Format(".FUNCTIONALITY\n{0}", String.Join("\n", Functionality)));
+ }
+
+ psHelpInfo = String.Join("\n", psHelpInfoLines);
+ psHelpInfo = psHelpInfo.TrimEnd('\n');
+ psHelpInfo += "\n\n#>";
+ return psHelpInfoSuccessfullyCreated;
+ }
+
+ ///
+ /// Helper method which takes lines of the PSScriptInfo comment block
+ /// and parses metadata from those lines into a hashtable.
+ ///
+ private static void GetMetadataFromCommentLines(
+ string[] commentLines,
+ ref Hashtable parsedScriptMetadata)
+ {
+ // parsedScriptMetadata = new Hashtable();
+ string keyName = "";
+ string value = "";
+
+ for (int i = 1; i < commentLines.Count(); i++)
+ {
+ string line = commentLines[i];
+
+ // scenario where line is: .KEY VALUE
+ // this line contains a new metadata property.
+ if (line.Trim().StartsWith("."))
+ {
+ // check if keyName was previously populated, if so add this key value pair to the metadata hashtable
+ if (!String.IsNullOrEmpty(keyName))
+ {
+ parsedScriptMetadata.Add(keyName, value);
+ }
+
+ string[] parts = line.Trim().TrimStart('.').Split();
+ keyName = parts[0];
+ value = parts.Count() > 1 ? String.Join(" ", parts.Skip(1)) : String.Empty;
+ }
+ else if (!(line.Trim()).Equals("#>"))
+ {
+ // TODO: this condition won't be hit anymore, as we don't add #> to array of comment lines captured
+ // scenario where line contains text that is a continuation of value from previously recorded key
+ // this line does not starting with .KEY, and is also not an empty line.
+ if (value.Equals(String.Empty))
+ {
+ value += line;
+ }
+ else
+ {
+ value += Environment.NewLine + line;
+ }
+ }
+ else
+ {
+ // scenario where line is: #>
+ // this line signifies end of comment block, so add last recorded key value pair before the comment block ends.
+ if (!String.IsNullOrEmpty(keyName))
+ {
+ parsedScriptMetadata.Add(keyName, value);
+ }
+ }
+ }
+
+ }
+
+ ///
+ /// Ensure no fields (passed as stringToValidate) contains '<#' or '#>' (would break AST block section).
+ ///
+ private bool StringContainsComment(string stringToValidate)
+ {
+ return stringToValidate.Contains("<#") || stringToValidate.Contains("#>");
+ }
+
+ ///
+ /// Removes the signature from the current PSScriptFileInfo instance's EndOfFileContents property
+ /// as the signature would be invalidated during update.
+ ///
+ private void RemoveSignatureString()
+ {
+ if (EndOfFileContents.Contains(signatureStartString))
+ {
+ int signatureStartIndex = EndOfFileContents.IndexOf(signatureStartString);
+ EndOfFileContents = EndOfFileContents.Substring(0, signatureStartIndex);
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/src/code/TestPSScriptFileInfo.cs b/src/code/TestPSScriptFileInfo.cs
new file mode 100644
index 000000000..09a1448bb
--- /dev/null
+++ b/src/code/TestPSScriptFileInfo.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.IO;
+using System.Management.Automation;
+using Microsoft.PowerShell.PowerShellGet.UtilClasses;
+
+namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
+{
+ ///
+ /// Tests the contents of a .ps1 file to see if it has all properties and is in correct format
+ /// for publishing the script with the file.
+ ///
+ [Cmdlet(VerbsDiagnostic.Test, "PSScriptFileInfo")]
+ [OutputType(typeof(bool))]
+ public sealed class TestPSScriptFileInfo : PSCmdlet
+ {
+ #region Parameters
+
+ ///
+ /// The path to the .ps1 file to test.
+ ///
+ [Parameter(Position = 0, Mandatory = true)]
+ [ValidateNotNullOrEmpty]
+ public string FilePath { get; set; }
+
+ #endregion
+
+ #region Methods
+
+ protected override void EndProcessing()
+ {
+ if (!FilePath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
+ {
+ var exMessage = "Path needs to end with a .ps1 file. Example: C:/Users/john/x/MyScript.ps1";
+ var ex = new ArgumentException(exMessage);
+ var InvalidPathError = new ErrorRecord(ex, "InvalidPath", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidPathError);
+ }
+
+ var resolvedPaths = SessionState.Path.GetResolvedPSPathFromPSPath(FilePath);
+ if (resolvedPaths.Count != 1)
+ {
+ var exMessage = "Error: Could not resolve provided Path argument into a single path.";
+ var ex = new PSArgumentException(exMessage);
+ var InvalidPathArgumentError = new ErrorRecord(ex, "InvalidPathArgumentError", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidPathArgumentError);
+ }
+
+ var resolvedFilePath = resolvedPaths[0].Path;
+
+ if (!File.Exists(resolvedFilePath))
+ {
+ var exMessage = "A file does not exist at the location specified";
+ var ex = new ArgumentException(exMessage);
+ var FileDoesNotExistError = new ErrorRecord(ex, "FileDoesNotExistAtPath", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(FileDoesNotExistError);
+ }
+
+ bool isValidScript = PSScriptFileInfo.TryParseScriptIntoPSScriptInfo(
+ scriptFileInfoPath: resolvedFilePath,
+ parsedScript: out PSScriptFileInfo parsedScriptInfo,
+ errors: out ErrorRecord[] errors,
+ out string[] verboseMsgs);
+
+ if (!isValidScript)
+ {
+ foreach (ErrorRecord error in errors)
+ {
+ WriteWarning("The .ps1 script file passed in was not valid due to: " + error.Exception.Message);
+ }
+ }
+
+ foreach (string msg in verboseMsgs)
+ {
+ WriteVerbose(msg);
+
+ // also write a warning as the existing ProjectUri, LicenseUri, IconUri may be overwrriten if they were determined to not be valid when parsed.
+ WriteWarning(msg);
+ }
+
+ WriteObject(isValidScript);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/code/UpdatePSScriptFileInfo.cs b/src/code/UpdatePSScriptFileInfo.cs
new file mode 100644
index 000000000..6db705283
--- /dev/null
+++ b/src/code/UpdatePSScriptFileInfo.cs
@@ -0,0 +1,322 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Management.Automation;
+using Microsoft.PowerShell.Commands;
+using Microsoft.PowerShell.PowerShellGet.UtilClasses;
+
+namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
+{
+ ///
+ /// Updates a .ps1 file with specified properties.
+ ///
+ [Cmdlet(VerbsData.Update, "PSScriptFileInfo")]
+ public sealed class UpdatePSScriptFileInfo : PSCmdlet
+ {
+ #region Parameters
+
+ ///
+ /// The author of the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Author { get; set; }
+
+ ///
+ /// The name of the company owning the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string CompanyName { get; set; }
+
+ ///
+ /// The copyright statement for the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Copyright { get; set; }
+
+ ///
+ /// The description of the script.
+ ///
+ [Parameter()]
+ [ValidateNotNullOrEmpty()]
+ public string Description { get; set; }
+
+ ///
+ /// The list of external module dependencies taken by this script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] ExternalModuleDependencies { get; set; }
+
+ ///
+ /// The list of external script dependencies taken by this script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] ExternalScriptDependencies { get; set; }
+
+ ///
+ /// The unique identifier for the script. The GUID can be used to distinguish among scripts with the same name.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public Guid Guid { get; set; }
+
+ ///
+ /// The Uri for the icon associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string IconUri { get; set; }
+
+ ///
+ /// The Uri for the license associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string LicenseUri { get; set; }
+
+ ///
+ /// The path the .ps1 script info file will be created at.
+ ///
+ [Parameter(Position = 0, Mandatory = true)]
+ [ValidateNotNullOrEmpty]
+ public string FilePath { get; set; }
+
+ ///
+ /// The private data associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string PrivateData { get; set; }
+
+ ///
+ /// The Uri for the project associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string ProjectUri { get; set; }
+
+ ///
+ /// The release notes for the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string ReleaseNotes { get; set; }
+
+ ///
+ /// Remove signature from signed .ps1 (if present) thereby allowing update of script to happen
+ /// User should re-sign the updated script afterwards.
+ ///
+ [Parameter]
+ public SwitchParameter RemoveSignature { get; set; }
+
+ ///
+ /// The list of modules required by the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public Hashtable[] RequiredModules { get; set; }
+
+ ///
+ /// The list of scripts required by the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] RequiredScripts { get; set; }
+
+ ///
+ /// The tags associated with the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string[] Tags { get; set; }
+
+ ///
+ /// The version of the script.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty()]
+ public string Version { get; set; }
+
+ #endregion
+
+ #region Private Members
+
+ private const string signatureStartString = "# SIG # Begin signature block";
+
+ #endregion
+
+ #region Methods
+
+ protected override void EndProcessing()
+ {
+ Uri projectUri = null;
+ if (!String.IsNullOrEmpty(ProjectUri) && !Utils.TryCreateValidUri(uriString: ProjectUri,
+ cmdletPassedIn: this,
+ uriResult: out projectUri,
+ errorRecord: out ErrorRecord projectErrorRecord))
+ {
+ ThrowTerminatingError(projectErrorRecord);
+ }
+
+ Uri licenseUri = null;
+ if (!String.IsNullOrEmpty(LicenseUri) && !Utils.TryCreateValidUri(uriString: LicenseUri,
+ cmdletPassedIn: this,
+ uriResult: out licenseUri,
+ errorRecord: out ErrorRecord licenseErrorRecord))
+ {
+ ThrowTerminatingError(licenseErrorRecord);
+ }
+
+ Uri iconUri = null;
+ if (!String.IsNullOrEmpty(IconUri) && !Utils.TryCreateValidUri(uriString: IconUri,
+ cmdletPassedIn: this,
+ uriResult: out iconUri,
+ errorRecord: out ErrorRecord iconErrorRecord))
+ {
+ ThrowTerminatingError(iconErrorRecord);
+ }
+
+ if (!FilePath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
+ {
+ var exMessage = "File path needs to end with a .ps1 extension. Example: C:/Users/john/x/MyScript.ps1";
+ var ex = new ArgumentException(exMessage);
+ var InvalidOrNonExistantPathError = new ErrorRecord(ex, "InvalidOrNonExistantPath", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidOrNonExistantPathError);
+ }
+
+ var resolvedPaths = SessionState.Path.GetResolvedPSPathFromPSPath(FilePath);
+ if (resolvedPaths.Count != 1)
+ {
+ var exMessage = "Error: Could not resolve provided Path argument into a single path.";
+ var ex = new PSArgumentException(exMessage);
+ var InvalidPathArgumentError = new ErrorRecord(ex, "InvalidPathArgumentError", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(InvalidPathArgumentError);
+ }
+
+ string resolvedFilePath = resolvedPaths[0].Path;
+
+ if (!File.Exists(resolvedFilePath))
+ {
+ var exMessage = "A script file does not exist at the location specified";
+ var ex = new ArgumentException(exMessage);
+ var FileDoesNotExistError = new ErrorRecord(ex, "FileDoesNotExistAtPath", ErrorCategory.InvalidArgument, null);
+ ThrowTerminatingError(FileDoesNotExistError);
+ }
+
+ ModuleSpecification[] validatedRequiredModuleSpecifications = new ModuleSpecification[]{};
+ if (RequiredModules != null && RequiredModules.Length > 0)
+ {
+ if (!Utils.TryCreateModuleSpecification(
+ moduleSpecHashtables: RequiredModules,
+ out validatedRequiredModuleSpecifications,
+ out ErrorRecord[] moduleSpecErrors))
+ {
+ foreach (ErrorRecord err in moduleSpecErrors)
+ {
+ WriteError(err);
+ }
+
+ return;
+ }
+ }
+
+ if (!PSScriptFileInfo.TryParseScriptIntoPSScriptInfo(
+ scriptFileInfoPath: resolvedFilePath,
+ parsedScript: out PSScriptFileInfo parsedScriptInfo,
+ errors: out ErrorRecord[] errors,
+ out string[] verboseMsgs))
+ {
+ foreach (string msg in verboseMsgs)
+ {
+ WriteVerbose(msg);
+
+ // also write a warning as the existing ProjectUri, LicenseUri, IconUri may be overwrriten if they were determined to not be valid when parsed.
+ WriteWarning(msg);
+ }
+
+ WriteWarning("The .ps1 script file passed in was not valid due to the following error(s) listed below");
+ foreach (ErrorRecord error in errors)
+ {
+ WriteError(error);
+ }
+
+ return;
+ }
+
+ if (parsedScriptInfo.EndOfFileContents.Contains(signatureStartString))
+ {
+ WriteWarning("This script contains a signature and cannot be updated without invalidating the current script signature");
+ if (!RemoveSignature)
+ {
+ var exMessage = "Cannot update the script file because the file contains a signature block and updating will invalidate the signature. Use -RemoveSignature to remove the signature block, and then re-sign the file after it is updated.";
+ var ex = new PSInvalidOperationException(exMessage);
+ var ScriptToBeUpdatedContainsSignatureError = new ErrorRecord(ex, "ScriptToBeUpdatedContainsSignature", ErrorCategory.InvalidOperation, null);
+ ThrowTerminatingError(ScriptToBeUpdatedContainsSignatureError);
+ }
+ }
+
+ if (!PSScriptFileInfo.TryUpdateScriptFileContents(
+ scriptInfo: parsedScriptInfo,
+ updatedPSScriptFileContents: out string updatedPSScriptFileContents,
+ errors: out ErrorRecord[] updateErrors,
+ version: Version,
+ guid: Guid,
+ author: Author,
+ companyName: CompanyName,
+ copyright: Copyright,
+ tags: Tags,
+ licenseUri: licenseUri,
+ projectUri: projectUri,
+ iconUri: iconUri,
+ requiredModules: validatedRequiredModuleSpecifications,
+ externalModuleDependencies: ExternalModuleDependencies,
+ requiredScripts: RequiredScripts,
+ externalScriptDependencies: ExternalScriptDependencies,
+ releaseNotes: ReleaseNotes,
+ privateData: PrivateData,
+ description: Description))
+ {
+ WriteWarning("Updating the specified script file failed due to the following error(s):");
+ foreach (ErrorRecord error in updateErrors)
+ {
+ WriteError(error);
+ }
+
+ return;
+ }
+
+ string tempScriptFilePath = null;
+ try
+ {
+ tempScriptFilePath = Path.GetTempFileName();
+
+ File.WriteAllText(tempScriptFilePath, updatedPSScriptFileContents);
+ File.Copy(tempScriptFilePath, resolvedFilePath, overwrite: true);
+ }
+ catch(Exception e)
+ {
+ WriteError(new ErrorRecord(
+ new PSInvalidOperationException($"Could not update .ps1 file due to: {e.Message}"),
+ "FileIOErrorDuringUpdate",
+ ErrorCategory.InvalidArgument,
+ this));
+ }
+ finally
+ {
+ if (tempScriptFilePath != null)
+ {
+ File.Delete(tempScriptFilePath);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/code/Utils.cs b/src/code/Utils.cs
index af3687a1f..cd42d4f7c 100644
--- a/src/code/Utils.cs
+++ b/src/code/Utils.cs
@@ -15,6 +15,8 @@
using System.Management.Automation.Runspaces;
using System.Runtime.InteropServices;
using System.Security;
+using System.Text.RegularExpressions;
+using Microsoft.PowerShell.Commands;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.PowerShell.PowerShellGet.UtilClasses
@@ -113,6 +115,17 @@ public static string[] GetStringArray(ArrayList list)
return strArray;
}
+ public static string[] GetStringArrayFromString(char[] delimeter, string stringToConvertToArray)
+ {
+ // this will be a string where entries are separated by space
+ if (String.IsNullOrEmpty(stringToConvertToArray))
+ {
+ return Utils.EmptyStrArray;
+ }
+
+ return stringToConvertToArray.Split(delimeter, StringSplitOptions.RemoveEmptyEntries);
+ }
+
public static string[] ProcessNameWildcards(
string[] pkgNames,
out string[] errorMsgs,
@@ -857,6 +870,117 @@ public static Hashtable ConvertJsonToHashtable(
return (results.Count == 1 && results[0] != null) ? (Hashtable)results[0].BaseObject : null;
}
+ public static bool TryCreateModuleSpecification(
+ Hashtable[] moduleSpecHashtables,
+ out ModuleSpecification[] validatedModuleSpecs,
+ out ErrorRecord[] errors)
+ {
+ bool moduleSpecCreatedSuccessfully = true;
+ List errorList = new List();
+ validatedModuleSpecs = new ModuleSpecification[]{};
+ List moduleSpecsList = new List();
+
+ foreach(Hashtable moduleSpec in moduleSpecHashtables)
+ {
+ // ModuleSpecification(string) constructor for creating a ModuleSpecification when only ModuleName is provided
+ if (!moduleSpec.ContainsKey("ModuleName") || String.IsNullOrEmpty((string) moduleSpec["ModuleName"]))
+ {
+ var exMessage = $"RequiredModules Hashtable entry {moduleSpec.ToString()} is missing a key 'ModuleName' and associated value, which is required for each module specification entry";
+ var ex = new ArgumentException(exMessage);
+ var NameMissingModuleSpecError = new ErrorRecord(ex, "NameMissingInModuleSpecification", ErrorCategory.InvalidArgument, null);
+ errorList.Add(NameMissingModuleSpecError);
+ moduleSpecCreatedSuccessfully = false;
+ continue;
+ }
+
+ // at this point it must contain ModuleName key.
+ string moduleSpecName = (string) moduleSpec["ModuleName"];
+ ModuleSpecification currentModuleSpec = null;
+ if (!moduleSpec.ContainsKey("MaximumVersion") && !moduleSpec.ContainsKey("ModuleVersion") && !moduleSpec.ContainsKey("RequiredVersion"))
+ {
+ // pass to ModuleSpecification(string) constructor
+ // this constructor method would only throw for a null/empty string, which we've already validated against above
+ currentModuleSpec = new ModuleSpecification(moduleSpecName);
+
+ if (currentModuleSpec != null)
+ {
+ moduleSpecsList.Add(currentModuleSpec);
+ }
+ else
+ {
+ var exMessage = $"ModuleSpecification object was not able to be created for {moduleSpecName}";
+ var ex = new ArgumentException(exMessage);
+ var ModuleSpecNotCreatedError = new ErrorRecord(ex, "ModuleSpecificationNotCreated", ErrorCategory.InvalidArgument, null);
+ errorList.Add(ModuleSpecNotCreatedError);
+ moduleSpecCreatedSuccessfully = false;
+ continue;
+ }
+ }
+ else
+ {
+ // ModuleSpecification(Hashtable) constructor for when ModuleName + {Required,Maximum,Module}Version value is also provided
+ string moduleSpecMaxVersion = moduleSpec.ContainsKey("MaximumVersion") ? (string) moduleSpec["MaximumVersion"] : String.Empty;
+ string moduleSpecModuleVersion = moduleSpec.ContainsKey("ModuleVersion") ? (string) moduleSpec["ModuleVersion"] : String.Empty;
+ string moduleSpecRequiredVersion = moduleSpec.ContainsKey("RequiredVersion") ? (string) moduleSpec["RequiredVersion"] : String.Empty;
+ Guid moduleSpecGuid = moduleSpec.ContainsKey("Guid") ? (Guid) moduleSpec["Guid"] : Guid.Empty;
+
+ if (String.IsNullOrEmpty(moduleSpecMaxVersion) && String.IsNullOrEmpty(moduleSpecModuleVersion) && String.IsNullOrEmpty(moduleSpecRequiredVersion))
+ {
+ var exMessage = $"ModuleSpecification hashtable requires one of the following keys: MaximumVersion, ModuleVersion, RequiredVersion and failed to be created for {moduleSpecName}";
+ var ex = new ArgumentException(exMessage);
+ var MissingModuleSpecificationMemberError = new ErrorRecord(ex, "MissingModuleSpecificationMember", ErrorCategory.InvalidArgument, null);
+ errorList.Add(MissingModuleSpecificationMemberError);
+ moduleSpecCreatedSuccessfully = false;
+ continue;
+ }
+
+ Hashtable moduleSpecHash = new Hashtable();
+
+ moduleSpecHash.Add("ModuleName", moduleSpecName);
+ if (moduleSpecGuid != Guid.Empty)
+ {
+ moduleSpecHash.Add("Guid", moduleSpecGuid);
+ }
+
+ if (!String.IsNullOrEmpty(moduleSpecMaxVersion))
+ {
+ moduleSpecHash.Add("MaximumVersion", moduleSpecMaxVersion);
+ }
+
+ if (!String.IsNullOrEmpty(moduleSpecModuleVersion))
+ {
+ moduleSpecHash.Add("ModuleVersion", moduleSpecModuleVersion);
+ }
+
+ if (!String.IsNullOrEmpty(moduleSpecRequiredVersion))
+ {
+ moduleSpecHash.Add("RequiredVersion", moduleSpecRequiredVersion);
+ }
+
+ try
+ {
+ currentModuleSpec = new ModuleSpecification(moduleSpecHash);
+ }
+ catch (Exception e)
+ {
+ var ex = new ArgumentException($"ModuleSpecification instance was not able to be created with hashtable constructor due to: {e.Message}");
+ var ModuleSpecNotCreatedError = new ErrorRecord(ex, "ModuleSpecificationNotCreated", ErrorCategory.InvalidArgument, null);
+ errorList.Add(ModuleSpecNotCreatedError);
+ moduleSpecCreatedSuccessfully = false;
+ }
+
+ if (currentModuleSpec != null)
+ {
+ moduleSpecsList.Add(currentModuleSpec);
+ }
+ }
+ }
+
+ errors = errorList.ToArray();
+ validatedModuleSpecs = moduleSpecsList.ToArray();
+ return moduleSpecCreatedSuccessfully;
+ }
+
#endregion
#region Directory and File
diff --git a/test/NewPSScriptFileInfo.Tests.ps1 b/test/NewPSScriptFileInfo.Tests.ps1
index 3ba34acf3..727a05792 100644
--- a/test/NewPSScriptFileInfo.Tests.ps1
+++ b/test/NewPSScriptFileInfo.Tests.ps1
@@ -1,299 +1,241 @@
-# Copyright (c) Microsoft Corporation.
-# Licensed under the MIT License.
-
-Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
-
-Describe "Test New-PSScriptFileInfo" {
- BeforeAll {
- $script:TempPath = Get-TempPath
- }
- BeforeEach {
- # Create temp script path
- $script:TempScriptPath = Join-Path $script:TempPath "PSGet_$(Get-Random)"
- $null = New-Item -Path $script:TempScriptPath -ItemType Directory -Force
-
- $script:PSScriptInfoName = "PSGetTestScript"
- $script:testPSScriptInfoPath = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath "$script:PSScriptInfoName.psd1"
- }
- AfterEach {
- RemoveItem "$script:TempScriptPath"
- }
-
- ### TODO: Add tests for -Force and -WhatIf if those parameters are applicable
-<#
- It "Create .ps1 file with minimal required fields" {
- $Description = "this is a test script"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Test-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- }
-
- It "Create .ps1 file with relative path" {
- $RelativeCurrentPath = Get-Location
- $ScriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:PSScriptInfoName.ps1"
- $Description = "this is a test script"
- New-PSScriptFileInfo -FilePath $ScriptFilePath -Description $Description
-
- Test-PSScriptFileInfo -FilePath $ScriptFilePath | Should -BeTrue
- Remove-Item -Path $ScriptFilePath
- }
-
- It "Create new .ps1 given Version parameter" {
- $Version = "2.0.0.0"
- $Description = "Test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Version $Version -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Version) | Should -BeTrue
- $results.Contains(".VERSION $Version") | Should -BeTrue
- }
-
- It "Create new .ps1 given Guid parameter" {
- $Guid = [guid]::NewGuid()
- $Description = "Test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Guid $Guid -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Guid) | Should -BeTrue
- $results.Contains(".GUID $Guid") | Should -BeTrue
- }
-
- It "Create new .ps1 given Author parameter" {
- $Author = "Test Author"
- $Description = "Test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Author $Author -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Author) | Should -BeTrue
- $results.Contains(".AUTHOR $Author") | Should -BeTrue
- }
-
- It "Create new .ps1 given Description parameter" {
- $Description = "PowerShellGet test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($Description) | Should -BeTrue
- $results -like ".DESCRIPTION*$Description" | Should -BeTrue
- }
-
- It "Create new .ps1 given CompanyName parameter" {
- $CompanyName = "Microsoft"
- $Description = "Test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -CompanyName $CompanyName -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($CompanyName) | Should -BeTrue
- $results.Contains(".COMPANYNAME $Companyname") | Should -BeTrue
- }
-
- It "Create new .ps1 given Copyright parameter" {
- $Copyright = "(c) Test Corporation"
- $Description = "Test description"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Copyright $Copyright -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Copyright) | Should -BeTrue
- $results.Contains(".COPYRIGHT $Copyright") | Should -BeTrue
- }
-
- It "Create new .ps1 given RequiredModules parameter" {
- $requiredModuleName = 'PackageManagement'
- $requiredModuleVersion = '1.0.0.0'
- $RequiredModules = @(@{ModuleName = $requiredModuleName; ModuleVersion = $requiredModuleVersion })
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredModules $RequiredModules -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($requiredModuleName) | Should -BeTrue
- $results.Contains($requiredModuleVersion) | Should -BeTrue
- $results -like ".REQUIREDMODULES*$requiredModuleName*$requiredModuleVersion" | Should -BeTrue
- }
-
- It "Create new .ps1 given ReleaseNotes parameter" {
- $Description = "Test Description"
- $ReleaseNotes = "Release notes for script."
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ReleaseNotes $ReleaseNotes -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($ReleaseNotes) | Should -BeTrue
- $results -like ".RELEASENOTES*$ReleaseNotes" | Should -BeTrue
- }
-
- It "Create new .ps1 given Tags parameter" {
- $Description = "Test Description"
- $Tag1 = "tag1"
- $Tag2 = "tag2"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Tags $Tag1, $Tag2 -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($Tag1) | Should -BeTrue
- $results.Contains($Tag2) | Should -BeTrue
- $results.Contains(".TAGS $Tag1 $Tag2") | Should -BeTrue
- }
-
- It "Create new .ps1 given ProjectUri parameter" {
- $Description = "Test Description"
- $ProjectUri = "https://www.testprojecturi.com/"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ProjectUri $ProjectUri -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($ProjectUri) | Should -BeTrue
- $results.Contains(".PROJECTURI $ProjectUri") | Should -BeTrue
- }
-
- It "Create new .ps1 given LicenseUri parameter" {
- $Description = "Test Description"
- $LicenseUri = "https://www.testlicenseuri.com/"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -LicenseUri $LicenseUri -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($LicenseUri) | Should -BeTrue
- $results.Contains(".LICENSEURI $LicenseUri") | Should -BeTrue
- }
-
- It "Create new .ps1 given IconUri parameter" {
- $Description = "Test Description"
- $IconUri = "https://www.testiconuri.com/"
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -IconUri $IconUri -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($IconUri) | Should -BeTrue
- $results.Contains(".ICONURI $IconUri") | Should -BeTrue
- }
-
- It "Create new .ps1 given ExternalModuleDependencies parameter" {
- $Description = "Test Description"
- $ExternalModuleDep1 = "ExternalModuleDep1"
- $ExternalModuleDep2 = "ExternalModuleDep2"
- $ExternalModuleDep1FileName = "ExternalModuleDep1.psm1"
- $ExternalModuleDep2FileName = "ExternalModuleDep2.psm1"
- $ExternalModuleDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $ExternalModuleDep1FileName
- $ExternalModuleDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $ExternalModuleDep2FileName
-
- $null = New-Item -Path $ExternalModuleDepPath1 -ItemType File -Force
- $null = New-Item -Path $ExternalModuleDepPath2 -ItemType File -Force
-
- # NOTE: you may need to add the -NestedModules parameter here as well
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $ExternalModuleDep1, $ExternalModuleDep2 -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($ExternalModuleDep1) | Should -BeTrue
- $results.Contains($ExternalModuleDep2) | Should -BeTrue
- $results -like ".EXTERNALMODULEDEPENDENCIES*$ExternalModuleDep1*$ExternalModuleDep2" | Should -BeTrue
- }
-
- It "Create new .ps1 given RequiredAssemblies parameter" {
- $Description = "Test Description"
- $RequiredAssembly1 = "RequiredAssembly1.dll"
- $RequiredAssembly2 = "RequiredAssembly2.dll"
- $RequiredAssemblyPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $RequiredAssembly1
- $RequiredAssemblyPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $RequiredAssembly2
-
- $null = New-Item -Path $RequiredAssemblyPath1 -ItemType File -Force
- $null = New-Item -Path $RequiredAssemblyPath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredAssemblies $RequiredAssembly1, $RequiredAssembly2 -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($RequiredAssembly1) | Should -BeTrue
- $results.Contains($RequiredAssembly2) | Should -BeTrue
- $results -like ".REQUIREDASSEMBLIES*$RequiredAssembly1*$RequiredAssembly2" | Should -BeTrue
- }
-
- It "Create new .ps1 given NestedModules parameter" {
- $Description = "Test Description"
- $NestedModule1 = "NestedModule1"
- $NestedModule2 = "NestedModule2"
- $NestModuleFileName1 = "NestedModule1.dll"
- $NestModuleFileName2 = "NestedModule2.dll"
- $NestedModulePath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NestModuleFileName1
- $NestedModulePath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NestModuleFileName2
-
- $null = New-Item -Path $NestedModulePath1 -ItemType File -Force
- $null = New-Item -Path $NestedModulePath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -NestedModules $NestedModule1, $NestedModule2 -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NestedModule1) | Should -BeTrue
- $results.Contains($NestedModule2) | Should -BeTrue
- $results -like ".NESTEDMODULES*$NestedModule1*$NestedModule2" | Should -BeTrue
- }
-
- It "Create new .ps1 given RequiredScripts parameter" {
- $Description = "Test Description"
- $RequiredScript1 = "NestedModule1.ps1"
- $RequiredScript2 = "NestedModule2.ps1"
- $RequiredScript1Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $RequiredScript1
- $RequiredScript2Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $RequiredScript2
-
- $null = New-Item -Path $RequiredScript1Path -ItemType File -Force
- $null = New-Item -Path $RequiredScript2Path -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredScripts $RequiredScript1, $RequiredScript2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($RequiredScript1) | Should -BeTrue
- $results.Contains($RequiredScript2) | Should -BeTrue
- $results -like ".REQUIREDSCRIPTS*$RequiredScript1*$RequiredScript2" | Should -BeTrue
- }
-
- It "Create new .ps1 given ExternalScriptDependencies parameter" {
- $Description = "Test Description"
- $ExternalScriptDep1 = "ExternalScriptDep1.ps1"
- $ExternalScriptDep2 = "ExternalScriptDep2.ps1"
- $ExternalScriptDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $ExternalScriptDep1
- $ExternalScriptDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $ExternalScriptDep2
-
- $null = New-Item -Path $ExternalScriptDepPath1 -ItemType File -Force
- $null = New-Item -Path $ExternalScriptDepPath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $ExternalModuleDep1, $ExternalModuleDep2 -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($ExternalModuleDep1) | Should -BeTrue
- $results.Contains($ExternalModuleDep2) | Should -BeTrue
- $results -like ".EXTERNALSCRIPTDEPENDENCIES*$ExternalScriptDep1*$ExternalScriptDep2" | Should -BeTrue
- }
-
- It "Create new .ps1 given PrivateData parameter" {
- $Description = "Test Description"
- $PrivateData = @{"PrivateDataEntry1" = "PrivateDataValue1"}
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -PrivateData $PrivateData -Description $Description
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($PrivateData) | Should -BeTrue
- $results -like ".PRIVATEDATA*$PrivateData" | Should -BeTrue
- }
-#>
-}
\ No newline at end of file
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+
+Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
+
+Describe "Test New-PSScriptFileInfo" {
+ BeforeAll {
+ $tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1"
+ $tmpDirPaths = @($tmpDir1Path)
+ Get-NewTestDirs($tmpDirPaths)
+ }
+ BeforeEach {
+ $script:PSScriptInfoName = "test_script"
+ $script:testScriptFilePath = Join-Path -Path $tmpDir1Path -ChildPath "$script:PSScriptInfoName.ps1"
+ }
+ AfterEach {
+ if (Test-Path -Path $script:testScriptFilePath)
+ {
+ Remove-Item $script:testScriptFilePath
+ }
+ }
+
+ It "Create .ps1 file with minimal required fields" {
+ $description = "Test description"
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Description $description
+ Test-PSScriptFileInfo -FilePath $script:testScriptFilePath | Should -BeTrue
+ }
+
+ It "Create .ps1 file with relative path" {
+ $relativeCurrentPath = Get-Location
+ $scriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:PSScriptInfoName.ps1"
+
+ $description = "Test description"
+ New-PSScriptFileInfo -FilePath $scriptFilePath -Description $description
+
+ Test-PSScriptFileInfo -FilePath $scriptFilePath | Should -BeTrue
+ Remove-Item -Path $scriptFilePath
+ }
+
+ It "Create new .ps1 given Version parameter" {
+ $version = "2.0.0.0"
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Version $version -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($version) | Should -BeTrue
+ $results.Contains(".VERSION $version") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given Guid parameter" {
+ $guid = [guid]::NewGuid()
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Guid $guid -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($guid) | Should -BeTrue
+ $results.Contains(".GUID $guid") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given Author parameter" {
+ $author = "Test Author"
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Author $author -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($author) | Should -BeTrue
+ $results.Contains(".AUTHOR $author") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given Description parameter" {
+ $description = "PowerShellGet test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($description) | Should -BeTrue
+ $results -like "*.DESCRIPTION`n*$description*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given CompanyName parameter" {
+ $companyName = "Microsoft"
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -CompanyName $companyName -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($companyName) | Should -BeTrue
+ $results.Contains(".COMPANYNAME $companyname") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given Copyright parameter" {
+ $copyright = "(c) Test Corporation"
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Copyright $copyright -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($copyright) | Should -BeTrue
+ $results.Contains(".COPYRIGHT $copyright") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given RequiredModules parameter" {
+ $requiredModuleName = 'PackageManagement'
+ $requiredModuleVersion = '1.0.0.0'
+ $RequiredModules = @(@{ModuleName = $requiredModuleName; ModuleVersion = $requiredModuleVersion })
+
+ $description = "Test description"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -RequiredModules $RequiredModules -Description $Description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($requiredModuleName) | Should -BeTrue
+ $results.Contains($requiredModuleVersion) | Should -BeTrue
+ $results -like "*#Requires*$requiredModuleName*$requiredModuleVersion*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given ReleaseNotes parameter" {
+ $description = "Test Description"
+ $releaseNotes = "Release notes for script."
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -ReleaseNotes $releaseNotes -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($releaseNotes) | Should -BeTrue
+ $results -like "*.RELEASENOTES`n*$ReleaseNotes*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given Tags parameter" {
+ $description = "Test Description"
+ $tag1 = "tag1"
+ $tag2 = "tag2"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Tags $tag1, $tag2 -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($tag1) | Should -BeTrue
+ $results.Contains($tag2) | Should -BeTrue
+ $results.Contains(".TAGS $tag1 $tag2") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given ProjectUri parameter" {
+ $description = "Test Description"
+ $projectUri = "https://www.testprojecturi.com/"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -ProjectUri $projectUri -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($projectUri) | Should -BeTrue
+ $results.Contains(".PROJECTURI $projectUri") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given LicenseUri parameter" {
+ $description = "Test Description"
+ $licenseUri = "https://www.testlicenseuri.com/"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -LicenseUri $licenseUri -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($licenseUri) | Should -BeTrue
+ $results.Contains(".LICENSEURI $licenseUri") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given IconUri parameter" {
+ $description = "Test Description"
+ $iconUri = "https://www.testiconuri.com/"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -IconUri $iconUri -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($iconUri) | Should -BeTrue
+ $results.Contains(".ICONURI $iconUri") | Should -BeTrue
+ }
+
+ It "Create new .ps1 given ExternalModuleDependencies parameter" {
+ $description = "Test Description"
+ $externalModuleDep1 = "ExternalModuleDep1"
+ $externalModuleDep2 = "ExternalModuleDep2"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -ExternalModuleDependencies $externalModuleDep1, $externalModuleDep2 -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($externalModuleDep1) | Should -BeTrue
+ $results.Contains($externalModuleDep2) | Should -BeTrue
+ $results -like "*.EXTERNALMODULEDEPENDENCIES*$externalModuleDep1*$externalModuleDep2*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given RequiredScripts parameter" {
+ $description = "Test Description"
+ $requiredScript1 = "RequiredScript1"
+ $requiredScript2 = "RequiredScript2"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -RequiredScripts $requiredScript1, $requiredScript2 -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($requiredScript1) | Should -BeTrue
+ $results.Contains($requiredScript2) | Should -BeTrue
+ $results -like "*.REQUIREDSCRIPTS*$requiredScript1*$requiredScript2*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given ExternalScriptDependencies parameter" {
+ $description = "Test Description"
+ $externalScriptDep1 = "ExternalScriptDep1"
+ $externalScriptDep2 = "ExternalScriptDep2"
+
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -ExternalScriptDependencies $externalScriptDep1, $externalScriptDep2 -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($externalScriptDep1) | Should -BeTrue
+ $results.Contains($externalScriptDep2) | Should -BeTrue
+ $results -like "*.EXTERNALSCRIPTDEPENDENCIES*$externalScriptDep1*$externalScriptDep2*" | Should -BeTrue
+ }
+
+ It "Create new .ps1 given PrivateData parameter" {
+ $description = "Test Description"
+ $privateData = @{"PrivateDataEntry1" = "PrivateDataValue1"}
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -PrivateData $privateData -Description $description
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($privateData) | Should -BeTrue
+ $results -like "*.PRIVATEDATA*$privateData*" | Should -BeTrue
+ }
+}
diff --git a/test/PSGetTestUtils.psm1 b/test/PSGetTestUtils.psm1
index e72984f60..c83d6b305 100644
--- a/test/PSGetTestUtils.psm1
+++ b/test/PSGetTestUtils.psm1
@@ -178,7 +178,7 @@ function Get-RemoveTestDirs {
{
if(Test-Path -Path $path)
{
- Remove-Item -Path $path -Force -ErrorAction Ignore
+ Remove-Item -Path $path -Force -Recurse -ErrorAction Ignore
}
}
}
diff --git a/test/TestPSScriptFileInfo.Tests.ps1 b/test/TestPSScriptFileInfo.Tests.ps1
new file mode 100644
index 000000000..30adae47b
--- /dev/null
+++ b/test/TestPSScriptFileInfo.Tests.ps1
@@ -0,0 +1,60 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+
+Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
+
+Describe "Test Test-PSScriptFileInfo" {
+ BeforeAll {
+ $tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1"
+ $tmpDirPaths = @($tmpDir1Path)
+ Get-NewTestDirs($tmpDirPaths)
+
+ # Path to folder, within our test folder, where we store invalid module and script files used for testing
+ $script:testFilesFolderPath = Join-Path $psscriptroot -ChildPath "testFiles"
+
+ # Path to specifically to that invalid test scripts folder
+ $script:testScriptsFolderPath = Join-Path $testFilesFolderPath -ChildPath "testScripts"
+ }
+
+ It "determine script file with minimal required fields as valid" {
+ $scriptFilePath = Join-Path -Path $tmpDir1Path -ChildPath "testscript.ps1"
+ $scriptDescription = "this is a test script"
+ New-PSScriptFileInfo -FilePath $scriptFilePath -Description $scriptDescription
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $true
+ }
+
+ It "not determine script file with Author field missing as valid" {
+ $scriptName = "InvalidScriptMissingAuthor.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $false
+ }
+
+ It "not determine script file with Description field missing as valid" {
+ $scriptName = "InvalidScriptMissingDescription.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $false
+ }
+
+ It "not determine script that is missing Description block altogether as valid" {
+ $scriptName = "InvalidScriptMissingDescriptionCommentBlock.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $false
+ }
+
+ It "not determine script file Guid as valid" {
+ $scriptName = "InvalidScriptMissingGuid.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $false
+ }
+
+ It "not determine script file missing Version as valid" {
+ $scriptName = "InvalidScriptMissingVersion.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ Test-PSScriptFileInfo $scriptFilePath | Should -Be $false
+ }
+}
diff --git a/test/TestPSScriptInfo.Tests.ps1 b/test/TestPSScriptInfo.Tests.ps1
deleted file mode 100644
index fa79f8bf9..000000000
--- a/test/TestPSScriptInfo.Tests.ps1
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) Microsoft Corporation.
-# Licensed under the MIT License.
-
-Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
-
-Describe "Test Test-PSScriptFileInfo" {
-
- BeforeAll {
- $script:TempPath = Get-TempPath
- }
- BeforeEach {
- # Create temp script path
- $script:TempScriptPath = Join-Path $script:TempPath "PSGet_$(Get-Random)"
- $null = New-Item -Path $script:TempScriptPath -ItemType Directory -Force
-
- $script:PSScriptInfoName = "PSGetTestScript"
- $script:testPSScriptInfoPath = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath "$script:PSScriptInfoName.psd1"
- }
- AfterEach {
- RemoveItem "$script:TempScriptPath"
- }
-
- ### TODO: Add tests for -Force and -WhatIf if those parameters are applicable
- <#
- It "Test .ps1 file with minimal required fields" {
- $Description = "This is a test script"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Test-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- }
-
- It "Test .ps1 file with relative path" {
- $RelativeCurrentPath = Get-Location
- $ScriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:PSScriptInfoName.ps1"
- $Description = "this is a test script"
- New-PSScriptFileInfo -FilePath $ScriptFilePath -Description $Description
-
- Test-PSScriptFileInfo -FilePath $ScriptFilePath | Should -BeTrue
- Remove-Item -Path $ScriptFilePath
- }
- #>
-}
diff --git a/test/UpdatePSScriptFileInfo.Tests.ps1 b/test/UpdatePSScriptFileInfo.Tests.ps1
new file mode 100644
index 000000000..91d59bbcd
--- /dev/null
+++ b/test/UpdatePSScriptFileInfo.Tests.ps1
@@ -0,0 +1,312 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+
+Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
+
+Describe "Test Update-PSScriptFileInfo" {
+ BeforeAll {
+ $tmpDir1Path = Join-Path -Path $TestDrive -ChildPath "tmpDir1"
+ $tmpDirPaths = @($tmpDir1Path)
+ Get-NewTestDirs($tmpDirPaths)
+
+ # Path to folder, within our test folder, where we store invalid module and script files used for testing
+ $script:testFilesFolderPath = Join-Path $psscriptroot -ChildPath "testFiles"
+
+ # Path to specifically to that invalid test scripts folder
+ $script:testScriptsFolderPath = Join-Path $testFilesFolderPath -ChildPath "testScripts"
+ }
+
+ BeforeEach {
+ $script:psScriptInfoName = "test_script"
+ $scriptDescription = "this is a test script"
+ $script:testScriptFilePath = Join-Path -Path $tmpDir1Path -ChildPath "$script:psScriptInfoName.ps1"
+ New-PSScriptFileInfo -FilePath $script:testScriptFilePath -Description $scriptDescription
+ }
+
+ AfterEach {
+ if (Test-Path -Path $script:testScriptFilePath)
+ {
+ Remove-Item $script:testScriptFilePath
+ }
+ }
+
+ It "Update .ps1 file with relative path" {
+ $relativeCurrentPath = Get-Location
+ $scriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:psScriptInfoName.ps1"
+ $oldDescription = "Old description for test script"
+ $newDescription = "New description for test script"
+ New-PSScriptFileInfo -FilePath $scriptFilePath -Description $oldDescription
+
+ Update-PSScriptFileInfo -FilePath $scriptFilePath -Description $newDescription
+ Test-PSScriptFileInfo -FilePath $scriptFilePath | Should -BeTrue
+
+ Test-Path -Path $scriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $scriptFilePath -Raw
+ $results.Contains($newDescription) | Should -BeTrue
+ $results -like "*.DESCRIPTION`n*$newDescription*" | Should -BeTrue
+
+ Remove-Item -Path $scriptFilePath -Force
+ }
+
+ It "Update script should not overwrite old script data unless that property is specified" {
+ $description = "Test Description"
+ $version = "3.0.0"
+ $author = "John Doe"
+ $newAuthor = "Jane Doe"
+ $projectUri = "https://testscript.com/"
+
+ $relativeCurrentPath = Get-Location
+ $scriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:psScriptInfoName.ps1"
+
+ New-PSScriptFileInfo -FilePath $scriptFilePath -Description $description -Version $version -Author $author -ProjectUri $projectUri
+ Update-PSScriptFileInfo -FilePath $scriptFilePath -Author $newAuthor
+
+ Test-PSScriptFileInfo -FilePath $scriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $scriptFilePath -Raw
+ $results.Contains($newAuthor) | Should -BeTrue
+ $results.Contains(".AUTHOR $newAuthor") | Should -BeTrue
+
+ # rest should be original data used when creating the script
+ $results.Contains($projectUri) | Should -BeTrue
+ $results.Contains(".PROJECTURI $projectUri") | Should -BeTrue
+
+ $results.Contains($version) | Should -BeTrue
+ $results.Contains(".VERSION $version") | Should -BeTrue
+
+ $results.Contains($description) | Should -BeTrue
+ $results -like "*.DESCRIPTION`n*$description*" | Should -BeTrue
+
+ Remove-Item -Path $scriptFilePath -Force
+ }
+
+ It "update script file Author property" {
+ $author = "New Author"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Author $author
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($author) | Should -BeTrue
+ $results.Contains(".AUTHOR $author") | Should -BeTrue
+ }
+
+ It "update script file Version property" {
+ $version = "2.0.0.0"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Version $version
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($version) | Should -BeTrue
+ $results.Contains(".VERSION $version") | Should -BeTrue
+ }
+
+ It "update script file Version property with prerelease version" {
+ $version = "3.0.0-alpha"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Version $version
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($version) | Should -BeTrue
+ $results.Contains(".VERSION $version") | Should -BeTrue
+ }
+
+ It "not update script file with invalid version" {
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Version "4.0.0.0.0" -ErrorVariable err -ErrorAction SilentlyContinue
+ $err.Count | Should -Not -Be 0
+ $err[0].FullyQualifiedErrorId | Should -BeExactly "VersionParseIntoNuGetVersion,Microsoft.PowerShell.PowerShellGet.Cmdlets.UpdatePSScriptFileInfo"
+ }
+
+ It "update script file Description property" {
+ $description = "this is an updated test script"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Description $description
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($description) | Should -BeTrue
+ $results -like "*.DESCRIPTION`n*$description*" | Should -BeTrue
+ }
+
+ It "update script file Guid property" {
+ $guid = [Guid]::NewGuid();
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Guid $guid
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($guid) | Should -BeTrue
+ $results.Contains(".GUID $guid") | Should -BeTrue
+ }
+
+ It "update script file CompanyName property" {
+ $companyName = "New Corporation"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -CompanyName $companyName
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($companyName) | Should -BeTrue
+ $results.Contains(".COMPANYNAME $companyName") | Should -BeTrue
+ }
+
+ It "update script file Copyright property" {
+ $copyright = "(c) 2022 New Corporation. All rights reserved"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Copyright $copyright
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($copyright) | Should -BeTrue
+ $results.Contains(".COPYRIGHT $copyright") | Should -BeTrue
+ }
+
+ It "update script file ExternalModuleDependencies property" {
+ $externalModuleDep1 = "ExternalModuleDep1"
+ $externalModuleDep2 = "ExternalModuleDep2"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -ExternalModuleDependencies $externalModuleDep1,$externalModuleDep2
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($externalModuleDep1) | Should -BeTrue
+ $results.Contains($externalModuleDep2) | Should -BeTrue
+ $results -like "*.EXTERNALMODULEDEPENDENCIES*$externalModuleDep1*$externalModuleDep2*" | Should -BeTrue
+ }
+
+ It "update script file ExternalScriptDependencies property" {
+ $externalScriptDep1 = "ExternalScriptDep1"
+ $externalScriptDep2 = "ExternalScriptDep2"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -ExternalScriptDependencies $externalScriptDep1,$externalScriptDep2
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($externalScriptDep1) | Should -BeTrue
+ $results.Contains($externalScriptDep2) | Should -BeTrue
+ $results -like "*.EXTERNALMODULEDEPENDENCIES*$externalScriptDep1*$externalScriptDep2*" | Should -BeTrue
+ }
+
+ It "update script file IconUri property" {
+ $iconUri = "https://testscript.com/icon"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -IconUri $iconUri
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($iconUri) | Should -BeTrue
+ $results.Contains(".ICONURI $iconUri") | Should -BeTrue
+ }
+
+ It "update script file LicenseUri property" {
+ $licenseUri = "https://testscript.com/license"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -LicenseUri $licenseUri
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($licenseUri) | Should -BeTrue
+ $results.Contains(".LICENSEURI $licenseUri") | Should -BeTrue
+ }
+
+ It "update script file ProjectUri property" {
+ $projectUri = "https://testscript.com/"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -ProjectUri $projectUri
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($projectUri) | Should -BeTrue
+ $results.Contains(".PROJECTURI $projectUri") | Should -BeTrue
+ }
+
+ It "update script file PrivateData property" {
+ $privateData = "this is some private data"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -PrivateData $privateData
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($privateData) | Should -BeTrue
+ $results -like "*.PRIVATEDATA*$privateData*" | Should -BeTrue
+ }
+
+ It "update script file ReleaseNotes property" {
+ $releaseNotes = "Release notes for script."
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -ReleaseNotes $releaseNotes
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($releaseNotes) | Should -BeTrue
+ $results -like "*.RELEASENOTES`n*$releaseNotes*" | Should -BeTrue
+ }
+
+ It "update script file RequiredModules property" {
+ $hashtable1 = @{ModuleName = "RequiredModule1"}
+ $hashtable2 = @{ModuleName = "RequiredModule2"; ModuleVersion = "1.0.0.0"}
+ $hashtable3 = @{ModuleName = "RequiredModule3"; RequiredVersion = "2.5.0.0"}
+ $hashtable4 = @{ModuleName = "RequiredModule4"; ModuleVersion = "1.1.0.0"; MaximumVersion = "2.0.0.0"}
+ $requiredModules = $hashtable1, $hashtable2, $hashtable3, $hashtable4
+
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -RequiredModules $requiredModules
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains("#Requires -Module RequiredModule1") | Should -BeTrue
+ $results -like "*#Requires*ModuleName*Version*" | Should -BeTrue
+ }
+
+ It "update script file RequiredScripts property" {
+ $requiredScript1 = "RequiredScript1"
+ $requiredScript2 = "RequiredScript2"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -RequiredScripts $requiredScript1, $requiredScript2
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($requiredScript1) | Should -BeTrue
+ $results.Contains($requiredScript2) | Should -BeTrue
+ $results -like "*.REQUIREDSCRIPTS*$requiredScript1*$requiredScript2*" | Should -BeTrue
+ }
+
+ It "update script file Tags property" {
+ $tag1 = "tag1"
+ $tag2 = "tag2"
+ Update-PSScriptFileInfo -FilePath $script:testScriptFilePath -Tags $tag1, $tag2
+ Test-PSScriptFileInfo $script:testScriptFilePath | Should -Be $true
+
+ Test-Path -Path $script:testScriptFilePath | Should -BeTrue
+ $results = Get-Content -Path $script:testScriptFilePath -Raw
+ $results.Contains($tag1) | Should -BeTrue
+ $results.Contains($tag2) | Should -BeTrue
+ $results.Contains(".TAGS $tag1 $tag2") | Should -BeTrue
+ }
+
+ It "throw error when attempting to update a signed script without -RemoveSignature parameter" {
+ # Note: user should sign the script again once it's been updated
+
+ $scriptName = "ScriptWithSignature.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ # use a copy of the signed script file so we can re-use for other tests
+ $null = Copy-Item -Path $scriptFilePath -Destination $TestDrive
+ $tmpScriptFilePath = Join-Path -Path $TestDrive -ChildPath $scriptName
+
+ { Update-PSScriptFileInfo -FilePath $tmpScriptFilePath -Version "2.0.0.0" } | Should -Throw -ErrorId "ScriptToBeUpdatedContainsSignature,Microsoft.PowerShell.PowerShellGet.Cmdlets.UpdatePSScriptFileInfo"
+ }
+
+ It "update signed script when using RemoveSignature parameter" {
+ $scriptName = "ScriptWithSignature.ps1"
+ $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
+
+ # use a copy of the signed script file so we can re-use for other tests
+ $null = Copy-Item -Path $scriptFilePath -Destination $TestDrive
+ $tmpScriptFilePath = Join-Path -Path $TestDrive -ChildPath $scriptName
+
+ Update-PSScriptFileInfo -FilePath $tmpScriptFilePath -Version "2.0.0.0" -RemoveSignature
+ Test-PSScriptFileInfo -FilePath $tmpScriptFilePath | Should -Be $true
+ }
+}
diff --git a/test/UpdatePSScriptInfo.Tests.ps1 b/test/UpdatePSScriptInfo.Tests.ps1
deleted file mode 100644
index eb1450eaf..000000000
--- a/test/UpdatePSScriptInfo.Tests.ps1
+++ /dev/null
@@ -1,415 +0,0 @@
-# Copyright (c) Microsoft Corporation.
-# Licensed under the MIT License.
-
-Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
-
-Describe "Test Update-PSScriptFileInfo" {
-
- BeforeAll {
- $script:TempPath = Get-TempPath
- }
- BeforeEach {
- # Create temp script path
- $script:TempScriptPath = Join-Path $script:TempPath "PSGet_$(Get-Random)"
- $null = New-Item -Path $script:TempScriptPath -ItemType Directory -Force
-
- $script:PSScriptInfoName = "PSGetTestScript"
- $script:testPSScriptInfoPath = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath "$script:PSScriptInfoName.psd1"
- }
- AfterEach {
- RemoveItem "$script:TempScriptPath"
- }
-
- ### TODO: Add tests for -Force and -WhatIf if those parameters are applicable
-<#
- It "Update .ps1 file with relative path" {
- $RelativeCurrentPath = Get-Location
- $ScriptFilePath = Join-Path -Path $relativeCurrentPath -ChildPath "$script:PSScriptInfoName.ps1"
- $OldDescription = "Old description for test script"
- $NewDescription = "Old description for test script"
- New-PSScriptFileInfo -FilePath $ScriptFilePath -Description $OldDescription
-
- Update-PSScriptFileInfo -FilePath $ScriptFilePath -Description $NewDescription
-
- Test-PSScriptFileInfo -FilePath $ScriptFilePath | Should -BeTrue
- Remove-Item -Path $ScriptFilePath
- }
-
- It "Update .ps1 given Version parameter" {
- $Version = "2.0.0.0"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Version $Version
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Version) | Should -BeTrue
- $results.Contains(".VERSION $Version") | Should -BeTrue
- }
-
- It "Update .ps1 given prerelease version" {
- $Version = "2.0.0.0-alpha"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Version $Version
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Version) | Should -BeTrue
- $results.Contains(".VERSION $Version") | Should -BeTrue
- }
-
- It "Should not update .ps1 with invalid version" {
- $Version = "4.0.0.0.0"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Version $Version -ErrorVariable err -ErrorAction SilentlyContinue
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeFalse
- $err.Count | Should -Not -Be 0
- $err[0].FullyQualifiedErrorId | Should -BeExactly "VersionParseIntoNuGetVersion,Microsoft.PowerShell.PowerShellGet.Cmdlets.UpdatePSScriptFileInfo"
- }
-
- It "Update .ps1 given Guid parameter" {
- $Guid = [guid]::NewGuid()
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Guid $Guid
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Guid) | Should -BeTrue
- $results.Contains(".GUID $Guid") | Should -BeTrue
- }
-
- It "Update .ps1 given Author parameter" {
- $Author = "New Author"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Author $Author
-
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($Author) | Should -BeTrue
- $results.Contains(".AUTHOR $Author") | Should -BeTrue
- }
-
- It "Update .ps1 given Description parameter" {
- $OldDescription = "Old description for test script."
- $NewDescription = "New description for test script."
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $OldDescription
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Description $NewDescription
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewDescription) | Should -BeTrue
- $results -like ".DESCRIPTION*$NewDescription" | Should -BeTrue
- }
-
- It "Update .ps1 given CompanyName parameter" {
- $OldCompanyName = "Old company name"
- $NewCompanyName = "New company name"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -CompanyName $OldCompanyName -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -CompanyName $NewCompanyName
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($NewCompanyName) | Should -BeTrue
- $results.Contains(".COMPANYNAME $NewCompanyName") | Should -BeTrue
- }
-
- It "Update .ps1 given Copyright parameter" {
- $OldCopyright = "(c) Old Test Corporation"
- $NewCopyright = "(c) New Test Corporation"
- $Description = "Test description"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Copyright $OldCopyright -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Copyright $NewCopyright
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testPSScriptInfoPath -Raw
- $results.Contains($NewCopyright) | Should -BeTrue
- $results.Contains(".COPYRIGHT $NewCopyright") | Should -BeTrue
- }
-
- It "Update .ps1 given RequiredModules parameter" {
- $RequiredModuleName = 'PackageManagement'
- $OldrequiredModuleVersion = '1.0.0.0'
- $OldRequiredModules = @(@{ModuleName = $RequiredModuleName; ModuleVersion = $OldrequiredModuleVersion })
- $NewrequiredModuleVersion = '2.0.0.0'
- $NewRequiredModules = @(@{ModuleName = $RequiredModuleName; ModuleVersion = $NewrequiredModuleVersion })
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredModules $OldRequiredModules -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredModules $NewRequiredModules
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($RequiredModuleName) | Should -BeTrue
- $results.Contains($NewrequiredModuleVersion) | Should -BeTrue
- $results -like ".REQUIREDMODULES*$RequiredModuleName*$NewrequiredModuleVersion" | Should -BeTrue
- }
-
- It "Update .ps1 given ReleaseNotes parameter" {
- $Description = "Test Description"
- $OldReleaseNotes = "Old release notes for script."
- $NewReleaseNotes = "New release notes for script."
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ReleaseNotes $OldReleaseNotes -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ReleaseNotes $NewReleaseNotes
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewReleaseNotes) | Should -BeTrue
- $results -like ".RELEASENOTES*$NewReleaseNotes" | Should -BeTrue
- }
-
- It "Update .ps1 given Tags parameter" {
- $Description = "Test Description"
- $OldTag1 = "Tag1"
- $OldTag2 = "Tag2"
- $NewTag1 = "NewTag1"
- $NewTag2 = "NewTag2"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Tags $OldTag1, $OldTag2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -Tags $NewTag1, $NewTag2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewTag1) | Should -BeTrue
- $results.Contains($NewTag2) | Should -BeTrue
- $results.Contains(".TAGS $NewTag1 $NewTag2") | Should -BeTrue
- }
-
- It "Update .ps1 given ProjectUri parameter" {
- $Description = "Test Description"
- $OldProjectUri = "https://www.oldtestprojecturi.com/"
- $NewProjectUri = "https://www.newtestprojecturi.com/"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ProjectUri $OldProjectUri -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ProjectUri $NewProjectUri
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewProjectUri) | Should -BeTrue
- $results.Contains(".PROJECTURI $NewProjectUri") | Should -BeTrue
- }
-
- It "Update .ps1 given LicenseUri parameter" {
- $Description = "Test Description"
- $OldLicenseUri = "https://www.oldtestlicenseuri.com/"
- $NewLicenseUri = "https://www.newtestlicenseuri.com/"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -LicenseUri $OldLicenseUri -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -LicenseUri $NewLicenseUri
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewLicenseUri) | Should -BeTrue
- $results.Contains(".LICENSEURI $NewLicenseUri") | Should -BeTrue
- }
-
- It "Update .ps1 given IconUri parameter" {
- $Description = "Test Description"
- $OldIconUri = "https://www.oldtesticonuri.com/"
- $NewIconUri = "https://www.newtesticonuri.com/"
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -IconUri $OldIconUri -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -IconUri $NewIconUri
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewIconUri) | Should -BeTrue
- $results.Contains(".ICONURI $NewIconUri") | Should -BeTrue
- }
-
- It "Update .ps1 given ExternalModuleDependencies parameter" {
- $Description = "Test Description"
- $OldExternalModuleDep1 = "OldExternalModuleDep1"
- $OldExternalModuleDep2 = "OldExternalModuleDep2"
- $OldExternalModuleDep1FileName = "OldExternalModuleDep1.psm1"
- $OldExternalModuleDep2FileName = "OldExternalModuleDep2.psm1"
- $OldExternalModuleDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldExternalModuleDep1FileName
- $OldExternalModuleDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldExternalModuleDep2FileName
- $null = New-Item -Path $OldExternalModuleDepPath1 -ItemType File -Force
- $null = New-Item -Path $OldExternalModuleDepPath2 -ItemType File -Force
-
- $NewExternalModuleDep1 = "NewExternalModuleDep1"
- $NewExternalModuleDep2 = "NewExternalModuleDep2"
- $NewExternalModuleDep1FileName = "NewExternalModuleDep1.psm1"
- $NewExternalModuleDep2FileName = "NewExternalModuleDep2.psm1"
- $NewExternalModuleDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewExternalModuleDep1FileName
- $NewExternalModuleDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewExternalModuleDep2FileName
- $null = New-Item -Path $NewExternalModuleDepPath1 -ItemType File -Force
- $null = New-Item -Path $NewExternalModuleDepPath2 -ItemType File -Force
-
- # NOTE: you may need to add the -NestedModules parameter here as well
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $OldExternalModuleDep1, $OldExternalModuleDep2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $NewExternalModuleDep1, $NewExternalModuleDep2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewExternalModuleDep1) | Should -BeTrue
- $results.Contains($NewExternalModuleDep2) | Should -BeTrue
- $results -like ".EXTERNALMODULEDEPENDENCIES*$NewExternalModuleDep1*$NewExternalModuleDep2" | Should -BeTrue
- }
-
- It "Update .ps1 given RequiredAssemblies parameter" {
- $Description = "Test Description"
- $OldRequiredAssembly1 = "OldRequiredAssembly1.dll"
- $OldRequiredAssembly2 = "OldRequiredAssembly2.dll"
- $OldRequiredAssemblyPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldRequiredAssembly1
- $OldRequiredAssemblyPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldRequiredAssembly2
- $null = New-Item -Path $OldRequiredAssemblyPath1 -ItemType File -Force
- $null = New-Item -Path $OldRequiredAssemblyPath2 -ItemType File -Force
-
- $NewRequiredAssembly1 = "NewRequiredAssembly1.dll"
- $NewRequiredAssembly2 = "NewRequiredAssembly2.dll"
- $NewRequiredAssemblyPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewRequiredAssembly1
- $NewRequiredAssemblyPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewRequiredAssembly2
- $null = New-Item -Path $NewRequiredAssemblyPath1 -ItemType File -Force
- $null = New-Item -Path $NewRequiredAssemblyPath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredAssemblies $OldRequiredAssembly1, $OldRequiredAssembly2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredAssemblies $NewRequiredAssembly1, $NewRequiredAssembly2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewRequiredAssembly1) | Should -BeTrue
- $results.Contains($NewRequiredAssembly2) | Should -BeTrue
- $results -like ".REQUIREDASSEMBLIES*$NewRequiredAssembly1*$NewRequiredAssembly2" | Should -BeTrue
- }
-
- It "Update .ps1 given NestedModules parameter" {
- $Description = "Test Description"
- $OldNestedModule1 = "OldNestedModule1"
- $OldNestedModule2 = "OldNestedModule2"
- $OldNestModuleFileName1 = "OldNestedModule1.dll"
- $OldNestModuleFileName2 = "OldNestedModule2.dll"
- $OldNestedModulePath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldNestModuleFileName1
- $OldNestedModulePath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldNestModuleFileName2
- $null = New-Item -Path $OldNestedModulePath1 -ItemType File -Force
- $null = New-Item -Path $OldNestedModulePath2 -ItemType File -Force
-
- $NewNestedModule1 = "NewNestedModule1"
- $NewNestedModule2 = "NewNestedModule2"
- $NewNestModuleFileName1 = "NewNestedModule1.dll"
- $NewNestModuleFileName2 = "NewNestedModule2.dll"
- $NewNestedModulePath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewNestModuleFileName1
- $NewNestedModulePath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewNestModuleFileName2
- $null = New-Item -Path $NewNestedModulePath1 -ItemType File -Force
- $null = New-Item -Path $NewNestedModulePath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -NestedModules $OldNestedModule1, $OldNestedModule2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -NestedModules $NewNestedModule1, $NewNestedModule2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewNestedModule1) | Should -BeTrue
- $results.Contains($NewNestedModule2) | Should -BeTrue
- $results -like ".NESTEDMODULES*$NewNestedModule1*$NewNestedModule2" | Should -BeTrue
- }
-
- It "Update .ps1 given RequiredScripts parameter" {
- $Description = "Test Description"
- $OldRequiredScript1 = "OldNestedModule1.ps1"
- $OldRequiredScript2 = "OldNestedModule2.ps1"
- $OldRequiredScript1Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldRequiredScript1
- $OldRequiredScript2Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldRequiredScript2
- $null = New-Item -Path $OldRequiredScript1Path -ItemType File -Force
- $null = New-Item -Path $OldRequiredScript2Path -ItemType File -Force
-
- $NewRequiredScript1 = "NewNestedModule1.ps1"
- $NewRequiredScript2 = "NewNestedModule2.ps1"
- $NewRequiredScript1Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewRequiredScript1
- $NewRequiredScript2Path = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewRequiredScript2
- $null = New-Item -Path $NewRequiredScript1Path -ItemType File -Force
- $null = New-Item -Path $NewRequiredScript2Path -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredScripts $OldRequiredScript1, $OldRequiredScript2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -RequiredScripts $NewRequiredScript1, $NewRequiredScript2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewRequiredScript1) | Should -BeTrue
- $results.Contains($NewRequiredScript2) | Should -BeTrue
- $results -like ".REQUIREDSCRIPTS*$NewRequiredScript1*$NewRequiredScript2" | Should -BeTrue
- }
-
- It "Update .ps1 given ExternalScriptDependencies parameter" {
- $Description = "Test Description"
- $OldExternalScriptDep1 = "OldExternalScriptDep1.ps1"
- $OldExternalScriptDep2 = "OldExternalScriptDep2.ps1"
- $OldExternalScriptDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldExternalScriptDep1
- $OldExternalScriptDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $OldExternalScriptDep2
- $null = New-Item -Path $OldExternalScriptDepPath1 -ItemType File -Force
- $null = New-Item -Path $OldExternalScriptDepPath2 -ItemType File -Force
-
- $NewExternalScriptDep1 = "NewExternalScriptDep1.ps1"
- $NewExternalScriptDep2 = "NewExternalScriptDep2.ps1"
- $NewExternalScriptDepPath1 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewExternalScriptDep1
- $NewExternalScriptDepPath2 = Microsoft.PowerShell.Management\Join-Path -Path $script:TempScriptPath -ChildPath $NewExternalScriptDep2
- $null = New-Item -Path $NewExternalScriptDepPath1 -ItemType File -Force
- $null = New-Item -Path $NewExternalScriptDepPath2 -ItemType File -Force
-
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $OldExternalModuleDep1, $OldExternalModuleDep2 -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -ExternalModuleDependencies $NewExternalModuleDep1, $NewExternalModuleDep2
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewExternalModuleDep1) | Should -BeTrue
- $results.Contains($NewExternalModuleDep2) | Should -BeTrue
- $results -like ".EXTERNALSCRIPTDEPENDENCIES*$NewExternalModuleDep1*$NewExternalModuleDep2" | Should -BeTrue
- }
-
- It "Update .ps1 given PrivateData parameter" {
- $Description = "Test Description"
- $OldPrivateData = @{"OldPrivateDataEntry1" = "OldPrivateDataValue1"}
- $NewPrivateData = @{"NewPrivateDataEntry1" = "NewPrivateDataValue1"}
- New-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -PrivateData $OldPrivateData -Description $Description
-
- Update-PSScriptFileInfo -FilePath $script:testPSScriptInfoPath -PrivateData $NewPrivateData
-
- Test-Path -FilePath $script:testPSScriptInfoPath | Should -BeTrue
- $results = Get-Content -Path $script:testManifestPath -Raw
- $results.Contains($NewPrivateData) | Should -BeTrue
- $results -like ".PRIVATEDATA*$NewPrivateData" | Should -BeTrue
- }
-
- It "Update signed script when using RemoveSignature parameter" {
- $scriptName = "ScriptWithSignature.ps1"
- $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
-
- # use a copy of the signed script file so we can re-use for other tests
- $null = Copy-Item -Path $scriptFilePath -Destination $TestDrive
- $tmpScriptFilePath = Join-Path -Path $TestDrive -ChildPath $scriptName
-
- Update-PSScriptFileInfo -FilePath $tmpScriptFilePath -Version "2.0.0.0" -RemoveSignature
- Test-PSScriptFileInfo -FilePath $tmpScriptFilePath | Should -Be $true
- }
-
- It "Throw error when attempting to update a signed script without -RemoveSignature parameter" {
- $scriptName = "ScriptWithSignature.ps1"
- $scriptFilePath = Join-Path $script:testScriptsFolderPath -ChildPath $scriptName
-
- # use a copy of the signed script file so we can re-use for other tests
- $null = Copy-Item -Path $scriptFilePath -Destination $TestDrive
- $tmpScriptFilePath = Join-Path -Path $TestDrive -ChildPath $scriptName
-
- { Update-PSScriptFileInfo -FilePath $tmpScriptFilePath -Version "2.0.0.0" } | Should -Throw -ErrorId "ScriptToBeUpdatedContainsSignature,Microsoft.PowerShell.PowerShellGet.Cmdlets.UpdatePSScriptFileInfo"
- }
-#>
-}
\ No newline at end of file
diff --git a/test/testFiles/testScripts/ScriptWithSignature.ps1 b/test/testFiles/testScripts/ScriptWithSignature.ps1
new file mode 100644
index 000000000..d83f3a998
--- /dev/null
+++ b/test/testFiles/testScripts/ScriptWithSignature.ps1
@@ -0,0 +1,75 @@
+
+<#PSScriptInfo
+
+.VERSION 1.0
+
+.GUID 3951be04-bd06-4337-8dc3-a620bf539fbd
+
+.AUTHOR annavied
+
+.COMPANYNAME
+
+.COPYRIGHT
+
+.TAGS
+
+.LICENSEURI
+
+.PROJECTURI
+
+.ICONURI
+
+.EXTERNALMODULEDEPENDENCIES
+
+.REQUIREDSCRIPTS
+
+.EXTERNALSCRIPTDEPENDENCIES
+
+.RELEASENOTES
+
+.PRIVATEDATA
+
+#>
+
+<#
+
+.DESCRIPTION
+ this is a test for a script that will be published remotely
+
+#>
+Param()
+
+
+
+# SIG # Begin signature block
+# MIIFbQYJKoZIhvcNAQcCoIIFXjCCBVoCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
+# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
+# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUhY04RvNe0Q8hliL7qS3/X9kr
+# QVugggMIMIIDBDCCAeygAwIBAgIQN+zCRZRKiphJ5gGoRKvpeTANBgkqhkiG9w0B
+# AQsFADAaMRgwFgYDVQQDDA9Db2RlU2lnbmluZ0NlcnQwHhcNMjIwNjIyMTgyODUx
+# WhcNMjQwNjIyMTgzODUwWjAaMRgwFgYDVQQDDA9Db2RlU2lnbmluZ0NlcnQwggEi
+# MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCf7gQAR4AVpVc4/4OlffaEQ6uE
+# klG01+ga7sZbV7z9UkJFIDbntapCoXV85w/bNbmWSI+IUDisVBS7BIoicKagHskE
+# YhRJv6WL/zxD2lWP21MRkEJBEMicbrj38F2R/khGDq/T5/a1XH+7QVAsf1kOG/oU
+# d0CUDqgsR5+JdpaMt/QRM/jFLEUdvs+7zCvduciEEQRFFUbYYqy9RfmxMpPxZ6CM
+# RjLVr5k4tirbg1YyBK6l7xPvT3BUejGvEYPOdAskPXMVbMO37DyEszudqOz9eEvp
+# yHCKOgePLeq+9DbOQ+fAy30c79YNU5JfvgaDY+3c99WQXSeQuLYNDUeDDPGxAgMB
+# AAGjRjBEMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNV
+# HQ4EFgQUrmtlJTMGV5h8ksEMzPTPYk04g3IwDQYJKoZIhvcNAQELBQADggEBAAR3
+# sIiiVgSxUiPzGS/Ivwgjvqfsb6HXioE9VIJxQPwXc63LqC01TGJpeGayjr5zQ4p5
+# vt9q8WsiZvoUMofWzabz4BdprGWVDrO8hwksIixF8ojbfLuAra1cZ4qkDZtJH2Sn
+# 0dUhvXabZqLuVghMiyqcSvs2hN8OiVI+tLzW8VQKzbFdj77c+lHxKBTkcKVpLiSI
+# V2V8P4zRxyYE+CMlpTr58ErOGVxP1zITou7fwCAXdWEKWo5nlU22VNF6oGE9tghm
+# S3M5PQT8lFCjZOPPKx+0oLDxwjluHENXZzH+61ugrszzRjK1rG3D3emrRYh/4BcG
+# Wy7J1H41povt21JlzEExggHPMIIBywIBATAuMBoxGDAWBgNVBAMMD0NvZGVTaWdu
+# aW5nQ2VydAIQN+zCRZRKiphJ5gGoRKvpeTAJBgUrDgMCGgUAoHgwGAYKKwYBBAGC
+# NwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
+# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUbfriqhB/
+# EKzgoXnVu2UFtaTb040wDQYJKoZIhvcNAQEBBQAEggEAiQa/HUhDP1HyrPh7mC5H
+# 6IwOdxL4p3EIkGeuUh3ZqWRNFLNz0ob24vqmKBtaKTfJqqrxTIBYeoBKB3Y8Wcx2
+# rEaH31WqQM2U7mFvM2cVv6dcrdWmLcMwi3LSEMxJf6VbWpbmWZK6zMRW2H76P5wQ
+# cs6BUOwKZq/5eQcQLjJ3h+Mh5dsENZ7scB4U1yihD7Ggvrgxf54+J/TS8XuDsx2o
+# g0czxIjMBwT5wGh8BqbC50izZ3D0WRFe7UNnhMk7zKG/bvIRBxah+JV25hdoGYaR
+# 2tdmgr4EMPoB1ti8DOFmYAicckDWfX7/X4NzeM234LSMLtOxO2lVj5jhkmJJdjKh
+# WA==
+# SIG # End signature block