net6.0
This commit is contained in:
parent
70f6e411e5
commit
4f040be236
18 changed files with 144 additions and 99 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
|
@ -32,7 +32,7 @@
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
"program": "${workspaceFolder}/src/isnd/bin/Debug/netcoreapp2.1/isnd.dll",
|
"program": "${workspaceFolder}/src/isnd/bin/Debug/net6.0/isnd.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}/src/isnd",
|
"cwd": "${workspaceFolder}/src/isnd",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
|
|
|
||||||
3
.vscode/tasks.json
vendored
3
.vscode/tasks.json
vendored
|
|
@ -21,8 +21,7 @@
|
||||||
"build",
|
"build",
|
||||||
"/p:Configuration=Debug",
|
"/p:Configuration=Debug",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary",
|
"/consoleloggerparameters:NoSummary"
|
||||||
"--ignore-failed-sources"
|
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageVersion>1.0.1</PackageVersion>
|
<PackageVersion>1.0.1</PackageVersion>
|
||||||
<Version>1.0.7</Version>
|
<Version>1.0.7</Version>
|
||||||
<TargetFrameworks>net451; net472; net4.8; netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
<NoWarn>NETSDK1138</NoWarn>
|
<NoWarn>NETSDK1138</NoWarn>
|
||||||
<AssemblyVersion>1.0.7.0</AssemblyVersion>
|
<AssemblyVersion>1.0.7.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.7.0</FileVersion>
|
<FileVersion>1.0.7.0</FileVersion>
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
<Reference Include="System.ComponentModel.DataAnnotations" Version="4.0.0.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
<RootNamespace>nuget_cli</RootNamespace>
|
<RootNamespace>nuget_cli</RootNamespace>
|
||||||
<UserSecretsId>45b74c62-05bc-4603-95b4-3e80ae2fdf50</UserSecretsId>
|
<UserSecretsId>45b74c62-05bc-4603-95b4-3e80ae2fdf50</UserSecretsId>
|
||||||
<Version>1.0.7</Version>
|
<Version>1.0.7</Version>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace isnd.Controllers
|
||||||
public class NewUpdateController : Controller
|
public class NewUpdateController : Controller
|
||||||
{
|
{
|
||||||
[Authorize(Policy = IsndConstants.RequireAdminPolicyName)]
|
[Authorize(Policy = IsndConstants.RequireAdminPolicyName)]
|
||||||
public IActionResult NewRelease(NewReleaseInfo version)
|
public IActionResult NewRelease(NewReleaseInfo release)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("web hook");
|
throw new NotImplementedException("web hook");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,14 @@ namespace isnd.Controllers
|
||||||
{
|
{
|
||||||
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
|
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
|
||||||
[HttpGet(_pkgRootPrefix + ApiConfig.Catalog)]
|
[HttpGet(_pkgRootPrefix + ApiConfig.Catalog)]
|
||||||
public IActionResult CatalogIndex()
|
public async Task<IActionResult> CatalogIndex()
|
||||||
{
|
{
|
||||||
return Ok(PackageManager.CurrentCatalogIndex);
|
return Ok(await packageManager.GetCatalogIndexAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogPage + "-{id}")]
|
|
||||||
public IActionResult Index(string id)
|
|
||||||
{
|
|
||||||
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
|
|
||||||
return Ok(PackageManager.CurrentCatalogPages[int.Parse(id)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet(_pkgRootPrefix + "{apiVersion}/" + ApiConfig.Registration + "/{id}/{lower}.json")]
|
[HttpGet(_pkgRootPrefix + "{apiVersion}/" + ApiConfig.Registration + "/{id}/{lower}.json")]
|
||||||
public IActionResult CatalogRegistration(string apiVersion, string id, string lower)
|
public async Task<IActionResult> CatalogRegistration(string apiVersion, string id, string lower)
|
||||||
{
|
{
|
||||||
if (lower.Equals("index", System.StringComparison.InvariantCultureIgnoreCase))
|
if (lower.Equals("index", System.StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
|
|
@ -34,7 +28,7 @@ namespace isnd.Controllers
|
||||||
Query = id,
|
Query = id,
|
||||||
Prerelease = true
|
Prerelease = true
|
||||||
};
|
};
|
||||||
var index = packageManager.GetPackageRegistrationIndex(query);
|
var index = await packageManager.GetPackageRegistrationIndexAsync(query);
|
||||||
if (index == null) return NotFound();
|
if (index == null) return NotFound();
|
||||||
// query.TotalHits = result.Items.Select(i=>i.Items.Length).Aggregate((a,b)=>a+b);
|
// query.TotalHits = result.Items.Select(i=>i.Items.Length).Aggregate((a,b)=>a+b);
|
||||||
return Ok(index);
|
return Ok(index);
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ namespace isnd.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
await dbContext.SaveChangesAsync();
|
await dbContext.SaveChangesAsync();
|
||||||
packageManager.ÛpdateCatalogFor(commit);
|
packageManager.ÛpdateCatalogForAsync(commit);
|
||||||
|
|
||||||
logger.LogInformation($"new paquet : {spec.Name}");
|
logger.LogInformation($"new paquet : {spec.Name}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ namespace isnd.Data.Catalog
|
||||||
NuGetVersion upper = new NuGetVersion(0,0,0);
|
NuGetVersion upper = new NuGetVersion(0,0,0);
|
||||||
|
|
||||||
// Assert.True(items.All(p=>p.Id == id));
|
// Assert.True(items.All(p=>p.Id == id));
|
||||||
|
long commitMax = 0;
|
||||||
foreach (var p in items)
|
foreach (var p in items)
|
||||||
{
|
{
|
||||||
if (upper < p.NugetVersion) upper = p.NugetVersion;
|
if (upper < p.NugetVersion) upper = p.NugetVersion;
|
||||||
|
|
@ -57,8 +57,11 @@ namespace isnd.Data.Catalog
|
||||||
foreach (var p in items)
|
foreach (var p in items)
|
||||||
{
|
{
|
||||||
if (lower > p.NugetVersion) lower = p.NugetVersion;
|
if (lower > p.NugetVersion) lower = p.NugetVersion;
|
||||||
|
if (p.CommitNId>commitMax) commitMax = p.CommitNId;
|
||||||
}
|
}
|
||||||
Lower = lower.ToFullString();
|
Lower = lower.ToFullString();
|
||||||
|
Count = items.Count;
|
||||||
|
CommitId = commitMax.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ namespace isnd.Data.Catalog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value></value>
|
/// <value></value>
|
||||||
[JsonProperty("@id")]
|
[JsonProperty("@id")]
|
||||||
|
[JsonRequired]
|
||||||
public string Id { get; protected set; }
|
public string Id { get; protected set; }
|
||||||
|
|
||||||
public RegistrationPageIndex()
|
public RegistrationPageIndex()
|
||||||
|
|
@ -21,7 +22,9 @@ namespace isnd.Data.Catalog
|
||||||
|
|
||||||
public RegistrationPageIndex(string bid, string id, string dlBase, IEnumerable<Package> pkgs)
|
public RegistrationPageIndex(string bid, string id, string dlBase, IEnumerable<Package> pkgs)
|
||||||
{
|
{
|
||||||
|
|
||||||
Items = new List<RegistrationPage>();
|
Items = new List<RegistrationPage>();
|
||||||
|
long cnid = 0;
|
||||||
var pkgsGroups = pkgs.GroupBy(l => l.Id);
|
var pkgsGroups = pkgs.GroupBy(l => l.Id);
|
||||||
// Pour tous les groupes par Id
|
// Pour tous les groupes par Id
|
||||||
foreach (var gsp in pkgsGroups)
|
foreach (var gsp in pkgsGroups)
|
||||||
|
|
@ -32,13 +35,23 @@ namespace isnd.Data.Catalog
|
||||||
foreach(var l in pkgsbi.Select(p => p.Versions))
|
foreach(var l in pkgsbi.Select(p => p.Versions))
|
||||||
{
|
{
|
||||||
versions.AddRange(l);
|
versions.AddRange(l);
|
||||||
|
foreach (var pv in l)
|
||||||
|
{
|
||||||
|
if (pv.CommitNId> cnid)
|
||||||
|
{
|
||||||
|
cnid = pv.CommitNId;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Items.Add(new RegistrationPage(bid, gsp.Key, dlBase, versions));
|
Items.Add(new RegistrationPage(bid, gsp.Key, dlBase, versions));
|
||||||
}
|
}
|
||||||
|
CommitId = cnid.ToString();
|
||||||
|
Id = bid + $"/{id}/index.json";
|
||||||
|
Count = Items.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("count")]
|
[JsonProperty("count")]
|
||||||
public int Count { get => Items?.Count ?? 0; }
|
public int Count { get ; private set; }
|
||||||
|
|
||||||
[JsonProperty("items")]
|
[JsonProperty("items")]
|
||||||
public List<RegistrationPage> Items { get; set; }
|
public List<RegistrationPage> Items { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@ namespace isnd.Interfaces
|
||||||
|
|
||||||
string[] GetVersions(string pkgid, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25);
|
string[] GetVersions(string pkgid, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25);
|
||||||
IEnumerable<Resource> GetResources(IUnleash unleashĈlient);
|
IEnumerable<Resource> GetResources(IUnleash unleashĈlient);
|
||||||
void ÛpdateCatalogFor(Commit commit);
|
Task<RegistrationPageIndex> ÛpdateCatalogForAsync(Commit commit);
|
||||||
Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type);
|
Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type);
|
||||||
Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type);
|
Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type);
|
||||||
Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type);
|
Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type);
|
||||||
IEnumerable<PackageVersion> GetCatalogLeaf(string pkgId, string version, string pkgType);
|
IEnumerable<PackageVersion> GetCatalogLeaf(string pkgId, string version, string pkgType);
|
||||||
IEnumerable<RegistrationLeaf> SearchById(string pkgId, string semver, string pkgType);
|
IEnumerable<RegistrationLeaf> SearchById(string pkgId, string semver, string pkgType);
|
||||||
|
|
||||||
RegistrationPageIndex GetCatalogIndex();
|
Task<RegistrationPageIndex> GetCatalogIndexAsync();
|
||||||
RegistrationPageIndex GetPackageRegistrationIndex(RegistrationPageIndexQuery query);
|
Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync(RegistrationPageIndexQuery query);
|
||||||
|
|
||||||
Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query);
|
Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ namespace isnd.Services
|
||||||
this.dbContext = dbContext;
|
this.dbContext = dbContext;
|
||||||
isndSettings = siteConfigOptionsOptions.Value;
|
isndSettings = siteConfigOptionsOptions.Value;
|
||||||
extUrl = isndSettings.ExternalUrl + "/";
|
extUrl = isndSettings.ExternalUrl + "/";
|
||||||
CurrentCatalogIndex = GetCatalogIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Resource> GetResources(IUnleash unleashClient)
|
public IEnumerable<Resource> GetResources(IUnleash unleashClient)
|
||||||
|
|
@ -55,9 +54,9 @@ namespace isnd.Services
|
||||||
{
|
{
|
||||||
Id = extUrl + ApiConfig.GetPackage,
|
Id = extUrl + ApiConfig.GetPackage,
|
||||||
Type = "PackageBaseAddress/3.0.0",
|
Type = "PackageBaseAddress/3.0.0",
|
||||||
Comment = "Package Base Address service"
|
Comment = @"Package Base Address service - Base URL of where NuGet packages are stored, in the format https://<host>/nupkg/{id-lower}/{version-lower}/{id-lower}.{version-lower}.nupkg"
|
||||||
});
|
});
|
||||||
if (unleashClient.IsEnabled("pkg-autocomplete", true))
|
if (unleashClient.IsEnabled("pkg-autocomplete", false))
|
||||||
res.Add(
|
res.Add(
|
||||||
new Resource
|
new Resource
|
||||||
{
|
{
|
||||||
|
|
@ -65,7 +64,7 @@ namespace isnd.Services
|
||||||
Type = "SearchAutocompleteService/" + BASE_API_LEVEL,
|
Type = "SearchAutocompleteService/" + BASE_API_LEVEL,
|
||||||
Comment = "Auto complete service"
|
Comment = "Auto complete service"
|
||||||
});
|
});
|
||||||
if (unleashClient.IsEnabled("pkg-search", true))
|
if (unleashClient.IsEnabled("pkg-search", false))
|
||||||
res.Add(
|
res.Add(
|
||||||
new Resource
|
new Resource
|
||||||
{
|
{
|
||||||
|
|
@ -73,7 +72,7 @@ namespace isnd.Services
|
||||||
Type = "SearchQueryService/" + BASE_API_LEVEL,
|
Type = "SearchQueryService/" + BASE_API_LEVEL,
|
||||||
Comment = "Search Query service"
|
Comment = "Search Query service"
|
||||||
});
|
});
|
||||||
if (unleashClient.IsEnabled("pkg-catalog", true))
|
if (unleashClient.IsEnabled("pkg-catalog", false))
|
||||||
res.Add(
|
res.Add(
|
||||||
new Resource
|
new Resource
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +85,7 @@ namespace isnd.Services
|
||||||
res.Add(
|
res.Add(
|
||||||
new Resource
|
new Resource
|
||||||
{
|
{
|
||||||
Id = extUrl + "v" + BASE_API_LEVEL + "/" + ApiConfig.Registration,
|
Id = extUrl + "v3.0.0/" + ApiConfig.Registration,
|
||||||
Type = "RegistrationsBaseUrl",
|
Type = "RegistrationsBaseUrl",
|
||||||
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
|
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
|
||||||
});
|
});
|
||||||
|
|
@ -161,32 +160,27 @@ namespace isnd.Services
|
||||||
.Skip(skip).Take(take).ToArray();
|
.Skip(skip).Take(take).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RegistrationPageIndex CurrentCatalogIndex { get; protected set; }
|
|
||||||
public static List<RegistrationPage> CurrentCatalogPages { get; protected set; }
|
|
||||||
|
|
||||||
public string CatalogBaseUrl => extUrl;
|
public string CatalogBaseUrl => extUrl;
|
||||||
|
|
||||||
private IsndSettings isndSettings;
|
private IsndSettings isndSettings;
|
||||||
private string extUrl;
|
private string extUrl;
|
||||||
|
|
||||||
public virtual RegistrationPageIndex GetCatalogIndex()
|
public virtual async Task<RegistrationPageIndex>GetCatalogIndexAsync()
|
||||||
{
|
{
|
||||||
if (CurrentCatalogIndex == null)
|
return await ÛpdateCatalogForAsync(null);
|
||||||
{
|
|
||||||
ÛpdateCatalogFor();
|
|
||||||
}
|
}
|
||||||
return CurrentCatalogIndex;
|
|
||||||
}
|
public async Task<RegistrationPageIndex> ÛpdateCatalogForAsync(Commit reason = null)
|
||||||
public void ÛpdateCatalogFor(Commit reason = null)
|
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
var oldIndex = CurrentCatalogIndex;
|
|
||||||
var oldPages = CurrentCatalogPages;
|
|
||||||
string baseid = extUrl + ApiConfig.Catalog;
|
string baseid = extUrl + ApiConfig.Catalog;
|
||||||
string bidreg = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
string bidreg = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
||||||
string basepageid = extUrl + ApiConfig.CatalogPage;
|
string basepageid = extUrl + ApiConfig.CatalogPage;
|
||||||
CurrentCatalogIndex = new RegistrationPageIndex();
|
RegistrationPageIndex CurrentCatalogIndex = new RegistrationPageIndex();
|
||||||
CurrentCatalogPages = new List<RegistrationPage>();
|
List<RegistrationPage> CurrentCatalogPages = new List<RegistrationPage>();
|
||||||
|
|
||||||
var scope = dbContext.Commits.OrderBy(c => c.TimeStamp);
|
var scope = dbContext.Commits.OrderBy(c => c.TimeStamp);
|
||||||
|
|
||||||
|
|
@ -214,9 +208,8 @@ namespace isnd.Services
|
||||||
.Include(po => po.Owner)
|
.Include(po => po.Owner)
|
||||||
.Include(pkg => pkg.Versions)
|
.Include(pkg => pkg.Versions)
|
||||||
.Include(pkg => pkg.LatestVersion)
|
.Include(pkg => pkg.LatestVersion)
|
||||||
.Where(
|
.ToList()
|
||||||
pkg => pkg.Versions.Count(v => v.CommitId == commit.CommitId) > 0
|
.GroupBy((q) => q.Id);
|
||||||
).GroupBy((q) => q.Id);
|
|
||||||
// pkg.Versions.OrderByDescending(vi => vi.CommitNId).First().FullString
|
// pkg.Versions.OrderByDescending(vi => vi.CommitNId).First().FullString
|
||||||
foreach (var pkgid in validPkgs)
|
foreach (var pkgid in validPkgs)
|
||||||
{
|
{
|
||||||
|
|
@ -251,6 +244,7 @@ namespace isnd.Services
|
||||||
// From a fresh db
|
// From a fresh db
|
||||||
CurrentCatalogIndex.CommitId = "none";
|
CurrentCatalogIndex.CommitId = "none";
|
||||||
}
|
}
|
||||||
|
return CurrentCatalogIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type)
|
public async Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type)
|
||||||
|
|
@ -273,7 +267,7 @@ namespace isnd.Services
|
||||||
}
|
}
|
||||||
dbContext.PackageVersions.Remove(pkg);
|
dbContext.PackageVersions.Remove(pkg);
|
||||||
await dbContext.SaveChangesAsync();
|
await dbContext.SaveChangesAsync();
|
||||||
ÛpdateCatalogFor(commit);
|
await ÛpdateCatalogForAsync(commit);
|
||||||
return new PackageDeletionReport { Deleted = true, DeletedVersion = pkg };
|
return new PackageDeletionReport { Deleted = true, DeletedVersion = pkg };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,13 +324,11 @@ namespace isnd.Services
|
||||||
&& (pkgType == null || pkgType == v.Type));
|
&& (pkgType == null || pkgType == v.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegistrationPageIndex GetPackageRegistrationIndex(RegistrationPageIndexQuery query)
|
public async Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync(RegistrationPageIndexQuery query)
|
||||||
{
|
{
|
||||||
// RegistrationPageIndexAndQuery
|
// RegistrationPageIndexAndQuery
|
||||||
var scope = dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
|
var scope = (await dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
|
||||||
.Where(p => p.Id.Equals(query.Query, StringComparison.InvariantCultureIgnoreCase)
|
.ToListAsync()) .Where(p => MatchingExact(p, query));
|
||||||
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease))
|
|
||||||
&& p.Versions.Count() > 0);
|
|
||||||
var total = scope.Count();
|
var total = scope.Count();
|
||||||
var pkgs = scope.Skip(query.Skip).Take(query.Take).ToArray();
|
var pkgs = scope.Skip(query.Skip).Take(query.Take).ToArray();
|
||||||
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
||||||
|
|
@ -346,17 +338,30 @@ namespace isnd.Services
|
||||||
public async Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query)
|
public async Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query)
|
||||||
{
|
{
|
||||||
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
|
||||||
// RegistrationPageIndexAndQuery
|
|
||||||
if (query.Query == null) query.Query = "";
|
if (query.Query == null) query.Query = "";
|
||||||
var scope = dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
|
var scope = (await dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
|
||||||
.Where(p => p.Id.StartsWith(query.Query, StringComparison.InvariantCultureIgnoreCase)
|
.ToListAsync())
|
||||||
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease)))
|
.Where(p => Matching(p,query))
|
||||||
.Where(p => p.Versions.Count>0);
|
;
|
||||||
var total = await scope.CountAsync();
|
var total = scope.Count();
|
||||||
var pkgs = await scope.Skip(query.Skip).Take(query.Take).ToArrayAsync();
|
var pkgs = scope.Skip(query.Skip).Take(query.Take);
|
||||||
|
|
||||||
return
|
return
|
||||||
new RegistrationPageIndex(bid, query.Query, extUrl, pkgs);
|
new RegistrationPageIndex(bid, query.Query, extUrl, pkgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool MatchingExact(Package p, RegistrationPageIndexQuery query)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
p.Id.Equals(query.Query, StringComparison.InvariantCultureIgnoreCase)
|
||||||
|
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Matching(Package p, RegistrationPageIndexQuery query)
|
||||||
|
{
|
||||||
|
return p.Id.StartsWith(query.Query, StringComparison.InvariantCultureIgnoreCase)
|
||||||
|
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,12 +20,13 @@ using Microsoft.IdentityModel.Tokens;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace isnd
|
namespace isnd
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public static string ExternalAddress { get; internal set; }
|
|
||||||
|
|
||||||
public Startup(IConfiguration config)
|
public Startup(IConfiguration config)
|
||||||
{
|
{
|
||||||
|
|
@ -57,7 +58,7 @@ namespace isnd
|
||||||
.AddDefaultUI()
|
.AddDefaultUI()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc(o=>o.EnableEndpointRouting = false);
|
||||||
|
|
||||||
services.AddDataProtection();
|
services.AddDataProtection();
|
||||||
|
|
||||||
|
|
@ -90,12 +91,14 @@ namespace isnd
|
||||||
services.AddAuthentication("Bearer")
|
services.AddAuthentication("Bearer")
|
||||||
.AddJwtBearer("Bearer", options =>
|
.AddJwtBearer("Bearer", options =>
|
||||||
{
|
{
|
||||||
options.Authority = ExternalAddress;
|
options.Authority = isndSettingsconf.GetValue<string>("ExternalUrl");
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
ValidateAudience = false
|
ValidateAudience = false
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
services.AddControllersWithViews();
|
||||||
|
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
options.SwaggerDoc("v1", new OpenApiInfo
|
options.SwaggerDoc("v1", new OpenApiInfo
|
||||||
|
|
@ -122,8 +125,9 @@ namespace isnd
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app,
|
public void Configure(IApplicationBuilder app,
|
||||||
Microsoft.AspNetCore.Hosting.IHostingEnvironment env,
|
IWebHostEnvironment env,
|
||||||
ApplicationDbContext dbContext)
|
ApplicationDbContext dbContext,
|
||||||
|
IOptions<IsndSettings> isnSettingsOption )
|
||||||
{
|
{
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|
@ -139,12 +143,9 @@ namespace isnd
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
dbContext.Database.Migrate();
|
dbContext.Database.Migrate();
|
||||||
}
|
}
|
||||||
app.UseStatusCodePages().UseStaticFiles().UseAuthentication().UseMvc(routes =>
|
app.UseStatusCodePages().UseStaticFiles().UseAuthentication();
|
||||||
{
|
app.UseMvcWithDefaultRoute();
|
||||||
routes.MapRoute(
|
|
||||||
name: "default",
|
|
||||||
template: "{controller=Home}/{action=Index}");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<UserSecretsId>85fd766d-5d23-4476-aed1-463b2942e86a</UserSecretsId>
|
<UserSecretsId>85fd766d-5d23-4476-aed1-463b2942e86a</UserSecretsId>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
|
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
|
||||||
|
|
@ -11,34 +11,36 @@
|
||||||
<Version>1.0.7</Version>
|
<Version>1.0.7</Version>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.13" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.6" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.13" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="2.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.13">
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" />
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<PackageReference Include="NuGet.Packaging.Core" Version="5.6.0" />
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.30" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.13" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.13" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.8" IncludeAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.13" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.13" />
|
||||||
|
<PackageReference Include="NuGet.Packaging.Core" Version="6.4.0" />
|
||||||
<PackageReference Include="MailKit" Version="2.8.0" />
|
<PackageReference Include="MailKit" Version="2.8.0" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.2" IncludeAssets="All" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.2" IncludeAssets="All" />
|
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.3" IncludeAssets="All" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2" />
|
|
||||||
<PackageReference Include="unleash.client" Version="1.6.1" />
|
<PackageReference Include="unleash.client" Version="1.6.1" />
|
||||||
<PackageReference Include="GitVersion.MsBuild" Version="5.6.10*">
|
<PackageReference Include="GitVersion.MsBuild" Version="5.6.10*">
|
||||||
<PrivateAssets>All</PrivateAssets>
|
<PrivateAssets>All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.6.0" />
|
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="5.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.2.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
|
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2" />
|
|
||||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.1.0-preview1-final" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="LICENSE" />
|
<None Include="..\..\LICENSE" Pack="true" PackagePath="LICENSE" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<NoWarn>NETSDK1138</NoWarn>
|
<NoWarn>NETSDK1138</NoWarn>
|
||||||
<AssemblyVersion>1.0.7.0</AssemblyVersion>
|
<AssemblyVersion>1.0.7.0</AssemblyVersion>
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\isn\isn.csproj" />
|
<ProjectReference Include="..\..\src\isn\isn.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\isn.abstract\isn.abstract.csproj" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -11,6 +11,10 @@ using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using isnd.tests;
|
using isnd.tests;
|
||||||
|
using NuGet.Protocol;
|
||||||
|
using NuGet.Configuration;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NuGet.Protocol.Core.Types;
|
||||||
|
|
||||||
namespace isnd.host.tests
|
namespace isnd.host.tests
|
||||||
{
|
{
|
||||||
|
|
@ -29,7 +33,6 @@ namespace isnd.host.tests
|
||||||
using (var serviceScope = server.Host.Services.CreateScope())
|
using (var serviceScope = server.Host.Services.CreateScope())
|
||||||
{
|
{
|
||||||
var services = serviceScope.ServiceProvider;
|
var services = serviceScope.ServiceProvider;
|
||||||
var isnSettings = services.GetRequiredService<IOptions<isn.Settings>>().Value;
|
|
||||||
var myDependency = services.GetRequiredService<ApplicationDbContext>();
|
var myDependency = services.GetRequiredService<ApplicationDbContext>();
|
||||||
myDependency.Database.Migrate();
|
myDependency.Database.Migrate();
|
||||||
}
|
}
|
||||||
|
|
@ -42,8 +45,6 @@ namespace isnd.host.tests
|
||||||
using (var serviceScope = server.Host.Services.CreateScope())
|
using (var serviceScope = server.Host.Services.CreateScope())
|
||||||
{
|
{
|
||||||
var services = serviceScope.ServiceProvider;
|
var services = serviceScope.ServiceProvider;
|
||||||
|
|
||||||
var isnSettings = services.GetRequiredService<IOptions<isn.Settings>>().Value;
|
|
||||||
var dbContext = services.GetRequiredService<ApplicationDbContext>();
|
var dbContext = services.GetRequiredService<ApplicationDbContext>();
|
||||||
var paul = dbContext.Users.FirstOrDefaultAsync(u => u.Email == "paul@pschneider.fr").Result;
|
var paul = dbContext.Users.FirstOrDefaultAsync(u => u.Email == "paul@pschneider.fr").Result;
|
||||||
if (paul!=null)
|
if (paul!=null)
|
||||||
|
|
@ -56,18 +57,41 @@ namespace isnd.host.tests
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
||||||
public void NugetInstallsTest()
|
public void NugetInstallsTest()
|
||||||
{
|
{
|
||||||
|
using (var serviceScope = server.Host.Services.CreateScope())
|
||||||
|
{ var isnSettings = serviceScope.ServiceProvider.GetService<IOptions<isnd.Entities.IsndSettings>>().Value;
|
||||||
|
string pkgSourceUrl = isnSettings.ExternalUrl + "/index.json";
|
||||||
ProcessStartInfo psi = new ProcessStartInfo("nuget");
|
ProcessStartInfo psi = new ProcessStartInfo("nuget");
|
||||||
psi.ArgumentList.Add("install");
|
psi.ArgumentList.Add("install");
|
||||||
psi.ArgumentList.Add("gitversion");
|
psi.ArgumentList.Add("gitversion");
|
||||||
psi.ArgumentList.Add("-PreRelease");
|
psi.ArgumentList.Add("-PreRelease");
|
||||||
psi.ArgumentList.Add("-Source");
|
psi.ArgumentList.Add("-Source");
|
||||||
psi.ArgumentList.Add("http://localhost:5000");
|
psi.ArgumentList.Add(pkgSourceUrl);
|
||||||
Process p = Process.Start(psi);
|
Process p = Process.Start(psi);
|
||||||
p.WaitForExit();
|
p.WaitForExit();
|
||||||
Assert.True(p.ExitCode == 0, "nuget install failed!");
|
Assert.True(p.ExitCode == 0, "nuget install failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestRegistrationV3Resource()
|
||||||
|
{
|
||||||
|
using (var serviceScope = server.Host.Services.CreateScope())
|
||||||
|
{ var isnSettings = serviceScope.ServiceProvider.GetService<IOptions<isnd.Entities.IsndSettings>>().Value;
|
||||||
|
string pkgSourceUrl = isnSettings.ExternalUrl + "/index.json";
|
||||||
|
NullThrottle throttle = new NullThrottle();
|
||||||
|
|
||||||
|
PackageSource packageSource = new PackageSource(pkgSourceUrl);
|
||||||
|
HttpSource client = new HttpSource(packageSource, PkgSourceMessageHandler, throttle);
|
||||||
|
NuGet.Protocol.RegistrationResourceV3 res = new NuGet.Protocol.RegistrationResourceV3(client ,
|
||||||
|
new Uri(isnSettings.ExternalUrl + "/v3.4.0//registration"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<HttpHandlerResource> PkgSourceMessageHandler()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
|
|
@ -15,6 +16,8 @@ namespace isnd.tests
|
||||||
public class WebServerFixture : IDisposable
|
public class WebServerFixture : IDisposable
|
||||||
{
|
{
|
||||||
public IWebHost Host { get; private set;}
|
public IWebHost Host { get; private set;}
|
||||||
|
public List<string> Addresses { get; private set; } = new List<string>();
|
||||||
|
|
||||||
public WebServerFixture()
|
public WebServerFixture()
|
||||||
{
|
{
|
||||||
SetupHost();
|
SetupHost();
|
||||||
|
|
@ -31,8 +34,7 @@ namespace isnd.tests
|
||||||
var webhostBuilder = new WebHostBuilder()
|
var webhostBuilder = new WebHostBuilder()
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseContentRoot("../../../../../src/isnd"
|
// .UseContentRoot("../../../../../src/isnd")
|
||||||
)
|
|
||||||
.UseStartup(typeof(Startup))
|
.UseStartup(typeof(Startup))
|
||||||
.ConfigureAppConfiguration((builderContext, config) =>
|
.ConfigureAppConfiguration((builderContext, config) =>
|
||||||
{
|
{
|
||||||
|
|
@ -48,12 +50,14 @@ namespace isnd.tests
|
||||||
|
|
||||||
void PrintAddresses(IServiceProvider services)
|
void PrintAddresses(IServiceProvider services)
|
||||||
{
|
{
|
||||||
|
Addresses.Clear();
|
||||||
Console.WriteLine("Checking addresses...");
|
Console.WriteLine("Checking addresses...");
|
||||||
var server = services.GetRequiredService<IServer>();
|
var server = services.GetRequiredService<IServer>();
|
||||||
var addressFeature = server.Features.Get<IServerAddressesFeature>();
|
var addressFeature = server.Features.Get<IServerAddressesFeature>();
|
||||||
foreach (var address in addressFeature.Addresses)
|
foreach (var address in addressFeature.Addresses)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Listing on address: " + address);
|
Console.WriteLine("Listing on address: " + address);
|
||||||
|
Addresses.Add(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<UserSecretsId>d7144e46-4e63-4391-ba86-64b61f6e7be4</UserSecretsId>
|
<UserSecretsId>d7144e46-4e63-4391-ba86-64b61f6e7be4</UserSecretsId>
|
||||||
<NoWarn>NETSDK1138</NoWarn>
|
<NoWarn>NETSDK1138</NoWarn>
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||||
<PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\isnd\isnd.csproj" />
|
<ProjectReference Include="..\..\src\isnd\isnd.csproj" />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue