Skip to content

Implement -DestinationPath parameter for Publish-PSResource #506

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 50 additions & 15 deletions src/code/PublishPSResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 (.).
/// </summary>
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "PathParameterSet")]
[Parameter()]
[ValidateNotNullOrEmpty]
public string Path
{
Expand All @@ -74,32 +74,47 @@ public string Path
}
}
private string _path;

/// <summary>
/// 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.
/// 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.
/// </summary>
[Parameter(Mandatory = true, ParameterSetName = "PathLiteralParameterSet")]
[Parameter()]
[ValidateNotNullOrEmpty]
public string LiteralPath
public string DestinationPath
{
get
{ return _literalPath; }
{ return _destinationPath; }

set
{
if (Directory.Exists(value))
string resolvedPath = string.Empty;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be Ok to set the path to null or empty string as this just means the package is not published to a local file path.
This should be the first check and return immediately. If the path doesn't exist we should either create it (-Force) or throw terminating error.

However, it feels strange to have this option in Publish-PSResource, since it is doing two different things. One is to publish to a repository. The other is to save the package to a file path. At the very lease I feel this should be a separate parameter set, and maybe should be a separate cmdlet (Publish-PSResourceToPath).

if (!string.IsNullOrEmpty(value))
{
_literalPath = value;
resolvedPath = SessionState.Path.GetResolvedPSPathFromPSPath(value).First().Path;
}
else if (File.Exists(value) && value.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))

if (Directory.Exists(resolvedPath))
{
_literalPath = value;
_destinationPath = resolvedPath;
}
else {
// 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);
}
}
}
}
private string _literalPath;
private string _destinationPath;

/// <summary>
/// Specifies a user account that has rights to a specific repository (used for finding dependencies).
Expand Down Expand Up @@ -173,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);
Expand Down Expand Up @@ -374,7 +387,29 @@ protected override void ProcessRecord()
return;
}

// If -DestinationPath is specified then also publish the .nupkg there
if (!string.IsNullOrWhiteSpace(_destinationPath))
{
try
{
var nupkgName = _pkgName + "." + _pkgVersion.ToNormalizedString() + ".nupkg";
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);

var ex = new ArgumentException(message);
var ErrorMovingNupkg = new ErrorRecord(ex, "ErrorMovingNupkg", ErrorCategory.NotSpecified, null);
WriteError(ErrorMovingNupkg);

// exit process record
return;
}
}

// This call does not throw any exceptions, but it will write unsuccessful responses to the console
PushNupkg(outputNupkgDir, repository.Name, repositoryUrl);

}
finally {
WriteVerbose(string.Format("Deleting temporary directory '{0}'", outputDir));
Expand Down
27 changes: 17 additions & 10 deletions test/PublishPSResource.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -271,4 +261,21 @@ 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
}
}