Initialial upload
This commit is contained in:
parent
742966573d
commit
18855a7884
|
@ -56,5 +56,10 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
/// Gets or sets the Version number of the plugin.
|
/// Gets or sets the Version number of the plugin.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Repository where the plugin originated.
|
||||||
|
/// </summary>
|
||||||
|
public string Repository { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,17 +93,29 @@ namespace Emby.Server.Implementations.Updates
|
||||||
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
public IEnumerable<InstallationInfo> CompletedInstallations => _completedInstallationsInternal;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <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
|
try
|
||||||
{
|
{
|
||||||
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
|
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);
|
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
try
|
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)
|
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 />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken = default)
|
public async Task<IReadOnlyList<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var result = new List<PackageInfo>();
|
var result = new List<PackageInfo>();
|
||||||
foreach (RepositoryInfo repository in _config.Configuration.PluginRepositories)
|
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;
|
// Where repositories have the same content, the details of the first is taken.
|
||||||
package.repositoryUrl = repository.Url;
|
foreach (var package in await GetPackages(repository.Name, repository.Url, cancellationToken).ConfigureAwait(true))
|
||||||
result.Add(package);
|
{
|
||||||
|
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(
|
public IEnumerable<PackageInfo> FilterPackages(
|
||||||
IEnumerable<PackageInfo> availablePackages,
|
IEnumerable<PackageInfo> availablePackages,
|
||||||
string name = null,
|
string name = null,
|
||||||
Guid guid = default)
|
Guid guid = default,
|
||||||
|
Version specificVersion = null)
|
||||||
{
|
{
|
||||||
if (name != null)
|
if (name != null)
|
||||||
{
|
{
|
||||||
|
@ -156,6 +221,11 @@ namespace Emby.Server.Implementations.Updates
|
||||||
availablePackages = availablePackages.Where(x => Guid.Parse(x.guid) == guid);
|
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;
|
return availablePackages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +237,7 @@ namespace Emby.Server.Implementations.Updates
|
||||||
Version minVersion = null,
|
Version minVersion = null,
|
||||||
Version specificVersion = null)
|
Version specificVersion = null)
|
||||||
{
|
{
|
||||||
var package = FilterPackages(availablePackages, name, guid).FirstOrDefault();
|
var package = FilterPackages(availablePackages, name, guid, specificVersion).FirstOrDefault();
|
||||||
|
|
||||||
// Package not found in repository
|
// Package not found in repository
|
||||||
if (package == null)
|
if (package == null)
|
||||||
|
@ -181,21 +251,21 @@ namespace Emby.Server.Implementations.Updates
|
||||||
|
|
||||||
if (specificVersion != null)
|
if (specificVersion != null)
|
||||||
{
|
{
|
||||||
availableVersions = availableVersions.Where(x => new Version(x.version) == specificVersion);
|
availableVersions = availableVersions.Where(x => x.VersionNumber.Equals(specificVersion));
|
||||||
}
|
}
|
||||||
else if (minVersion != null)
|
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
|
yield return new InstallationInfo
|
||||||
{
|
{
|
||||||
Changelog = v.changelog,
|
Changelog = v.changelog,
|
||||||
Guid = new Guid(package.guid),
|
Guid = new Guid(package.guid),
|
||||||
Name = package.name,
|
Name = package.name,
|
||||||
Version = new Version(v.version),
|
Version = v.VersionNumber,
|
||||||
SourceUrl = v.sourceUrl,
|
SourceUrl = v.sourceUrl,
|
||||||
Checksum = v.checksum
|
Checksum = v.checksum
|
||||||
};
|
};
|
||||||
|
@ -322,7 +392,7 @@ namespace Emby.Server.Implementations.Updates
|
||||||
|
|
||||||
private async Task PerformPackageInstallation(InstallationInfo package, CancellationToken cancellationToken)
|
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))
|
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl);
|
_logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl);
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
|
var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
|
||||||
if (!string.IsNullOrEmpty(repositoryUrl))
|
if (!string.IsNullOrEmpty(repositoryUrl))
|
||||||
{
|
{
|
||||||
packages = packages.Where(p => p.repositoryUrl.Equals(repositoryUrl, StringComparison.OrdinalIgnoreCase))
|
packages = packages.Where(p => p.versions.Where(q => q.repositoryUrl.Equals(repositoryUrl, StringComparison.OrdinalIgnoreCase)).Any())
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Model.Updates;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ namespace Jellyfin.Server.Migrations.Routines
|
||||||
private readonly RepositoryInfo _defaultRepositoryInfo = new RepositoryInfo
|
private readonly RepositoryInfo _defaultRepositoryInfo = new RepositoryInfo
|
||||||
{
|
{
|
||||||
Name = "Jellyfin Stable",
|
Name = "Jellyfin Stable",
|
||||||
Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json"
|
Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json",
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -46,4 +46,4 @@ namespace Jellyfin.Server.Migrations.Routines
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,11 @@ namespace MediaBrowser.Common.Updates
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses a plugin manifest at the supplied URL.
|
/// Parses a plugin manifest at the supplied URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="manifestName">Name of the repository.</param>
|
||||||
/// <param name="manifest">The URL to query.</param>
|
/// <param name="manifest">The URL to query.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{IReadOnlyList{PackageInfo}}.</returns>
|
/// <returns>Task{IReadOnlyList{PackageInfo}}.</returns>
|
||||||
Task<IReadOnlyList<PackageInfo>> GetPackages(string manifest, CancellationToken cancellationToken = default);
|
Task<IList<PackageInfo>> GetPackages(string manifestName, string manifest, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all available packages.
|
/// Gets all available packages.
|
||||||
|
@ -37,11 +38,13 @@ namespace MediaBrowser.Common.Updates
|
||||||
/// <param name="availablePackages">The available packages.</param>
|
/// <param name="availablePackages">The available packages.</param>
|
||||||
/// <param name="name">The name of the plugin.</param>
|
/// <param name="name">The name of the plugin.</param>
|
||||||
/// <param name="guid">The id of the plugin.</param>
|
/// <param name="guid">The id of the plugin.</param>
|
||||||
|
/// <param name="specificVersion">The version of the plugin.</param>
|
||||||
/// <returns>All plugins matching the requirements.</returns>
|
/// <returns>All plugins matching the requirements.</returns>
|
||||||
IEnumerable<PackageInfo> FilterPackages(
|
IEnumerable<PackageInfo> FilterPackages(
|
||||||
IEnumerable<PackageInfo> availablePackages,
|
IEnumerable<PackageInfo> availablePackages,
|
||||||
string name = null,
|
string name = null,
|
||||||
Guid guid = default);
|
Guid guid = default,
|
||||||
|
Version specificVersion = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all compatible versions ordered from newest to oldest.
|
/// Returns all compatible versions ordered from newest to oldest.
|
||||||
|
|
|
@ -50,17 +50,7 @@ namespace MediaBrowser.Model.Updates
|
||||||
/// Gets or sets the versions.
|
/// Gets or sets the versions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The versions.</value>
|
/// <value>The versions.</value>
|
||||||
public IReadOnlyList<VersionInfo> versions { get; set; }
|
public IList<VersionInfo> versions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the repository name.
|
|
||||||
/// </summary>
|
|
||||||
public string repositoryName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the repository url.
|
|
||||||
/// </summary>
|
|
||||||
public string repositoryUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="PackageInfo"/> class.
|
/// Initializes a new instance of the <see cref="PackageInfo"/> class.
|
||||||
|
|
|
@ -16,5 +16,11 @@ namespace MediaBrowser.Model.Updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The URL.</value>
|
/// <value>The URL.</value>
|
||||||
public string? Url { get; set; }
|
public string? Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the repository is enabled.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if enabled.</value>
|
||||||
|
public bool Enabled { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,29 @@ namespace MediaBrowser.Model.Updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VersionInfo
|
public class VersionInfo
|
||||||
{
|
{
|
||||||
|
private Version _version;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the version.
|
/// Gets or sets the version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The version.</value>
|
/// <value>The version.</value>
|
||||||
public string version { get; set; }
|
public string version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _version == null ? string.Empty : _version.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_version = Version.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the version as a <see cref="Version"/>.
|
||||||
|
/// </summary>
|
||||||
|
public Version VersionNumber => _version;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the changelog for this version.
|
/// Gets or sets the changelog for this version.
|
||||||
|
@ -44,5 +62,15 @@ namespace MediaBrowser.Model.Updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The timestamp.</value>
|
/// <value>The timestamp.</value>
|
||||||
public string timestamp { get; set; }
|
public string timestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the repository name.
|
||||||
|
/// </summary>
|
||||||
|
public string repositoryName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the repository url.
|
||||||
|
/// </summary>
|
||||||
|
public string repositoryUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user