Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 1.1.0 - Unreleased

- Initial support for proxied search query \#9

### 1.0.1 (2019-Feb-13)

- fix returning metadata of packages with no dependencies \#8
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ Not implemented:
* Does not work with older paket versions
* Cache package metadata and invalidates when upstream changes are detected using [NuGet.CatalogReader](https://github.com/emgarten/NuGet.CatalogReader). *This will be ported from older liget < 1.0.0.*
* V2 search, filter and alike queries. *This is not planned.*
* search and autocomplete endpoints for cached packages. Basically, you need to query nuget.org to *search* for public packages.

# Usage

Expand Down
5 changes: 5 additions & 0 deletions src/LiGet/Cache/CacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,10 @@ public Task<IPackageSearchMetadata> FindAsync(PackageIdentity identity)
//TODO: possibly cache and stream from in-memory cache
return _sourceRepository.GetMetadataAsync(identity, CancellationToken.None);
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
return _sourceRepository.SearchAsync(searchTerm, filter, skip, take, ct);
}
}
}
5 changes: 5 additions & 0 deletions src/LiGet/Cache/FakeCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,10 @@ public Task CacheAsync(
{
return Task.CompletedTask;
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
throw new System.NotImplementedException();
}
}
}
2 changes: 2 additions & 0 deletions src/LiGet/Cache/ICacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ public interface ICacheService
Task<Stream> GetNuspecStreamAsync(PackageIdentity identity);
Task<Stream> GetReadmeStreamAsync(PackageIdentity identity);
Task<IPackageSearchMetadata> FindAsync(PackageIdentity identity);

Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct);
}
}
1 change: 1 addition & 0 deletions src/LiGet/CarterModules/CacheIndexModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ await res.AsJson(new
Version = "3.0.0",
Resources =
ServiceWithAliases("PackagePublish", req.PackagePublish(prefix), "2.0.0") // api.nuget.org returns this too.
.Concat(ServiceWithAliases("SearchQueryService", req.PackageSearch(prefix), "", "3.0.0-beta", "3.0.0-rc")) // each version is an alias of others
.Concat(ServiceWithAliases("RegistrationsBaseUrl", req.RegistrationsBase(prefix), "", "3.0.0-rc", "3.0.0-beta"))
.Concat(ServiceWithAliases("PackageBaseAddress", req.PackageBase(prefix), "3.0.0"))
.ToList()
Expand Down
36 changes: 36 additions & 0 deletions src/LiGet/CarterModules/CacheSearchModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Linq;
using System.Threading;
using Carter;
using Carter.ModelBinding;
using Carter.Request;
using Carter.Response;
using LiGet.Cache;
using LiGet.Configuration;
using LiGet.WebModels;
using NuGet.Protocol.Core.Types;

namespace LiGet.CarterModules
{
public class CacheSearchModule : CarterModule
{
const string prefix = "api/cache";

public CacheSearchModule(ICacheService cacheService) {
this.Get("/api/cache/v3/search", async (req, res, routeData) => {
var query = req.Query.As<string>("q");
int? skip = req.Query.As<int?>("skip");
int? take = req.Query.As<int?>("take");
bool? prerelease = req.Query.As<bool?>("prerelease");
string semVerLevel = req.Query.As<string>("semVerLevel");
query = query ?? string.Empty;

var results = await cacheService.SearchAsync(query, new SearchFilter(prerelease ?? false), skip ?? 0, take ?? 0, CancellationToken.None);
await res.AsJson(new
{
TotalHits = results.Count(),
Data = results.Select(r => new SearchResultModel(r, r.GetVersionsAsync().Result, req, prefix))
});
});
}
}
}
3 changes: 2 additions & 1 deletion src/LiGet/ISourceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public interface ISourceRepository
Task<IEnumerable<IPackageSearchMetadata>> GetMetadataAsync(string packageId, bool includePrerelease, bool includeUnlisted, CancellationToken ct);
Task<IEnumerable<NuGetVersion>> GetAllVersionsAsync(string id, CancellationToken ct);
Task<Uri> GetPackageUriAsync(string id, string version, CancellationToken cancellationToken);
Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, CancellationToken none);
Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, CancellationToken ct);
Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct);
}
}
8 changes: 8 additions & 0 deletions src/LiGet/NuGetClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private class NuRepository : ISourceRepository
private RegistrationResourceV3 _regResource;
private PackageMetadataResourceV3 _metadataSearch;
private RemoteV3FindPackageByIdResource _versionSearch;
private PackageSearchResourceV3 _search;
private NuGetLoggerAdapter<NuGetClient> _loggerAdapter;

