Skip to content

Commit

Permalink
Support Is(Absolute)Latest for SemVer2 + semVerLevel for SearchService (
Browse files Browse the repository at this point in the history
  • Loading branch information
xavierdecoster committed May 18, 2017
1 parent 2538748 commit 62723c4
Show file tree
Hide file tree
Showing 40 changed files with 952 additions and 282 deletions.
8 changes: 7 additions & 1 deletion src/NuGet.Services.Search.Client/Client/SearchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,20 @@ public async Task<ServiceResponse<SearchResults>> Search(
bool countOnly = false,
bool explain = false,
bool getAllVersions = false,
string supportedFramework = null)
string supportedFramework = null,
string semVerLevel = null)
{
IDictionary<string, string> nameValue = new Dictionary<string, string>();
nameValue.Add("q", query);
nameValue.Add("skip", skip.ToString());
nameValue.Add("take", take.ToString());
nameValue.Add("sortBy", SortNames[sortBy]);

if (!String.IsNullOrEmpty(semVerLevel))
{
nameValue.Add("semVerLevel", semVerLevel);
}

if (!String.IsNullOrEmpty(supportedFramework))
{
nameValue.Add("supportedFramework", supportedFramework);
Expand Down
3 changes: 3 additions & 0 deletions src/NuGetGallery.Core/Entities/Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ public Package()
public bool IsLatest { get; set; }
public bool IsLatestStable { get; set; }

public bool IsLatestSemVer2 { get; set; }
public bool IsLatestStableSemVer2 { get; set; }

/// <summary>
/// This is when the Package Entity was last touched (so caches can notice changes). In UTC.
/// </summary>
Expand Down
10 changes: 5 additions & 5 deletions src/NuGetGallery.Core/NuGetGallery.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,19 @@
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NuGet.Common, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\NuGet.Common.4.3.0-preview1-2507\lib\net45\NuGet.Common.dll</HintPath>
<HintPath>..\..\packages\NuGet.Common.4.3.0-preview1-2524\lib\net45\NuGet.Common.dll</HintPath>
</Reference>
<Reference Include="NuGet.Frameworks, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\NuGet.Frameworks.4.3.0-preview1-2507\lib\net45\NuGet.Frameworks.dll</HintPath>
<HintPath>..\..\packages\NuGet.Frameworks.4.3.0-preview1-2524\lib\net45\NuGet.Frameworks.dll</HintPath>
</Reference>
<Reference Include="NuGet.Packaging, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\NuGet.Packaging.4.3.0-preview1-2507\lib\net45\NuGet.Packaging.dll</HintPath>
<HintPath>..\..\packages\NuGet.Packaging.4.3.0-preview1-2524\lib\net45\NuGet.Packaging.dll</HintPath>
</Reference>
<Reference Include="NuGet.Packaging.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\NuGet.Packaging.Core.4.3.0-preview1-2507\lib\net45\NuGet.Packaging.Core.dll</HintPath>
<HintPath>..\..\packages\NuGet.Packaging.Core.4.3.0-preview1-2524\lib\net45\NuGet.Packaging.Core.dll</HintPath>
</Reference>
<Reference Include="NuGet.Versioning, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\NuGet.Versioning.4.3.0-preview1-2507\lib\net45\NuGet.Versioning.dll</HintPath>
<HintPath>..\..\packages\NuGet.Versioning.4.3.0-preview1-2524\lib\net45\NuGet.Versioning.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
Expand Down
7 changes: 6 additions & 1 deletion src/NuGetGallery.Core/NuGetVersionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ public static class NuGetVersionExtensions

public static string ToNormalizedStringSafe(this NuGetVersion self)
{
return self != null ? self.ToNormalizedString() : String.Empty;
return self != null ? self.ToNormalizedString() : string.Empty;
}

public static string ToFullStringSafe(this NuGetVersion self)
{
return self != null ? self.ToFullString() : string.Empty;
}

public static bool IsValidVersionForLegacyClients(this NuGetVersion self)
Expand Down
3 changes: 2 additions & 1 deletion src/NuGetGallery.Core/SemVerLevelKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace NuGetGallery
/// </summary>
public static class SemVerLevelKey
{
private static readonly NuGetVersion _semVer2Version = NuGetVersion.Parse("2.0.0");
public static readonly string SemVerLevel2 = "2.0.0";
private static readonly NuGetVersion _semVer2Version = NuGetVersion.Parse(SemVerLevel2);

/// <summary>
/// This could either indicate being SemVer1-compliant, or non-SemVer-compliant at all (e.g. System.Versioning pattern).
Expand Down
10 changes: 5 additions & 5 deletions src/NuGetGallery.Core/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
<package id="Microsoft.Web.Xdt" version="2.1.1" targetFramework="net452" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="3.1.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="NuGet.Common" version="4.3.0-preview1-2507" targetFramework="net452" />
<package id="NuGet.Frameworks" version="4.3.0-preview1-2507" targetFramework="net452" />
<package id="NuGet.Packaging" version="4.3.0-preview1-2507" targetFramework="net452" />
<package id="NuGet.Packaging.Core" version="4.3.0-preview1-2507" targetFramework="net452" />
<package id="NuGet.Versioning" version="4.3.0-preview1-2507" targetFramework="net452" />
<package id="NuGet.Common" version="4.3.0-preview1-2524" targetFramework="net452" />
<package id="NuGet.Frameworks" version="4.3.0-preview1-2524" targetFramework="net452" />
<package id="NuGet.Packaging" version="4.3.0-preview1-2524" targetFramework="net452" />
<package id="NuGet.Packaging.Core" version="4.3.0-preview1-2524" targetFramework="net452" />
<package id="NuGet.Versioning" version="4.3.0-preview1-2524" targetFramework="net452" />
<package id="System.Spatial" version="5.6.5-beta" targetFramework="net452" />
<package id="WindowsAzure.Storage" version="7.0.0" targetFramework="net452" />
</packages>
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public virtual ActionResult Search(string query)
}
else if (splitQueryPart.Length == 2)
{
var resultingPackage = _packageService.FindPackageByIdAndVersion(splitQueryPart[0].Trim(), splitQueryPart[1].Trim(), true);
var resultingPackage = _packageService.FindPackageByIdAndVersionStrict(splitQueryPart[0].Trim(), splitQueryPart[1].Trim());
if (resultingPackage != null)
{
results.Add(CreateDeleteSearchResult(resultingPackage));
Expand Down
15 changes: 10 additions & 5 deletions src/NuGetGallery/Controllers/ApiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,16 @@ public virtual async Task<ActionResult> GetPackage(string id, string version)
}
else
{
// if version is null, get the latest version from the database.
// If version is null, get the latest version from the database.
// This ensures that on package restore scenario where version will be non null, we don't hit the database.
try
{
var package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
var package = PackageService.FindPackageByIdAndVersion(
id,
version,
SemVerLevelKey.SemVer2,
allowPrerelease: false);

if (package == null)
{
return new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version));
Expand Down Expand Up @@ -261,7 +266,7 @@ public async virtual Task<ActionResult> VerifyPackageKeyAsync(string id, string
private async Task<HttpStatusCodeWithBodyResult> VerifyPackageKeyInternalAsync(User user, Credential credential, string id, string version)
{
// Verify that the user has permission to push for the specific Id \ version combination.
var package = PackageService.FindPackageByIdAndVersion(id, version);
var package = PackageService.FindPackageByIdAndVersionStrict(id, version);
if (package == null)
{
return new HttpStatusCodeWithBodyResult(
Expand Down Expand Up @@ -544,7 +549,7 @@ private static ActionResult BadRequestForExceptionMessage(Exception ex)
[ActionName("DeletePackageApi")]
public virtual async Task<ActionResult> DeletePackage(string id, string version)
{
var package = PackageService.FindPackageByIdAndVersion(id, version);
var package = PackageService.FindPackageByIdAndVersionStrict(id, version);
if (package == null)
{
return new HttpStatusCodeWithBodyResult(
Expand Down Expand Up @@ -577,7 +582,7 @@ public virtual async Task<ActionResult> DeletePackage(string id, string version)
[ActionName("PublishPackageApi")]
public virtual async Task<ActionResult> PublishPackage(string id, string version)
{
var package = PackageService.FindPackageByIdAndVersion(id, version);
var package = PackageService.FindPackageByIdAndVersionStrict(id, version);
if (package == null)
{
return new HttpStatusCodeWithBodyResult(
Expand Down
12 changes: 9 additions & 3 deletions src/NuGetGallery/Controllers/CuratedFeedsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,15 @@ public virtual async Task<ActionResult> ListPackages(string curatedFeedName, str
page = 1;
}

q = (q ?? "").Trim();
q = (q ?? string.Empty).Trim();

var searchFilter = SearchAdaptor.GetSearchFilter(
q,
page,
sortOrder: null,
context: SearchFilter.UISearchContext,
semVerLevel: SemVerLevelKey.SemVerLevel2);

var searchFilter = SearchAdaptor.GetSearchFilter(q, page, sortOrder: null, context: SearchFilter.UISearchContext);
searchFilter.CuratedFeed = CuratedFeedService.GetFeedByName(curatedFeedName, includePackages: false);
if (searchFilter.CuratedFeed == null)
{
Expand All @@ -91,7 +97,7 @@ public virtual async Task<ActionResult> ListPackages(string curatedFeedName, str

ViewBag.SearchTerm = q;

return View("ListPackages", viewModel);
return View("ListPackages", viewModel);
}
}
}
17 changes: 15 additions & 2 deletions src/NuGetGallery/Controllers/ODataV1FeedController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,13 @@ private async Task<IHttpActionResult> GetCore(ODataQueryOptions<V1FeedPackage> o
try
{
var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore(
_searchService, GetTraditionalHttpContext().Request, packages, id, version, curatedFeed: null);
_searchService,
GetTraditionalHttpContext().Request,
packages,
id,
version,
curatedFeed: null,
semVerLevel: null);

// If intercepted, create a paged queryresult
if (searchAdaptorResult.ResultsAreProvidedBySearchService)
Expand Down Expand Up @@ -190,7 +196,14 @@ public async Task<IHttpActionResult> Search(

// todo: search hijack should take queryOptions instead of manually parsing query options
var searchAdaptorResult = await SearchAdaptor.SearchCore(
_searchService, GetTraditionalHttpContext().Request, packages, searchTerm, targetFramework, false, curatedFeed: null);
_searchService,
GetTraditionalHttpContext().Request,
packages,
searchTerm,
targetFramework,
false,
curatedFeed: null,
semVerLevel: null);

// Packages provided by search service (even when not hijacked)
var query = searchAdaptorResult.Packages;
Expand Down
58 changes: 49 additions & 9 deletions src/NuGetGallery/Controllers/ODataV2CuratedFeedController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@ public IHttpActionResult Get(
return NotFound();
}

var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel);

var queryable = _curatedFeedService.GetPackages(curatedFeedName)
.Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevel(semVerLevel))
.ToV2FeedPackageQuery(_configurationService.GetSiteRoot(UseHttps()), _configurationService.Features.FriendlyLicenses)
.ToV2FeedPackageQuery(
_configurationService.GetSiteRoot(UseHttps()),
_configurationService.Features.FriendlyLicenses,
semVerLevelKey)
.InterceptWith(new NormalizeVersionInterceptor());

return QueryResult(options, queryable, MaxPageSize);
Expand Down Expand Up @@ -94,8 +99,10 @@ public async Task<IHttpActionResult> FindPackagesById(
{
if (string.IsNullOrEmpty(curatedFeedName) || string.IsNullOrEmpty(id))
{
var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel);

var emptyResult = Enumerable.Empty<Package>().AsQueryable()
.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey);

return QueryResult(options, emptyResult, MaxPageSize);
}
Expand Down Expand Up @@ -126,11 +133,19 @@ private async Task<IHttpActionResult> GetCore(
packages = packages.Where(p => p.Version == version);
}

var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel);

// try the search service
try
{
var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore(
_searchService, GetTraditionalHttpContext().Request, packages, id, version, curatedFeed: curatedFeed);
_searchService,
GetTraditionalHttpContext().Request,
packages,
id,
version,
curatedFeed: curatedFeed,
semVerLevel: semVerLevel);

// If intercepted, create a paged queryresult
if (searchAdaptorResult.ResultsAreProvidedBySearchService)
Expand All @@ -148,7 +163,7 @@ private async Task<IHttpActionResult> GetCore(

var pagedQueryable = packages
.Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize)
.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey);

return QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) =>
SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { id }, o, s));
Expand All @@ -166,7 +181,11 @@ private async Task<IHttpActionResult> GetCore(
return NotFound();
}

var queryable = packages.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
var queryable = packages.ToV2FeedPackageQuery(
GetSiteRoot(),
_configurationService.Features.FriendlyLicenses,
semVerLevelKey);

return QueryResult(options, queryable, MaxPageSize);
}

Expand Down Expand Up @@ -225,34 +244,55 @@ public async Task<IHttpActionResult> Search(

// todo: search hijack should take queryOptions instead of manually parsing query options
var searchAdaptorResult = await SearchAdaptor.SearchCore(
_searchService, GetTraditionalHttpContext().Request, packages, searchTerm, targetFramework, includePrerelease, curatedFeed: curatedFeed);
_searchService,
GetTraditionalHttpContext().Request,
packages,
searchTerm,
targetFramework,
includePrerelease,
curatedFeed: curatedFeed,
semVerLevel: semVerLevel);

// Packages provided by search service (even when not hijacked)
var query = searchAdaptorResult.Packages;

var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel);

// If intercepted, create a paged queryresult
if (searchAdaptorResult.ResultsAreProvidedBySearchService)
{
// Add explicit Take() needed to limit search hijack result set size if $top is specified
var totalHits = query.LongCount();
var pagedQueryable = query
.Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize)
.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
.ToV2FeedPackageQuery(
GetSiteRoot(),
_configurationService.Features.FriendlyLicenses,
semVerLevelKey);

return QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) =>
{
// The nuget.exe 2.x list command does not like the next link at the bottom when a $top is passed.
// Strip it of for backward compatibility.
if (o.Top == null || (resultCount.HasValue && o.Top.Value >= resultCount.Value))
{
return SearchAdaptor.GetNextLink(Request.RequestUri, resultCount, new { searchTerm, targetFramework, includePrerelease }, o, s);
return SearchAdaptor.GetNextLink(
Request.RequestUri,
resultCount,
new { searchTerm, targetFramework, includePrerelease },
o,
s);
}
return null;
});
}

// If not, just let OData handle things
var queryable = query.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
var queryable = query.ToV2FeedPackageQuery(
GetSiteRoot(),
_configurationService.Features.FriendlyLicenses,
semVerLevelKey);

return QueryResult(options, queryable, MaxPageSize);
}

Expand Down
Loading

0 comments on commit 62723c4

Please sign in to comment.