From da3a197ebdf80cdaffa422eda1a7079c522b63f3 Mon Sep 17 00:00:00 2001 From: Amber Erickson Date: Thu, 7 Oct 2021 20:13:00 -0700 Subject: [PATCH 1/6] Add implementation for -destinationpath parameter --- src/code/PublishPSResource.cs | 58 +++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 5684bfc08..54814d4c2 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -101,6 +101,40 @@ public string LiteralPath } private string _literalPath; + /// + /// Specifies the path to where the resource (as a nupkg) should be saved to. This parameter can be used in conjunction with the + /// -Repository parameter to publish to a repository and also save the exact same package to the local file system. + /// Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). + /// + [Parameter()] + [ValidateNotNullOrEmpty] + public string DestinationPath + { + get + { return _destinationPath; } + + set + { + string resolvedPath = string.Empty; + if (!string.IsNullOrEmpty(value)) + { + resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path; + } + + if (Directory.Exists(resolvedPath)) + { + _destinationPath = resolvedPath; + } + // consider throwing error if path does not exist + else { + var ex = new ArgumentException("Destination path does not exist."); + var DestinationPathDoesNotExist = new ErrorRecord(ex, "DestinationPathDoesNotExist", ErrorCategory.InvalidArgument, null); + WriteError(DestinationPathDoesNotExist); + } + } + } + private string _destinationPath; + /// /// Specifies a user account that has rights to a specific repository (used for finding dependencies). /// @@ -163,7 +197,7 @@ public PSCredential ProxyCredential { protected override void BeginProcessing() { // Create a respository story (the PSResourceRepository.xml file) if it does not already exist - // This is to create a better experience for those who have just installed v3 and want to get up and running quickly + // This is to create a better experience for those who have just installed v3 and want to get up and running quickly RepositorySettings.CheckRepositoryStore(); } @@ -374,7 +408,27 @@ protected override void ProcessRecord() return; } - PushNupkg(outputNupkgDir, repositoryUrl); + // This call does not throw any exceptions, but it will return unsuccessful response status codes + PushNupkg(outputNupkgDir, repositoryUrl); + + // If -DestinationPath is specified then also publish the .nupkg there + if (!string.IsNullOrWhiteSpace(_destinationPath)) + { + try + { + var nupkgName = _pkgName + "." + _pkgVersion.ToNormalizedString() + ".nupkg"; + File.Move(System.IO.Path.Combine(outputNupkgDir, nupkgName), System.IO.Path.Combine(_destinationPath, nupkgName)); + } + catch (Exception e) { + var message = string.Format("Error moving .nupkg into destination path: '{0}'.", e.Message); + var ex = new ArgumentException(message); + var ErrorMovingNupkg = new ErrorRecord(ex, "ErrorMovingNupkg", ErrorCategory.NotSpecified, null); + WriteError(ErrorMovingNupkg); + + // exit process record + return; + } + } } finally { WriteVerbose(string.Format("Deleting temporary directory '{0}'", outputDir)); From 535ca9e02c80a3ac41d28dfad584d32268e0c9b4 Mon Sep 17 00:00:00 2001 From: Amber Erickson Date: Thu, 7 Oct 2021 20:19:14 -0700 Subject: [PATCH 2/6] Add test for -destinationpath param --- test/PublishPSResource.Tests.ps1 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/PublishPSResource.Tests.ps1 b/test/PublishPSResource.Tests.ps1 index 2a49a1799..807f49f45 100644 --- a/test/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResource.Tests.ps1 @@ -271,4 +271,20 @@ Describe "Test Publish-PSResource" { $Error[0].FullyQualifiedErrorId | Should -be "403Error,Microsoft.PowerShell.PowerShellGet.Cmdlets.PublishPSResource" } + + It "Publish a module with -Path -Repository and -DestinationPath" { + $version = "1.0.0" + New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module" + + $tmpPath = Join-Path -Path $TestDrive -ChildPath "testtmppath" + New-Item $tmpPath -Itemtype directory -Force + + Publish-PSResource -Path $script:PublishModuleBase -Repository $testRepository2 -DestinationPath $tmpPath + + $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$script:PublishModuleName.$version.nupkg" + (Get-ChildItem $script:repositoryPath2).FullName | Should -Be $expectedPath + + $expectedPath = Join-Path -Path $tmpPath -ChildPath "$script:PublishModuleName.$version.nupkg" + (Get-ChildItem $tmpPath).FullName | Should -Be $expectedPath + } } From eb00a45d7607130685c9f9cdc303a1fab0c29d7b Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:00:24 -0700 Subject: [PATCH 3/6] Update src/code/PublishPSResource.cs Co-authored-by: Anam Navied --- src/code/PublishPSResource.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 54814d4c2..3b9135626 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -420,7 +420,8 @@ protected override void ProcessRecord() File.Move(System.IO.Path.Combine(outputNupkgDir, nupkgName), System.IO.Path.Combine(_destinationPath, nupkgName)); } catch (Exception e) { - var message = string.Format("Error moving .nupkg into destination path: '{0}'.", e.Message); + var message = string.Format("Error moving .nupkg into destination path '{0}' due to: '{1}'.", _destinationPath, e.Message); + var ex = new ArgumentException(message); var ErrorMovingNupkg = new ErrorRecord(ex, "ErrorMovingNupkg", ErrorCategory.NotSpecified, null); WriteError(ErrorMovingNupkg); From c78cf4d0caed94f09981a3fd180bed3b1c19e88d Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:01:45 -0700 Subject: [PATCH 4/6] Update test/PublishPSResource.Tests.ps1 Co-authored-by: Anam Navied --- test/PublishPSResource.Tests.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/PublishPSResource.Tests.ps1 b/test/PublishPSResource.Tests.ps1 index 807f49f45..525399c73 100644 --- a/test/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResource.Tests.ps1 @@ -281,7 +281,8 @@ Describe "Test Publish-PSResource" { Publish-PSResource -Path $script:PublishModuleBase -Repository $testRepository2 -DestinationPath $tmpPath - $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$script:PublishModuleName.$version.nupkg" + $expectedPath = Join-Path -Path $script:repositoryPath2 -ChildPath "$script:PublishModuleName.$version.nupkg" + (Get-ChildItem $script:repositoryPath2).FullName | Should -Be $expectedPath $expectedPath = Join-Path -Path $tmpPath -ChildPath "$script:PublishModuleName.$version.nupkg" From bffb6f588ebc5bf32747d8ccb0076c368ad0ab59 Mon Sep 17 00:00:00 2001 From: Amber Erickson Date: Thu, 4 Nov 2021 22:45:28 -0700 Subject: [PATCH 5/6] Incorporate code review suggestions --- src/code/PublishPSResource.cs | 49 ++++++++++------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 753f86dbc..af2b5c690 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -48,7 +48,7 @@ public sealed class PublishPSResource : PSCmdlet /// Specifies the path to the resource that you want to publish. This parameter accepts the path to the folder that contains the resource. /// Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). /// - [Parameter(Mandatory = true, Position = 0, ParameterSetName = "PathParameterSet")] + [Parameter()] [ValidateNotNullOrEmpty] public string Path { @@ -74,37 +74,10 @@ public string Path } } private string _path; - - /// - /// Specifies a path to one or more locations. Unlike the Path parameter, the value of the LiteralPath parameter is used exactly as entered. - /// No characters are interpreted as wildcards. If the path includes escape characters, enclose them in single quotation marks. - /// Single quotation marks tell PowerShell not to interpret any characters as escape sequences. - /// - [Parameter(Mandatory = true, ParameterSetName = "PathLiteralParameterSet")] - [ValidateNotNullOrEmpty] - public string LiteralPath - { - get - { return _literalPath; } - - set - { - if (Directory.Exists(value)) - { - _literalPath = value; - } - else if (File.Exists(value) && value.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase)) - { - _literalPath = value; - } - } - } - private string _literalPath; /// /// Specifies the path to where the resource (as a nupkg) should be saved to. This parameter can be used in conjunction with the /// -Repository parameter to publish to a repository and also save the exact same package to the local file system. - /// Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). /// [Parameter()] [ValidateNotNullOrEmpty] @@ -125,11 +98,19 @@ public string DestinationPath { _destinationPath = resolvedPath; } - // consider throwing error if path does not exist else { - var ex = new ArgumentException("Destination path does not exist."); - var DestinationPathDoesNotExist = new ErrorRecord(ex, "DestinationPathDoesNotExist", ErrorCategory.InvalidArgument, null); - WriteError(DestinationPathDoesNotExist); + // try to create the path + try + { + Directory.CreateDirectory(value); + } + catch (Exception e) + { + var exMessage = string.Format("Destination path does not exist and cannot be created: {0}", e.Message); + var ex = new ArgumentException(exMessage); + var InvalidDestinationPath = new ErrorRecord(ex, "InvalidDestinationPath", ErrorCategory.InvalidArgument, null); + ThrowTerminatingError(InvalidDestinationPath); + } } } } @@ -207,8 +188,6 @@ protected override void ProcessRecord() FileInfo moduleFileInfo; Hashtable parsedMetadataHash = new Hashtable(StringComparer.InvariantCultureIgnoreCase); - // _path has been resolved, literal path does not need to be resolved - _path = string.IsNullOrEmpty(_path) ? _literalPath : _path; // Returns the name of the file or the name of the directory, depending on path var pkgFileOrDir = new DirectoryInfo(_path); bool isScript = _path.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase); @@ -414,7 +393,7 @@ protected override void ProcessRecord() try { var nupkgName = _pkgName + "." + _pkgVersion.ToNormalizedString() + ".nupkg"; - File.Move(System.IO.Path.Combine(outputNupkgDir, nupkgName), System.IO.Path.Combine(_destinationPath, nupkgName)); + Utils.MoveFiles(System.IO.Path.Combine(outputNupkgDir, nupkgName), System.IO.Path.Combine(_destinationPath, nupkgName)); } catch (Exception e) { var message = string.Format("Error moving .nupkg into destination path '{0}' due to: '{1}'.", _destinationPath, e.Message); From de3fba613728bc9cdf5a1fb7b689b25d9ee22f02 Mon Sep 17 00:00:00 2001 From: Amber Erickson Date: Thu, 4 Nov 2021 22:56:18 -0700 Subject: [PATCH 6/6] Remove -LiteralPath test --- test/PublishPSResource.Tests.ps1 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/PublishPSResource.Tests.ps1 b/test/PublishPSResource.Tests.ps1 index 525399c73..2a4feb5b2 100644 --- a/test/PublishPSResource.Tests.ps1 +++ b/test/PublishPSResource.Tests.ps1 @@ -74,16 +74,6 @@ Describe "Test Publish-PSResource" { (Get-ChildItem $script:repositoryPath2).FullName | Should -Be $expectedPath } - It "Publish a module with -LiteralPath" { - $version = "1.0.0" - New-ModuleManifest -Path (Join-Path -Path $script:PublishModuleBase -ChildPath "$script:PublishModuleName.psd1") -ModuleVersion $version -Description "$script:PublishModuleName module" - - Publish-PSResource -LiteralPath $script:PublishModuleBase - - $expectedPath = Join-Path -Path $script:repositoryPath -ChildPath "$script:PublishModuleName.$version.nupkg" - (Get-ChildItem $script:repositoryPath).FullName | Should -Be $expectedPath - } - <# Temporarily comment this test out until Find Helper is complete and code within PublishPSResource is uncommented It "Publish a module with dependencies" { # Create dependency module