From 309e72be7035f54d7229f6f9b6930e7fe5c22feb Mon Sep 17 00:00:00 2001 From: HawkForge <75696486+HawkForge@users.noreply.github.com> Date: Sat, 24 Oct 2026 17:45:23 +0600 Subject: [PATCH] Keep Scoop source placeholders valid across source reloads Closes #4835 --- .../Manager/Classes/SourceFactory.cs | 18 +++++++-- .../SourceFactoryTests.cs | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/UniGetUI.PackageEngine.Tests/SourceFactoryTests.cs diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/SourceFactory.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/SourceFactory.cs index 49dda4391f..41a7a04bd8 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/SourceFactory.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/SourceFactory.cs @@ -7,6 +7,7 @@ public class SourceFactory : ISourceFactory { private readonly IPackageManager __manager; private readonly ConcurrentDictionary __reference; + private readonly ConcurrentDictionary __placeholders = []; private readonly Uri __default_uri = new("https://devolutions.net/unigetui"); public SourceFactory(IPackageManager manager) @@ -32,9 +33,11 @@ public IManagerSource GetSourceOrDefault(string name) return source; } - ManagerSource new_source = new(__manager, name, __default_uri); - __reference.TryAdd(name, new_source); - return new_source; + IManagerSource new_source = __placeholders.GetOrAdd( + name, + n => new ManagerSource(__manager, n, __default_uri) + ); + return __reference.GetOrAdd(name, new_source); } /// @@ -60,6 +63,15 @@ public void AddSource(IManagerSource source) existing_source.ReplaceUrl(source.Url); } } + + // Placeholders handed out before a Reset() are still referenced by packages + if (__placeholders.TryRemove(source.Name, out IManagerSource? placeholder)) + { + if (placeholder.Url == __default_uri) + { + placeholder.ReplaceUrl(source.Url); + } + } } public IManagerSource[] GetAvailableSources() diff --git a/src/UniGetUI.PackageEngine.Tests/SourceFactoryTests.cs b/src/UniGetUI.PackageEngine.Tests/SourceFactoryTests.cs new file mode 100644 index 0000000000..c1a14e9791 --- /dev/null +++ b/src/UniGetUI.PackageEngine.Tests/SourceFactoryTests.cs @@ -0,0 +1,37 @@ +using UniGetUI.PackageEngine.Interfaces; +using UniGetUI.PackageEngine.Tests.Infrastructure.Builders; + +namespace UniGetUI.PackageEngine.Tests; + +public sealed class SourceFactoryTests +{ + [Fact] + public void PlaceholderHandedOutBeforeResetReceivesRealUrlFromAddSource() + { + var manager = new PackageManagerBuilder().Build(); + var factory = manager.SourcesHelper.Factory; + IManagerSource placeholder = factory.GetSourceOrDefault("main"); + + factory.Reset(); + var real = new SourceBuilder() + .WithManager(manager) + .WithName("main") + .WithUrl("https://github.com/ScoopInstaller/Main") + .Build(); + factory.AddSource(real); + + Assert.Equal(real.Url, placeholder.Url); + } + + [Fact] + public void PlaceholderRequestedAfterResetIsTheSameInstanceAsBefore() + { + var manager = new PackageManagerBuilder().Build(); + var factory = manager.SourcesHelper.Factory; + IManagerSource before = factory.GetSourceOrDefault("main"); + + factory.Reset(); + + Assert.Same(before, factory.GetSourceOrDefault("main")); + } +}