|
@@ -93,17 +93,29 @@ namespace Emby.Server.Implementations.Updates
|
|
|
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
- public async Task<IReadOnlyList<PackageInfo>> GetPackages(string manifest, CancellationToken cancellationToken = default)
|
|
|
+ public async Task<IList<PackageInfo>> GetPackages(string manifestName, string manifest, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
|
|
- .GetAsync(manifest, cancellationToken).ConfigureAwait(false);
|
|
|
+ .GetAsync(new Uri(manifest), cancellationToken).ConfigureAwait(false);
|
|
|
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
try
|
|
|
{
|
|
|
- return await _jsonSerializer.DeserializeFromStreamAsync<IReadOnlyList<PackageInfo>>(stream).ConfigureAwait(false);
|
|
|
+ var package = await _jsonSerializer.DeserializeFromStreamAsync<IList<PackageInfo>>(stream).ConfigureAwait(false);
|
|
|
+
|
|
|
+ // Store the repository and repository url with each version, as they may be spread apart.
|
|
|
+ foreach (var entry in package)
|
|
|
+ {
|
|
|
+ foreach (var ver in entry.versions)
|
|
|
+ {
|
|
|
+ ver.repositoryName = manifestName;
|
|
|
+ ver.repositoryUrl = manifest;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return package;
|
|
|
}
|
|
|
catch (SerializationException ex)
|
|
|
{
|
|
@@ -123,17 +135,69 @@ namespace Emby.Server.Implementations.Updates
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private static void MergeSort(IList<VersionInfo> source, IList<VersionInfo> dest)
|
|
|
+ {
|
|
|
+ int sLength = source.Count - 1;
|
|
|
+ int dLength = dest.Count;
|
|
|
+ int s = 0, d = 0;
|
|
|
+ var sourceVersion = source[0].VersionNumber;
|
|
|
+ var destVersion = dest[0].VersionNumber;
|
|
|
+
|
|
|
+ while (d < dLength)
|
|
|
+ {
|
|
|
+ if (sourceVersion.CompareTo(destVersion) >= 0)
|
|
|
+ {
|
|
|
+ if (s < sLength)
|
|
|
+ {
|
|
|
+ sourceVersion = source[++s].VersionNumber;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Append all of destination to the end of source.
|
|
|
+ while (d < dLength)
|
|
|
+ {
|
|
|
+ source.Add(dest[d++]);
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ source.Insert(s++, dest[d++]);
|
|
|
+ if (d >= dLength)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ sLength++;
|
|
|
+ destVersion = dest[d].VersionNumber;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <inheritdoc />
|
|
|
public async Task<IReadOnlyList<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
var result = new List<PackageInfo>();
|
|
|
foreach (RepositoryInfo repository in _config.Configuration.PluginRepositories)
|
|
|
{
|
|
|
- foreach (var package in await GetPackages(repository.Url, cancellationToken).ConfigureAwait(true))
|
|
|
+ if (repository.Enabled)
|
|
|
{
|
|
|
- package.repositoryName = repository.Name;
|
|
|
- package.repositoryUrl = repository.Url;
|
|
|
- result.Add(package);
|
|
|
+ // Where repositories have the same content, the details of the first is taken.
|
|
|
+ foreach (var package in await GetPackages(repository.Name, repository.Url, cancellationToken).ConfigureAwait(true))
|
|
|
+ {
|
|
|
+ var existing = FilterPackages(result, package.name, Guid.Parse(package.guid)).FirstOrDefault();
|
|
|
+ if (existing != null)
|
|
|
+ {
|
|
|
+ // Assumption is both lists are ordered, so slot these into the correct place.
|
|
|
+ MergeSort(existing.versions, package.versions);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ result.Add(package);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -144,7 +208,8 @@ namespace Emby.Server.Implementations.Updates
|
|
|
public IEnumerable<PackageInfo> FilterPackages(
|
|
|
IEnumerable<PackageInfo> availablePackages,
|
|
|
string name = null,
|
|
|
- Guid guid = default)
|
|
|
+ Guid guid = default,
|
|
|
+ Version specificVersion = null)
|
|
|
{
|
|
|
if (name != null)
|
|
|
{
|
|
@@ -156,6 +221,11 @@ namespace Emby.Server.Implementations.Updates
|
|
|
availablePackages = availablePackages.Where(x => Guid.Parse(x.guid) == guid);
|
|
|
}
|
|
|
|
|
|
+ if (specificVersion != null)
|
|
|
+ {
|
|
|
+ availablePackages = availablePackages.Where(x => x.versions.Where(y => y.VersionNumber.Equals(specificVersion)).Any());
|
|
|
+ }
|
|
|
+
|
|
|
return availablePackages;
|
|
|
}
|
|
|
|
|
@@ -167,7 +237,7 @@ namespace Emby.Server.Implementations.Updates
|
|
|
Version minVersion = null,
|
|
|
Version specificVersion = null)
|
|
|
{
|
|
|
- var package = FilterPackages(availablePackages, name, guid).FirstOrDefault();
|
|
|
+ var package = FilterPackages(availablePackages, name, guid, specificVersion).FirstOrDefault();
|
|
|
|
|
|
// Package not found in repository
|
|
|
if (package == null)
|
|
@@ -181,21 +251,21 @@ namespace Emby.Server.Implementations.Updates
|
|
|
|
|
|
if (specificVersion != null)
|
|
|
{
|
|
|
- availableVersions = availableVersions.Where(x => new Version(x.version) == specificVersion);
|
|
|
+ availableVersions = availableVersions.Where(x => x.VersionNumber.Equals(specificVersion));
|
|
|
}
|
|
|
else if (minVersion != null)
|
|
|
{
|
|
|
- availableVersions = availableVersions.Where(x => new Version(x.version) >= minVersion);
|
|
|
+ availableVersions = availableVersions.Where(x => x.VersionNumber >= minVersion);
|
|
|
}
|
|
|
|
|
|
- foreach (var v in availableVersions.OrderByDescending(x => x.version))
|
|
|
+ foreach (var v in availableVersions.OrderByDescending(x => x.VersionNumber))
|
|
|
{
|
|
|
yield return new InstallationInfo
|
|
|
{
|
|
|
Changelog = v.changelog,
|
|
|
Guid = new Guid(package.guid),
|
|
|
Name = package.name,
|
|
|
- Version = new Version(v.version),
|
|
|
+ Version = v.VersionNumber,
|
|
|
SourceUrl = v.sourceUrl,
|
|
|
Checksum = v.checksum
|
|
|
};
|
|
@@ -322,7 +392,7 @@ namespace Emby.Server.Implementations.Updates
|
|
|
|
|
|
private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var extension = Path.GetExtension(package.SourceUrl);
|
|
|
+ var extension = Path.GetExtension(package.SourceUrl.ToString());
|
|
|
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
_logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl);
|