File tree Expand file tree Collapse file tree
UniGetUI.PackageEngine.Interfaces
UniGetUI.PackageEngine.Managers.Generic.NuGet
UniGetUI.PackageEngine.Managers.Scoop
UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers
UniGetUI.PackageEngine.Operations
UniGetUI.PackageEngine.PackageManagerClasses/Manager
UniGetUI.PackageEngine.Tests Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -85,6 +85,10 @@ public interface IPackageManager
8585 /// </summary>
8686 public IReadOnlyList < IPackage > GetInstalledPackages ( ) ;
8787
88+ public long InstalledPackagesGeneration { get ; }
89+
90+ public void InvalidateInstalledPackages ( ) ;
91+
8892 /// <summary>
8993 /// Refreshes the Package Manager sources/indexes
9094 /// Each manager MUST implement this method.
Original file line number Diff line number Diff line change @@ -852,7 +852,14 @@ internal static List<Package> ParseUpdatesResponse(
852852 }
853853
854854 protected sealed override IReadOnlyList < Package > GetInstalledPackages_UnSafe ( ) =>
855- TaskRecycler < IReadOnlyList < Package > > . RunOrAttach ( _getInstalledPackages_UnSafe ) ;
855+ TaskRecycler < IReadOnlyList < Package > > . RunOrAttach (
856+ ListInstalledPackagesForGeneration ,
857+ InstalledPackagesGeneration
858+ ) ;
859+
860+ private IReadOnlyList < Package > ListInstalledPackagesForGeneration (
861+ long installedPackagesGeneration
862+ ) => _getInstalledPackages_UnSafe ( ) ;
856863
857864 protected abstract IReadOnlyList < Package > _getInstalledPackages_UnSafe ( ) ;
858865 }
Original file line number Diff line number Diff line change @@ -440,9 +440,13 @@ protected override IReadOnlyList<Package> GetAvailableUpdates_UnSafe()
440440 }
441441
442442 protected override IReadOnlyList < Package > GetInstalledPackages_UnSafe ( ) =>
443- TaskRecycler < IReadOnlyList < Package > > . RunOrAttach ( _getInstalledPackages_UnSafe , 15 ) ;
443+ TaskRecycler < IReadOnlyList < Package > > . RunOrAttach (
444+ _getInstalledPackages_UnSafe ,
445+ InstalledPackagesGeneration ,
446+ 15
447+ ) ;
444448
445- private IReadOnlyList < Package > _getInstalledPackages_UnSafe ( )
449+ private IReadOnlyList < Package > _getInstalledPackages_UnSafe ( long installedPackagesGeneration )
446450 {
447451 using Process p = new ( )
448452 {
Original file line number Diff line number Diff line change @@ -475,21 +475,24 @@ nativePackage.AvailableVersions is { } versions
475475
476476 private IReadOnlyList < CatalogPackage > GetCachedLocalWinGetPackages ( int ? cacheSeconds = null )
477477 {
478- long sourceIndexGeneration = WinGet . SourceIndexGeneration ;
478+ ( long , long ) generations = (
479+ WinGet . SourceIndexGeneration ,
480+ Manager . InstalledPackagesGeneration
481+ ) ;
479482
480483 return cacheSeconds is null
481484 ? TaskRecycler < IReadOnlyList < CatalogPackage > > . RunOrAttach (
482485 EnumerateLocalWinGetPackages ,
483- sourceIndexGeneration
486+ generations
484487 )
485488 : TaskRecycler < IReadOnlyList < CatalogPackage > > . RunOrAttach (
486489 EnumerateLocalWinGetPackages ,
487- sourceIndexGeneration ,
490+ generations ,
488491 cacheSeconds . Value
489492 ) ;
490493 }
491494
492- private IReadOnlyList < CatalogPackage > EnumerateLocalWinGetPackages ( long sourceIndexGeneration )
495+ private IReadOnlyList < CatalogPackage > EnumerateLocalWinGetPackages ( ( long , long ) generations )
493496 {
494497 return _localPackagesProvider is not null
495498 ? _localPackagesProvider ( )
Original file line number Diff line number Diff line change @@ -137,6 +137,7 @@ public PackageOperation(
137137 if ( status is OperationStatus . Canceled )
138138 Package . SetTag ( PackageTag . Default ) ;
139139 } ;
140+ OperationSucceeded += ( _ , _ ) => Package . Manager . InvalidateInstalledPackages ( ) ;
140141 OperationSucceeded += ( _ , _ ) => RecordPendingRebootState ( ) ;
141142 OperationSucceeded += ( _ , _ ) => HandleSuccess ( ) ;
142143 OperationFailed += ( _ , _ ) => HandleFailure ( ) ;
Original file line number Diff line number Diff line change @@ -20,6 +20,10 @@ public class NullPackageManager : IPackageManager
2020
2121 public bool LastInstalledListingFailed => false ;
2222
23+ public long InstalledPackagesGeneration => 0 ;
24+
25+ public void InvalidateInstalledPackages ( ) { }
26+
2327 public static NullPackageManager Instance = new ( ) ;
2428 public ManagerProperties Properties { get ; }
2529 public ManagerCapabilities Capabilities { get ; }
Original file line number Diff line number Diff line change @@ -546,6 +546,13 @@ private IReadOnlyList<IPackage> _getAvailableUpdates(bool SecondAttempt)
546546 /// </summary>
547547 public bool LastInstalledListingFailed { get ; private set ; }
548548
549+ private long _installedPackagesGeneration ;
550+
551+ public long InstalledPackagesGeneration => Volatile . Read ( ref _installedPackagesGeneration ) ;
552+
553+ public void InvalidateInstalledPackages ( ) =>
554+ Interlocked . Increment ( ref _installedPackagesGeneration ) ;
555+
549556 public IReadOnlyList < IPackage > GetInstalledPackages ( )
550557 {
551558 LastInstalledListingFailed = false ;
Original file line number Diff line number Diff line change @@ -544,6 +544,27 @@ private static Func<bool> ReportsWaitingOnTheGate(AbstractOperation operation)
544544 return ( ) => reported ;
545545 }
546546
547+ [ Fact ]
548+ public async Task ASuccessfulOperationInvalidatesTheInstalledPackagesOfItsManager ( )
549+ {
550+ if ( ! OperatingSystem . IsWindows ( ) )
551+ return ;
552+
553+ var manager = CreateSlowProcessManager ( serializesOperations : false ) ;
554+ InitializeLoaders ( ) ;
555+ long generationBefore = manager . InstalledPackagesGeneration ;
556+ using var operation = new UpdatePackageOperation (
557+ new PackageBuilder ( ) . WithManager ( manager ) . WithId ( "updated" ) . Build ( ) ,
558+ new InstallOptions ( ) ,
559+ IgnoreParallelInstalls : true
560+ ) ;
561+
562+ await operation . MainThread ( ) . WaitAsync ( TimeSpan . FromSeconds ( 30 ) ) ;
563+
564+ Assert . Equal ( OperationStatus . Succeeded , operation . Status ) ;
565+ Assert . NotEqual ( generationBefore , manager . InstalledPackagesGeneration ) ;
566+ }
567+
547568 [ Fact ]
548569 public async Task OperationsOfASerializingManagerNeverRunTheirProcessesConcurrently ( )
549570 {
Original file line number Diff line number Diff line change @@ -900,6 +900,31 @@ public void NativeWinGetHelperReusesTheCatalogSnapshotWhileTheSourceIndexIsUncha
900900 Assert . Equal ( 1 , snapshots ) ;
901901 }
902902
903+ [ Fact ]
904+ public void NativeWinGetHelperTakesAFreshSnapshotOnceTheInstalledPackagesAreInvalidated ( )
905+ {
906+ WinGet . MarkSourceIndexRefreshed ( ) ;
907+ var manager = new TestableWinGet ( ) ;
908+ int snapshots = 0 ;
909+ var helper = new NativeWinGetHelper (
910+ manager ,
911+ systemCliHelperFactory : null ,
912+ skipInitialization : true ,
913+ localPackagesProvider : ( ) =>
914+ {
915+ snapshots ++ ;
916+ return [ ] ;
917+ }
918+ ) ;
919+
920+ helper . GetInstalledPackages_UnSafe ( ) ;
921+ manager . InvalidateInstalledPackages ( ) ;
922+ helper . GetInstalledPackages_UnSafe ( ) ;
923+ helper . GetAvailableUpdates_UnSafe ( ) ;
924+
925+ Assert . Equal ( 2 , snapshots ) ;
926+ }
927+
903928 [ Fact ]
904929 public void RefreshPackageIndexesAdvancesTheSourceIndexGenerationWhenTheCliCallFails ( )
905930 {
Original file line number Diff line number Diff line change @@ -665,6 +665,8 @@ private sealed class SearchManager : IPackageManager
665665 public bool IdentifiersAreQuotedOnCommandLine => true ;
666666 public bool LastUpdatesListingFailed => false ;
667667 public bool LastInstalledListingFailed => false ;
668+ public long InstalledPackagesGeneration => 0 ;
669+ public void InvalidateInstalledPackages ( ) { }
668670 public int ? CompareVersions ( string versionA , string versionB ) => throw new NotSupportedException ( ) ;
669671 public void Initialize ( ) => throw new NotSupportedException ( ) ;
670672 public bool IsEnabled ( ) => true ;
You can’t perform that action at this time.
0 commit comments