diff --git a/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs b/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
index 3c122b484..fd0df6884 100644
--- a/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
+++ b/Dalamud/Plugin/Internal/AutoUpdate/AutoUpdateManager.cs
@@ -119,6 +119,16 @@ internal class AutoUpdateManager : IServiceType
///
public bool IsAutoUpdateComplete { get; private set; }
+ ///
+ /// Gets the time of the next scheduled update check.
+ ///
+ public DateTime? NextUpdateCheckTime => this.nextUpdateCheckTime;
+
+ ///
+ /// Gets the time the auto-update was unblocked.
+ ///
+ public DateTime? UnblockedSince => this.unblockedSince;
+
private static UpdateListingRestriction DecideUpdateListingRestriction(AutoUpdateBehavior behavior)
{
return behavior switch
diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs
index f440ae542..ca9e4a922 100644
--- a/Dalamud/Plugin/Internal/PluginManager.cs
+++ b/Dalamud/Plugin/Internal/PluginManager.cs
@@ -995,20 +995,16 @@ internal class PluginManager : IInternalDisposableService
var totalPlugins = toUpdate.Count;
var processedPlugins = 0;
- // Prevent collection was modified errors
- lock (this.pluginListLock)
+ foreach (var plugin in toUpdate)
{
- foreach (var plugin in toUpdate)
- {
- // Can't update that!
- if (plugin.InstalledPlugin.IsDev)
- continue;
+ // Can't update that!
+ if (plugin.InstalledPlugin.IsDev)
+ continue;
- if (plugin.InstalledPlugin.Manifest.ScheduledForDeletion)
- continue;
+ if (plugin.InstalledPlugin.Manifest.ScheduledForDeletion)
+ continue;
- updateTasks.Add(UpdateSinglePluginWithProgressAsync(plugin));
- }
+ updateTasks.Add(UpdateSinglePluginWithProgressAsync(plugin));
}
var updatedList = await Task.WhenAll(updateTasks);
@@ -1065,6 +1061,18 @@ internal class PluginManager : IInternalDisposableService
Status = PluginUpdateStatus.StatusKind.Success,
HasChangelog = !metadata.UpdateManifest.Changelog.IsNullOrWhitespace(),
};
+
+ // Check if this plugin is already up to date (=> AvailablePluginUpdate was stale)
+ lock (this.installedPluginsList)
+ {
+ var matchedPlugin = this.installedPluginsList.FirstOrDefault(x => x.EffectiveWorkingPluginId == workingPluginId);
+ if (matchedPlugin?.EffectiveVersion == metadata.EffectiveVersion)
+ {
+ Log.Information("Plugin {Name} is already up to date", plugin.Manifest.Name);
+ updateStatus.Status = PluginUpdateStatus.StatusKind.AlreadyUpToDate;
+ return updateStatus;
+ }
+ }
if (!dryRun)
{
@@ -1457,7 +1465,7 @@ internal class PluginManager : IInternalDisposableService
// ignored, since the plugin may be loaded already
}
- Log.Debug($"Extracting to {outputDir}");
+ Log.Debug("Extracting to {OutputDir}", outputDir);
using (var archive = new ZipArchive(zipStream))
{
diff --git a/Dalamud/Plugin/Internal/Types/AvailablePluginUpdate.cs b/Dalamud/Plugin/Internal/Types/AvailablePluginUpdate.cs
index 36823b389..a3673629e 100644
--- a/Dalamud/Plugin/Internal/Types/AvailablePluginUpdate.cs
+++ b/Dalamud/Plugin/Internal/Types/AvailablePluginUpdate.cs
@@ -34,4 +34,10 @@ internal record AvailablePluginUpdate
/// Gets a value indicating whether the update should use the testing URL.
///
public bool UseTesting { get; init; }
+
+ ///
+ /// Gets the effective version to use for the update.
+ ///
+ public Version EffectiveVersion => (this.UseTesting ? this.UpdateManifest.TestingAssemblyVersion : this.UpdateManifest.AssemblyVersion)
+ ?? throw new Exception("Update manifest does not contain a valid version.");
}
diff --git a/Dalamud/Plugin/Internal/Types/PluginUpdateStatus.cs b/Dalamud/Plugin/Internal/Types/PluginUpdateStatus.cs
index 1f20ad960..c14cde62b 100644
--- a/Dalamud/Plugin/Internal/Types/PluginUpdateStatus.cs
+++ b/Dalamud/Plugin/Internal/Types/PluginUpdateStatus.cs
@@ -32,6 +32,11 @@ internal class PluginUpdateStatus
///
FailedLoad,
+ ///
+ /// The updated plugin is already up to date.
+ ///
+ AlreadyUpToDate,
+
///
/// The update succeeded.
///