Skip to content
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

Add support for packageType query parameter #73

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
5 changes: 4 additions & 1 deletion src/ProjectFileTools.NuGetSearch/Contracts/IPackageInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ProjectFileTools.NuGetSearch.Feeds;
using System.Collections.Generic;
using ProjectFileTools.NuGetSearch.Feeds;

namespace ProjectFileTools.NuGetSearch.Contracts
{
Expand All @@ -24,6 +25,8 @@ public interface IPackageInfo

string Tags { get; }

IReadOnlyList<PackageType> PackageTypes { get; }

FeedKind SourceKind { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
namespace ProjectFileTools.NuGetSearch.Contracts
namespace ProjectFileTools.NuGetSearch.Contracts
{
public interface IPackageQueryConfiguration
{
string CompatibiltyTarget { get; }
string CompatibilityTarget { get; }

bool IncludePreRelease { get; }

int MaxResults { get; }

PackageType PackageType { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System;
using ProjectFileTools.NuGetSearch.Feeds;

namespace ProjectFileTools.NuGetSearch.Contracts
{

public interface IPackageSearchManager
{
IPackageFeedSearchJob<Tuple<string, FeedKind>> SearchPackageNames(string prefix, string tfm);
IPackageFeedSearchJob<Tuple<string, FeedKind>> SearchPackageNames(string prefix, string tfm, string packageType = null);

IPackageFeedSearchJob<Tuple<string, FeedKind>> SearchPackageVersions(string packageName, string tfm);
IPackageFeedSearchJob<Tuple<string, FeedKind>> SearchPackageVersions(string packageName, string tfm, string packageType = null);

IPackageFeedSearchJob<IPackageInfo> SearchPackageInfo(string packageId, string version, string tfm);
}
Expand Down
46 changes: 46 additions & 0 deletions src/ProjectFileTools.NuGetSearch/Contracts/PackageType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;

namespace ProjectFileTools.NuGetSearch.Contracts
{
public class PackageType : IEquatable<PackageType>
{
public static IReadOnlyList<PackageType> DefaultList { get; } = new[] { KnownPackageType.Dependency };

public PackageType(string id, string version = null)
{
Name = id ?? throw new ArgumentNullException(nameof(id));
Version = version;
}
public string Name { get; }
public string Version { get; }


public override bool Equals(object obj) => Equals(obj as PackageType);

public bool Equals(PackageType other) => other is PackageType
&& string.Equals(Name, other.Name, StringComparison.Ordinal)
&& string.Equals(Version, other.Version, StringComparison.Ordinal);

public override int GetHashCode()
{
int hashCode = -612338121;
hashCode = hashCode * -1521134295 + StringComparer.Ordinal.GetHashCode(Name);
if (Version is not null) {
hashCode = hashCode * -1521134295 + StringComparer.Ordinal.GetHashCode(Version);
}
return hashCode;
}
}

public class KnownPackageType
{
public static PackageType Legacy { get; } = new PackageType("Legacy");
public static PackageType DotnetCliTool { get; } = new PackageType("DotnetCliTool");
public static PackageType Dependency { get; } = new PackageType("Dependency");
public static PackageType DotnetTool { get; } = new PackageType("DotnetTool");
public static PackageType SymbolsPackage { get; } = new PackageType("SymbolsPackage");
public static PackageType DotnetPlatform { get; } = new PackageType("DotnetPlatform");
public static PackageType MSBuildSdk { get; } = new PackageType("MSBuildSdk");
}
}
15 changes: 13 additions & 2 deletions src/ProjectFileTools.NuGetSearch/Feeds/Disk/NuGetPackageMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using ProjectFileTools.NuGetSearch.Contracts;
using System.Linq;

using ProjectFileTools.NuGetSearch.Contracts;
using ProjectFileTools.NuGetSearch.IO;

namespace ProjectFileTools.NuGetSearch.Feeds.Disk
Expand All @@ -17,7 +19,16 @@ public static bool IsMatch(string dir, IPackageInfo info, IPackageQueryConfigura
}
}

return true;
if (queryConfiguration.PackageType != null)
{
//NOTE: can't find any info on how the version is supposed to be handled (or what it's even for), so use an exact match
if (!info.PackageTypes.Any(p => queryConfiguration.PackageType.Equals(p)))
{
return false;
}
}

return true;
}
}
}
22 changes: 20 additions & 2 deletions src/ProjectFileTools.NuGetSearch/Feeds/NuSpecReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Xml.Linq;
using System.Collections.Generic;
using System.Xml.Linq;
using ProjectFileTools.NuGetSearch.Contracts;

namespace ProjectFileTools.NuGetSearch.Feeds
Expand All @@ -23,9 +24,26 @@ internal static IPackageInfo Read(string nuspec, FeedKind kind)
XElement iconUrl = metadata?.Element (XName.Get ("iconUrl", ns.NamespaceName));
XElement tags = metadata?.Element(XName.Get("tags", ns.NamespaceName));

List<PackageType> packageTypes = null;
XElement packageTypesEl = metadata?.Element(XName.Get("packageTypes", ns.NamespaceName));
if (packageTypesEl != null)
{
var nameName = XName.Get("name");
var versionName = XName.Get("version");
packageTypes = new List<PackageType>();
foreach (var packageType in packageTypesEl.Elements(XName.Get("packageType", ns.NamespaceName)))
{
var typeName = packageType.Attribute(nameName).Value;
var typeVersion = packageType.Attribute(versionName)?.Value;
packageTypes.Add (new PackageType(typeName, typeVersion));
}
}

if (id != null)
{
return new PackageInfo(id.Value, version?.Value, title?.Value, authors?.Value, summary?.Value, description?.Value, licenseUrl?.Value, projectUrl?.Value, iconUrl?.Value, tags?.Value, kind);
return new PackageInfo(
id.Value, version?.Value, title?.Value, authors?.Value, summary?.Value, description?.Value,
licenseUrl?.Value, projectUrl?.Value, iconUrl?.Value, tags?.Value, kind, packageTypes);
}

return null;
Expand Down
9 changes: 7 additions & 2 deletions src/ProjectFileTools.NuGetSearch/Feeds/PackageInfo.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using ProjectFileTools.NuGetSearch.Contracts;
using System.Collections.Generic;

using ProjectFileTools.NuGetSearch.Contracts;

namespace ProjectFileTools.NuGetSearch.Feeds
{

public class PackageInfo : IPackageInfo
{
public PackageInfo(string id, string version, string title, string authors, string summary, string description, string licenseUrl, string projectUrl, string iconUrl, string tags, FeedKind sourceKind)
public PackageInfo(string id, string version, string title, string authors, string summary, string description, string licenseUrl, string projectUrl, string iconUrl, string tags, FeedKind sourceKind, IReadOnlyList<PackageType> packageTypes)
{
Id = id;
Version = version;
Expand All @@ -17,6 +19,7 @@ public PackageInfo(string id, string version, string title, string authors, stri
SourceKind = sourceKind;
IconUrl = iconUrl;
Tags = tags;
PackageTypes = packageTypes ?? PackageType.DefaultList;
}

public string Id { get; }
Expand All @@ -40,5 +43,7 @@ public PackageInfo(string id, string version, string title, string authors, stri
public string Tags { get; }

public FeedKind SourceKind { get; }

public IReadOnlyList<PackageType> PackageTypes { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
using ProjectFileTools.NuGetSearch.Contracts;
using ProjectFileTools.NuGetSearch.Contracts;

namespace ProjectFileTools.NuGetSearch.Feeds
{
public class PackageQueryConfiguration : IPackageQueryConfiguration
{
public PackageQueryConfiguration(string targetFrameworkMoniker, bool includePreRelease = true, int maxResults = 100)
public PackageQueryConfiguration(string targetFrameworkMoniker, bool includePreRelease = true, int maxResults = 100, PackageType packageType = null)
{
CompatibiltyTarget = targetFrameworkMoniker;
CompatibilityTarget = targetFrameworkMoniker;
IncludePreRelease = includePreRelease;
MaxResults = maxResults;
PackageType = packageType;
}

public string CompatibiltyTarget { get; }
public string CompatibilityTarget { get; }

public bool IncludePreRelease { get; }

public int MaxResults { get; }

public PackageType PackageType { get; }

public override int GetHashCode()
{
return (CompatibiltyTarget?.GetHashCode() ?? 0) ^ IncludePreRelease.GetHashCode() ^ MaxResults.GetHashCode();
return (CompatibilityTarget?.GetHashCode() ?? 0) ^ IncludePreRelease.GetHashCode() ^ MaxResults.GetHashCode() ^ (PackageType?.GetHashCode() ?? 0);
}

public override bool Equals(object obj)
{
PackageQueryConfiguration cfg = obj as PackageQueryConfiguration;
return cfg != null
&& string.Equals(CompatibiltyTarget, cfg.CompatibiltyTarget, System.StringComparison.Ordinal)
return obj is PackageQueryConfiguration cfg
&& string.Equals(CompatibilityTarget, cfg.CompatibilityTarget, System.StringComparison.Ordinal)
&& IncludePreRelease == cfg.IncludePreRelease
&& MaxResults == cfg.MaxResults;
&& MaxResults == cfg.MaxResults
&& (PackageType?.Equals(cfg.PackageType) ?? false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public async Task<IPackageNameSearchResult> GetPackageNamesAsync(string prefix,
}

IReadOnlyList<string> results = new List<string>();
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibiltyTarget) ? $"&targetFramework={queryConfiguration.CompatibiltyTarget}" : "";
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibilityTarget) ? $"&targetFramework={queryConfiguration.CompatibilityTarget}" : "";
var serviceEndpoint = $"{_feed}/Search()";
Func<string, string> queryFunc = x => $"{x}?searchTerm='{prefix}'{frameworkQuery}&includePrerelease={queryConfiguration.IncludePreRelease}&semVerLevel=2.0.0";
XDocument document = await ExecuteAutocompleteServiceQueryAsync(serviceEndpoint, queryFunc, cancellationToken).ConfigureAwait(false);
Expand Down Expand Up @@ -101,7 +101,7 @@ public async Task<IPackageInfo> GetPackageInfoAsync(string packageId, string ver
var licenseUrl = GetPropertyValue(document, el, "LicenseUrl");
var iconUrl = GetPropertyValue(document, el, "IconUrl");
var tags = GetPropertyValue(document, el, "Tags");
var packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind);
var packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind, null);
return packageInfo;
}

Expand Down
15 changes: 8 additions & 7 deletions src/ProjectFileTools.NuGetSearch/Feeds/Web/NuGetV3ServiceFeed.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
Expand Down Expand Up @@ -192,10 +192,11 @@ public async Task<IPackageNameSearchResult> GetPackageNamesAsync(string prefix,
}

IReadOnlyList<string> results = new List<string>();
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibiltyTarget) ? $"&supportedFramework={queryConfiguration.CompatibiltyTarget}" : "";
const string autoCompleteServiceTypeIdentifier = "SearchAutocompleteService";
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibilityTarget) ? $"&supportedFramework={queryConfiguration.CompatibilityTarget}" : "";
string packageTypeQuery = !string.IsNullOrEmpty(queryConfiguration.PackageType?.Name) ? $"&packageType={queryConfiguration.PackageType.Name}" : "";
const string autoCompleteServiceTypeIdentifier = "SearchAutocompleteService/3.5.0";
List<string> serviceEndpoints = await DiscoverEndpointsAsync(_feed, autoCompleteServiceTypeIdentifier, cancellationToken).ConfigureAwait(false);
Func<string, string> queryFunc = x => $"{x}?q={prefix}{frameworkQuery}&take={queryConfiguration.MaxResults}&prerelease={queryConfiguration.IncludePreRelease}";
Func<string, string> queryFunc = x => $"{x}?q={prefix}&semVerLevel=2.0.0{frameworkQuery}{packageTypeQuery}&take={queryConfiguration.MaxResults}&prerelease={queryConfiguration.IncludePreRelease}";
JObject document = await ExecuteAutocompleteServiceQueryAsync(serviceEndpoints, queryFunc, cancellationToken).ConfigureAwait(false);

if (document != null)
Expand Down Expand Up @@ -294,7 +295,7 @@ public async Task<IPackageInfo> GetPackageInfoAsync(string packageId, string ver
licenseUrl = catalogEntry["licenseUrl"]?.ToString();
iconUrl = catalogEntry["iconUrl"]?.ToString();
tags = catalogEntry ["tags"]?.ToString ();
packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind);
packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind, null);
return packageInfo;
}
}
Expand All @@ -311,7 +312,7 @@ public async Task<IPackageInfo> GetPackageInfoAsync(string packageId, string ver
licenseUrl = catalogEntry["licenseUrl"]?.ToString();
iconUrl = catalogEntry["iconUrl"]?.ToString ();
tags = catalogEntry["tags"]?.ToString();
packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind);
packageInfo = new PackageInfo(id, version, title, authors, summary, description, licenseUrl, projectUrl, iconUrl, tags, _kind, null);
bestSemanticVersion = currentVersion;
}
}
Expand All @@ -329,7 +330,7 @@ public async Task<IPackageInfo> GetPackageInfoAsync(string packageId, string ver
public async Task<IPackageVersionSearchResult> GetPackageVersionsAsync(string id, IPackageQueryConfiguration queryConfiguration, CancellationToken cancellationToken)
{
IReadOnlyList<string> results = new List<string>();
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibiltyTarget) ? $"&supportedFramework={queryConfiguration.CompatibiltyTarget}" : "";
string frameworkQuery = !string.IsNullOrEmpty(queryConfiguration.CompatibilityTarget) ? $"&supportedFramework={queryConfiguration.CompatibilityTarget}" : "";
const string autoCompleteServiceTypeIdentifier = "SearchAutocompleteService";
List<string> serviceEndpoints = await DiscoverEndpointsAsync(_feed, autoCompleteServiceTypeIdentifier, cancellationToken).ConfigureAwait(false);
Func<string, string> queryFunc = x => $"{x}?id={id}{frameworkQuery}&take={queryConfiguration.MaxResults}&prerelease={queryConfiguration.IncludePreRelease}";
Expand Down
Loading