Skip to content
Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
36 changes: 33 additions & 3 deletions src/code/LocalServerApiCalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -649,9 +649,10 @@ private Hashtable GetMetadataFromNupkg(string packageName, string packagePath, s
_cmdletPassedIn.WriteDebug($"Extracting '{zipFilePath}' to '{tempDiscoveryPath}'");
System.IO.Compression.ZipFile.ExtractToDirectory(zipFilePath, tempDiscoveryPath);

string psd1FilePath = Path.Combine(tempDiscoveryPath, $"{packageName}.psd1");
string ps1FilePath = Path.Combine(tempDiscoveryPath, $"{packageName}.ps1");
string nuspecFilePath = Path.Combine(tempDiscoveryPath, $"{packageName}.nuspec");
string psd1FilePath = String.Empty;
string ps1FilePath = String.Empty;
string nuspecFilePath = String.Empty;
GetMetadataFilesFromPath(tempDiscoveryPath, packageName, out psd1FilePath, out ps1FilePath, out nuspecFilePath);

List<string> pkgTags = new List<string>();

Expand Down Expand Up @@ -1083,6 +1084,35 @@ private string[] GetCmdsOrDSCTags(string[] tags, bool isSearchingForCommands)
return cmdDSCTags.ToArray();
}

private void GetMetadataFilesFromPath(string dirPath, string packageName, out string psd1FilePath, out string ps1FilePath, out string nuspecFilePath)
{
psd1FilePath = String.Empty;
ps1FilePath = String.Empty;
nuspecFilePath = String.Empty;

var discoveredFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
string pkgNamePattern = $"{packageName}*";
Regex rgx = new(pkgNamePattern, RegexOptions.IgnoreCase);
foreach (var file in discoveredFiles)
{
if (rgx.IsMatch(file))
{
if (file.EndsWith("psd1"))
{
psd1FilePath = file;
}
else if (file.EndsWith("nuspec"))
{
nuspecFilePath = file;
}
else if (file.EndsWith("ps1"))
{
ps1FilePath = file;
}
}
}
}

#endregion
}
}
48 changes: 47 additions & 1 deletion src/code/V2ResponseUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Licensed under the MIT License.

