using System; using System.Collections.Generic; using System.Linq; using isnd.Controllers; using isnd.Data; using isnd.Data.Catalog; using isnd.Entities; using isnd.Interfaces; using isnd.ViewModels; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using NuGet.Versioning; using Unleash; namespace isnd.Services { public class PackageManager : IPackageManager { ApplicationDbContext dbContext; public PackageManager(ApplicationDbContext dbContext, IOptions pmConfigOptions) { this.dbContext = dbContext; CurrentCatalogIndex = GetCatalogIndex(); this.pmConfigOptions = pmConfigOptions.Value; } public PackageIndexViewModel SearchByName(string query, int skip, int take, bool prerelease = false, string packageType = null) { var scope = dbContext.Packages .Include(p => p.Versions) .Where( p => (CamelCaseMatch(p.Id, query) || SeparatedByMinusMatch(p.Id, query)) && (prerelease || p.Versions.Any(v => !v.IsPrerelease)) && (packageType == null || p.Versions.Any(v => v.Type == packageType)) ); var total = scope.Count(); var pkgs = scope.Skip(skip).Take(take).ToArray(); return new PackageIndexViewModel { query = query, totalHits = total, data = pkgs }; } const int maxPageLen = 512; public CatalogIndex GenerateCatalogIndex(string commitId) { var root = "/index.json"; var catalog = new CatalogIndex { CommitId = commitId, CommitTimeStamp = DateTime.Now }; var scope = dbContext.Packages.Where(p => p.Public) .OrderBy(p => p.CommitTimeStamp); catalog.Items = new List(); int pagecount = (int)(scope.Count() / maxPageLen); for (int pagelen = 0, pagenum = 0; pagelen < pagecount; pagenum++) { Page p = new Page { }; } dbContext.Packages.Where(p => p.Public) .OrderBy(p => p.CommitTimeStamp); return catalog; } public Page CatalogPage() { var scope = dbContext.Packages .Where(P => P.Versions.Count > 0) .Select( p => new PackageRef { Id = p.Id, Version = p.Versions.Max().FullString }); return new Page { Items = scope.ToList() }; } public void PublishCatalog() { } public AutoCompleteResult AutoComplete(string id, int skip, int take, bool prerelease = false, string packageType = null) { var scope = dbContext.PackageVersions.Where( v => v.PackageId == id && (prerelease || !v.IsPrerelease) && (packageType == null || v.Type == packageType) ) .OrderBy(v => v.FullString); return new AutoCompleteResult { totalHits = scope.Count(), data = scope.Select(v => v.FullString) .Skip(skip).Take(take).ToArray() }; } // TODO stocker MetaData plutôt que FullString en base, // et en profiter pour corriger ce listing public string[] GetVersions( string id, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25) { return dbContext.PackageVersions.Where( v => v.PackageId == id && (prerelease || !v.IsPrerelease) && (packageType == null || v.Type == packageType) && (parsedVersion.CompareTo(new SemanticVersion(v.Major, v.Minor, v.Patch)) < 0) ) .OrderBy(v => v.FullString) .Select(v => v.FullString) .Skip(skip).Take(take).ToArray(); } public static CatalogIndex CurrentCatalogIndex { get; protected set; } private IsndSettings pmConfigOptions; public virtual CatalogIndex GetCatalogIndex() { if (CurrentCatalogIndex == null) { LoadCatalogFromDb(); } return CurrentCatalogIndex; } void LoadCatalogFromDb() { dbContext.Commits.OrderBy(c => c.TimeStamp); throw new NotImplementedException(); } protected static bool CamelCaseMatch(string id, string query) { // Assert.False (q==null); if (string.IsNullOrEmpty(query)) return true; while (id.Length > 0) { int i = 0; while (id.Length > i && char.IsLower(id[i])) i++; if (i == 0) break; id = id.Substring(i); if (id.StartsWith(query, System.StringComparison.OrdinalIgnoreCase)) return true; } return false; } protected static bool SeparatedByMinusMatch(string id, string q) { foreach (var part in id.Split('-')) { if (part.StartsWith(q, System.StringComparison.OrdinalIgnoreCase)) return true; } return false; } public IEnumerable GetResources(IUnleash unleashClient) { var res = new List(); if (unleashClient.IsEnabled("pkg-push")) res.Add( new Resource { id = "package", type = "PackagePublish/2.0.0", comment = "Package Publish service" }); if (unleashClient.IsEnabled("pkg-get")) res.Add( new Resource { id = "package", type = "PackageBaseAddress/3.0.0", comment = "Package Base Address service" }); if (unleashClient.IsEnabled("pkg-autocomplete")) res.Add( new Resource { id = "package", type = "SearchAutocompleteService/3.5.0", comment = "Auto complete service" }); if (unleashClient.IsEnabled("pkg-search")) res.Add( new Resource { id = "package", type = "SearchQueryService/3.5.0", comment = "Search Query service" }); return res; } } }