public NuRepository(List<Lazy<INuGetResourceProvider>> providers, Uri repositoryUrl, Microsoft.Extensions.Logging.ILogger<NuGetClient> logger)
Expand All @@ -55,6 +56,8 @@ public NuRepository(List<Lazy<INuGetResourceProvider>> providers, Uri repository
ReportAbuseResourceV3 reportAbuseResource = _sourceRepository.GetResource<ReportAbuseResourceV3>();
_metadataSearch = new PackageMetadataResourceV3(httpSource.HttpSource, _regResource, reportAbuseResource);
_versionSearch = new RemoteV3FindPackageByIdResource(_sourceRepository, httpSource.HttpSource);
RawSearchResourceV3 rawSearchResource = _sourceRepository.GetResource<RawSearchResourceV3>();
_search = new PackageSearchResourceV3(rawSearchResource, _metadataSearch);
this._loggerAdapter = new NuGetLoggerAdapter<NuGetClient>(logger);
}

Expand Down Expand Up @@ -100,6 +103,11 @@ public Task<IPackageSearchMetadata> GetMetadataAsync(PackageIdentity identity, C
{
return _metadataSearch.GetMetadataAsync(identity, _cacheContext, _loggerAdapter, ct);
}

public Task<IEnumerable<IPackageSearchMetadata>> SearchAsync(string searchTerm, SearchFilter filter, int skip, int take, CancellationToken ct)
{
return _search.SearchAsync(searchTerm, filter, skip, take, _loggerAdapter, ct);
}
}
}
}
33 changes: 33 additions & 0 deletions src/LiGet/Services/ISearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using LiGet.Entities;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

namespace LiGet.Services
Expand All @@ -17,6 +18,31 @@ public interface ISearchService

public class SearchResult
{
public SearchResult()
{
}

public SearchResult(IPackageSearchMetadata result, IEnumerable<VersionInfo> versions)
{
this.Id = result.Identity.Id;
this.Version = result.Identity.Version;
this.Description = result.Description;
this.Authors = result.Authors;
this.IconUrl = result.IconUrl?.AbsoluteUri;
this.LicenseUrl = result.LicenseUrl?.AbsoluteUri;
this.ProjectUrl = result.ProjectUrl?.AbsoluteUri;
this.Summary = result.Summary;
if(result.Tags != null)
this.Tags = result.Tags.Split(',');
this.Title = result.Title;
this.TotalDownloads = result.DownloadCount ?? 0;
var list = new List<SearchResultVersion>();
foreach(var v in versions) {
list.Add(new SearchResultVersion(v));
}
this.Versions = list;
}

public string Id { get; set; }

public NuGetVersion Version { get; set; }
Expand All @@ -36,6 +62,13 @@ public class SearchResult

public class SearchResultVersion
{

public SearchResultVersion(VersionInfo v)
{
this.Version = v.Version;
this.Downloads = v.DownloadCount ?? 0;
}

public SearchResultVersion(NuGetVersion version, long downloads)
{
Version = version ?? throw new ArgumentNullException(nameof(version));
Expand Down
13 changes: 13 additions & 0 deletions src/LiGet/WebModels/SearchResultModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using LiGet.Services;
using LiGet.Extensions;
using Microsoft.AspNetCore.Http;
using NuGet.Protocol.Core.Types;

namespace LiGet.WebModels
{
Expand All @@ -27,6 +28,18 @@ public SearchResultModel(SearchResult result, HttpRequest url, string prefix)
Versions = versions.ToList().AsReadOnly();
}

public SearchResultModel(IPackageSearchMetadata result, IEnumerable<VersionInfo> versions, HttpRequest url, string prefix)
{
_result = new SearchResult(result, versions);
_url = url ?? throw new ArgumentNullException(nameof(url));
this._prefix = prefix;
Versions = _result.Versions.Select(
v => new SearchResultVersionModel(
url.PackageRegistration(_result.Id, v.Version.ToNormalizedString()),
v.Version.ToNormalizedString(),
v.Downloads)).ToList();
}

public string Id => _result.Id;
public string Version => _result.Version.ToNormalizedString();
public string Description => _result.Description;
Expand Down
15 changes: 14 additions & 1 deletion tests/LiGet.Tests/NuGetClientIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public async Task V2IndexResourceReturnsODataServiceDocument(string indexEndpoin
}

[Theory]
[MemberData(nameof(V3CasesExcludingCache))]
[MemberData(nameof(V3Cases))]
public async Task IndexIncludesAtLeastOneSearchQueryEntry(string indexEndpoint)
{
InitializeClient(indexEndpoint);
Expand Down Expand Up @@ -335,6 +335,19 @@ await packageResource.Push(TestResources.GetNupkgBagetTest1(),
Assert.Equal(new PackageIdentity("liget-test1", NuGetVersion.Parse("1.0.0")), one.Identity);
}

[Fact]
[Trait("Category", "integration")] // because it queries nuget.org
public async Task CacheSearchPackage()
{
InitializeClient(CacheIndex);
var packageResource = await _sourceRepository.GetResourceAsync<PackageUpdateResource>();
PackageSearchResourceV3 search = GetSearch();
var found = await search.SearchAsync("log4net", new SearchFilter(true), 0, 10, logger, CancellationToken.None);
Assert.NotEmpty(found);
var one = found.First();
Assert.Equal("log4net", one.Identity.Id);
}

private PackageSearchResourceV3 GetSearch()
{
PackageMetadataResourceV3 packageMetadataRes = GetPackageMetadataResource();
Expand Down