using Microsoft.PowerShell.PSResourceGet.UtilClasses;
using NuGet.Versioning;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace Microsoft.PowerShell.PSResourceGet.Cmdlets
Expand Down Expand Up @@ -70,6 +72,9 @@ public override IEnumerable<PSResourceResult> ConvertToPSResourceResult(FindResu
#region V2 Specific Methods

public XmlNode[] ConvertResponseToXML(string httpResponse) {
NuGetVersion emptyVersion = new NuGetVersion("0.0.0.0");
NuGetVersion firstVersion = emptyVersion;
NuGetVersion lastVersion = emptyVersion;

//Create the XmlDocument.
XmlDocument doc = new XmlDocument();
Expand All @@ -80,7 +85,48 @@ public XmlNode[] ConvertResponseToXML(string httpResponse) {
XmlNode[] nodes = new XmlNode[entryNode.Count];
for (int i = 0; i < entryNode.Count; i++)
{
nodes[i] = entryNode[i];
XmlNode node = entryNode[i];
nodes[i] = node;
var entryChildNodes = node.ChildNodes;
foreach (XmlElement childNode in entryChildNodes)
{
var entryKey = childNode.LocalName;
if (entryKey.Equals("properties"))
{
var propertyChildNodes = childNode.ChildNodes;
foreach (XmlElement propertyChild in propertyChildNodes)
{
var propertyKey = propertyChild.LocalName;
var propertyValue = propertyChild.InnerText;
if (propertyKey.Equals("NormalizedVersion"))
{
if (!NuGetVersion.TryParse(propertyValue, out NuGetVersion parsedNormalizedVersion))
{
parsedNormalizedVersion = emptyVersion;
}

if (i == 0)
{
firstVersion = parsedNormalizedVersion;
}
else
{
// later version element
lastVersion = parsedNormalizedVersion;
}

break; // don't care about rest of the childNode's properties
}
}
}
}
}

// only order the array in desc order if array has more than 1 element and is currently in ascending order
// check for emptyVersion is in case a version that couldn't be parsed was found, just keep ordering as is.
if (nodes.Length > 1 && firstVersion != emptyVersion && lastVersion != emptyVersion && firstVersion < lastVersion)
{
nodes = nodes.Reverse().ToArray();
}

return nodes;
Expand Down
22 changes: 22 additions & 0 deletions src/code/V2ServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,17 @@ public override FindResults FindName(string packageName, bool includePrerelease,
string response = HttpRequestCall(requestUrlV2, out errRecord);
if (errRecord != null)
{
// usually this is for errors in calling the V2 server, but for ADO V2 this error will include package not found errors which we want to deliver in a standard message
if (_isADORepo && errRecord.Exception is ResourceNotFoundException)
{
errRecord = new ErrorRecord(
new ResourceNotFoundException($"Package with name '{packageName}' could not be found in repository '{Repository.Name}'. For ADO feed, if the package is in an upstream feed make sure you are authenticated to the upstream feed.", errRecord.Exception),
"PackageNotFound",
ErrorCategory.ObjectNotFound,
this);
response = string.Empty;
}

return new FindResults(stringResponse: Utils.EmptyStrArray, hashtableResponse: emptyHashResponses, responseType: v2FindResponseType);
}

Expand Down Expand Up @@ -648,6 +659,17 @@ public override FindResults FindVersion(string packageName, string version, Reso
string response = HttpRequestCall(requestUrlV2, out errRecord);
if (errRecord != null)
{
// usually this is for errors in calling the V2 server, but for ADO V2 this error will include package not found errors which we want to deliver with a standard message
if (_isADORepo && errRecord.Exception is ResourceNotFoundException)
{
errRecord = new ErrorRecord(
new ResourceNotFoundException($"Package with name '{packageName}' and version '{version}' could not be found in repository '{Repository.Name}'. For ADO feed, if the package is in an upstream feed make sure you are authenticated to the upstream feed.", errRecord.Exception),
"PackageNotFound",
ErrorCategory.ObjectNotFound,
this);
response = string.Empty;
}

return new FindResults(stringResponse: Utils.EmptyStrArray, hashtableResponse: emptyHashResponses, responseType: v2FindResponseType);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Describe 'Test HTTP Find-PSResource for ADO V2 Server Protocol' -tags 'CI' {
$res = Find-PSResource -Name NonExistantModule -Repository $ADOV2RepoName -ErrorVariable err -ErrorAction SilentlyContinue
$res | Should -BeNullOrEmpty
$err.Count | Should -BeGreaterThan 0
$err[0].FullyQualifiedErrorId | Should -BeExactly "ResourceNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
$err[0].FullyQualifiedErrorId | Should -BeExactly "PackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
$res | Should -BeNullOrEmpty
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,14 @@ Describe 'Test Install-PSResource for V3Server scenarios' -tags 'CI' {
$pkg.Version | Should -Be "5.0.0"
}

It "Install resource with companyname and repository source location and validate properties" {
It "Install resource with author and repository source location and validate properties" {
# CompanyName is not present in ADO V2 feed response properties.
Install-PSResource -Name $testModuleName -Version "5.2.5-alpha001" -Repository $ADORepoName -TrustRepository
$pkg = Get-InstalledPSResource $testModuleName
$pkg.Version | Should -Be "5.2.5"
$pkg.Prerelease | Should -Be "alpha001"

$pkg.CompanyName | Should -Be "None"
$pkg.Author | Should -Be "None"
$pkg.RepositorySourceLocation | Should -Be $ADORepoUri
}

Expand Down
11 changes: 7 additions & 4 deletions test/InstallPSResourceTests/InstallPSResourceLocal.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ Describe 'Test Install-PSResource for local repositories' -tags 'CI' {
BeforeAll {
$localRepo = "psgettestlocal"
$localUNCRepo = "psgettestlocal3"
$localNupkgRepo = "LocalNupkgRepo"
$localNupkgRepoUri = "test\testFiles\testNupkgs"
$localNupkgRepo = "localNupkgRepo"
$testModuleName = "test_local_mod"
$testModuleName2 = "test_local_mod2"
$testModuleClobber = "testModuleClobber"
$testModuleClobber2 = "testModuleClobber2"
Get-NewPSResourceRepositoryFile
Register-LocalRepos
Register-PSResourceRepository -Name $localNupkgRepo -SourceLocation $localNupkgRepoUri
Register-LocalTestNupkgsRepo

$prereleaseLabel = "alpha001"
$tags = @()
Expand Down Expand Up @@ -290,7 +289,11 @@ Describe 'Test Install-PSResource for local repositories' -tags 'CI' {
It "Install .nupkg that contains directories (specific package throws errors when accessed by ZipFile.OpenRead)" {
$nupkgName = "Microsoft.Web.Webview2"
$nupkgVersion = "1.0.2792.45"
Install-PSResource -Name $nupkgName -Version $nupkgVersion -Repository $localNupkgRepo -TrustRepository
$repoPath = Get-PSResourceRepository $localNupkgRepo
Write-Verbose -Verbose "repoPath $($repoPath.Uri)"
$searchPkg = Find-PSResource -Name $nupkgName -Version $nupkgVersion -Repository $localNupkgRepo
Write-Verbose -Verbose "search name: $($searchPkg.Name)"
Install-PSResource -Name $nupkgName -Version $nupkgVersion -Repository $localNupkgRepo -TrustRepository -Verbose
$pkg = Get-InstalledPSResource $nupkgName
$pkg.Name | Should -Be $nupkgName
$pkg.Version | Should -Be $nupkgVersion
Expand Down
20 changes: 20 additions & 0 deletions test/PSGetTestUtils.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,26 @@ function Register-LocalRepos {
Write-Verbose "registered psgettestlocal, psgettestlocal2, psgettestlocal3, psgettestlocal4"
}

function Register-LocalTestNupkgsRepo {
# Path to folder, within our test folder, where we store special case modules, scripts and nupkgs used for testing
$testDir = (get-item $psscriptroot).FullName
$testFilesFolderPath = Join-Path $testDir -ChildPath "testFiles"

# Path to specifically to that invalid test nupkgs folder
$testNupkgsFolderPath = Join-Path $testFilesFolderPath -ChildPath "testNupkgs"
Write-Verbose -Verbose "testNupkgsFolderPath: $testNupkgsFolderPath"

$repoUriAddress = $testNupkgsFolderPath
$localRepoParams = @{
Name = "localNupkgRepo"
Uri = $repoUriAddress
Priority = 70
Trusted = $false
}

Register-PSResourceRepository @localRepoParams
}

function Register-PSGallery {
$PSGalleryRepoParams = @{
Name = $script:PSGalleryName
Expand Down
Loading