diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index 469b367f80..f8132152b6 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -143,6 +143,8 @@ + + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceView.xaml b/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceView.xaml index 874d4ce1c8..0589b38075 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceView.xaml +++ b/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceView.xaml @@ -48,6 +48,11 @@ x:Name="packageUpdatesView" DataContext="{Binding Path=PackageUpdatesViewModel}"/> + + + \ No newline at end of file diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceViewModel.cs b/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceViewModel.cs index bc3105c862..0cb3dc2053 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceViewModel.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/AddPackageReferenceViewModel.cs @@ -14,6 +14,7 @@ namespace ICSharpCode.PackageManagement InstalledPackagesViewModel installedPackagesViewModel; AvailablePackagesViewModel availablePackagesViewModel; PackageUpdatesViewModel packageUpdatesViewModel; + RecentPackagesViewModel recentPackagesViewModel; public AddPackageReferenceViewModel( IPackageManagementService packageManagementService, @@ -22,13 +23,15 @@ namespace ICSharpCode.PackageManagement this.packageManagementService = packageManagementService; this.packageManagementService.OutputMessagesView.Clear(); - installedPackagesViewModel = new InstalledPackagesViewModel(packageManagementService, taskFactory); availablePackagesViewModel = new AvailablePackagesViewModel(packageManagementService, taskFactory); + installedPackagesViewModel = new InstalledPackagesViewModel(packageManagementService, taskFactory); packageUpdatesViewModel = new PackageUpdatesViewModel(packageManagementService, taskFactory); + recentPackagesViewModel = new RecentPackagesViewModel(packageManagementService, taskFactory); - installedPackagesViewModel.ReadPackages(); availablePackagesViewModel.ReadPackages(); + installedPackagesViewModel.ReadPackages(); packageUpdatesViewModel.ReadPackages(); + recentPackagesViewModel.ReadPackages(); } public InstalledPackagesViewModel InstalledPackagesViewModel { @@ -42,5 +45,9 @@ namespace ICSharpCode.PackageManagement public PackageUpdatesViewModel PackageUpdatesViewModel { get { return packageUpdatesViewModel; } } + + public RecentPackagesViewModel RecentPackagesViewModel { + get { return recentPackagesViewModel; } + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementService.cs index e25532f078..888c2cf1b6 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementService.cs @@ -133,5 +133,11 @@ namespace ICSharpCode.PackageManagement.Design public IPackageManagementOutputMessagesView OutputMessagesView { get { return FakeOutputMessagesView; } } + + public FakePackageRepository FakeRecentPackageRepository = new FakePackageRepository(); + + public IPackageRepository RecentPackageRepository { + get { return FakeRecentPackageRepository; } + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementService.cs index 1afbf89cec..6cae4e685e 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementService.cs @@ -15,6 +15,7 @@ namespace ICSharpCode.PackageManagement IPackageRepository CreateAggregatePackageRepository(); IPackageRepository ActivePackageRepository { get; } IProjectManager ActiveProjectManager { get; } + IPackageRepository RecentPackageRepository { get; } void InstallPackage(IPackageRepository repository, IPackage package, IEnumerable operations); void UninstallPackage(IPackageRepository repository, IPackage package); diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementService.cs index f21873eeb1..e5709a8bf3 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementService.cs @@ -19,6 +19,7 @@ namespace ICSharpCode.PackageManagement IPackageManagementProjectService projectService; IPackageRepository activePackageRepository; PackageSource activePackageSource; + RecentPackageRepository recentPackageRepository; public PackageManagementService( PackageManagementOptions options, @@ -70,16 +71,32 @@ namespace ICSharpCode.PackageManagement } } - public IPackageRepository ActivePackageRepository { - get { return GetActivePackageRepository(); } + public IPackageRepository RecentPackageRepository { + get { + if (recentPackageRepository == null) { + CreateRecentPackageRepository(); + } + return recentPackageRepository; + } } - IPackageRepository GetActivePackageRepository() + void CreateRecentPackageRepository() { - if (activePackageRepository == null) { - activePackageRepository = packageRepositoryCache.CreateRepository(ActivePackageSource); + recentPackageRepository = new RecentPackageRepository(); + } + + public IPackageRepository ActivePackageRepository { + get { + if (activePackageRepository == null) { + CreateActivePackageRepository(); + } + return activePackageRepository; } - return activePackageRepository; + } + + void CreateActivePackageRepository() + { + activePackageRepository = packageRepositoryCache.CreateRepository(ActivePackageSource); } public IProjectManager ActiveProjectManager { @@ -101,6 +118,7 @@ namespace ICSharpCode.PackageManagement ISharpDevelopPackageManager packageManager = CreatePackageManager(packageRepository); packageManager.InstallPackage(package, operations); projectService.RefreshProjectBrowser(); + RecentPackageRepository.AddPackage(package); OnPackageInstalled(); } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackageRepository.cs b/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackageRepository.cs new file mode 100644 index 0000000000..a3de8b175d --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackageRepository.cs @@ -0,0 +1,77 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class RecentPackageRepository : IPackageRepository + { + public const int DefaultMaximumPackagesCount = 20; + + List packages = new List(); + int maximumPackagesCount = DefaultMaximumPackagesCount; + + public RecentPackageRepository() + { + } + + public string Source { + get { return "RecentPackages"; } + } + + public void AddPackage(IPackage package) + { + RemovePackageIfAlreadyAdded(package); + AddPackageAtBeginning(package); + RemoveLastPackageIfCurrentPackageCountExceedsMaximum(); + } + + void RemovePackageIfAlreadyAdded(IPackage package) + { + int index = FindPackage(package); + if (index >= 0) { + packages.RemoveAt(index); + } + } + + int FindPackage(IPackage package) + { + return packages.FindIndex(p => PackageEqualityComparer.IdAndVersion.Equals(package, p)); + } + + void AddPackageAtBeginning(IPackage package) + { + packages.Insert(0, package); + } + + void RemoveLastPackageIfCurrentPackageCountExceedsMaximum() + { + if (packages.Count > maximumPackagesCount) { + RemoveLastPackage(); + } + } + + void RemoveLastPackage() + { + packages.RemoveAt(packages.Count - 1); + } + + public void RemovePackage(IPackage package) + { + } + + public IQueryable GetPackages() + { + return packages.AsQueryable(); + } + + public int MaximumPackagesCount { + get { return maximumPackagesCount; } + set { maximumPackagesCount = value; } + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackagesViewModel.cs b/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackagesViewModel.cs new file mode 100644 index 0000000000..664b5c0e8e --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/RecentPackagesViewModel.cs @@ -0,0 +1,31 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class RecentPackagesViewModel : PackagesViewModel + { + IPackageRepository recentPackageRepository; + + public RecentPackagesViewModel(IPackageManagementService packageManagementService, ITaskFactory taskFactory) + : base(packageManagementService, taskFactory) + { + recentPackageRepository = packageManagementService.RecentPackageRepository; + packageManagementService.PackageInstalled += PackageInstalled; + } + + void PackageInstalled(object sender, EventArgs e) + { + ReadPackages(); + } + + protected override IQueryable GetAllPackages() + { + return recentPackageRepository.GetPackages(); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index 9581602815..496952eecd 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -123,6 +123,8 @@ + + diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/AddPackageReferenceViewModelTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/AddPackageReferenceViewModelTests.cs index 9fffa4ac93..198239b6d0 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/AddPackageReferenceViewModelTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/AddPackageReferenceViewModelTests.cs @@ -98,5 +98,19 @@ namespace PackageManagement.Tests Assert.IsTrue(fakePackageManagementService.FakeOutputMessagesView.IsClearCalled); } + + [Test] + public void RecentPackagesViewModel_RecentRepositoryHasOnePackage_HasOnePackageViewModel() + { + CreatePackageManagementService(); + var package = new FakePackage(); + package.Id = "Test"; + fakePackageManagementService.FakeRecentPackageRepository.FakePackages.Add(package); + CreateViewModel(fakePackageManagementService); + + List expectedPackages = fakePackageManagementService.FakeRecentPackageRepository.FakePackages; + + PackageCollectionAssert.AreEqual(expectedPackages, viewModel.RecentPackagesViewModel.PackageViewModels); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementServiceTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementServiceTests.cs index 3f14eea0ff..bdce072e05 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementServiceTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementServiceTests.cs @@ -468,5 +468,21 @@ namespace PackageManagement.Tests Assert.AreEqual(expectedLogger, actualLogger); } + + [Test] + public void InstallPackage_OnePackageOperation_PackageInstalledAddedToRecentPackagesRepository() + { + CreatePackageManagementService(); + installPackageHelper.AddPackageInstallOperation(); + installPackageHelper.InstallTestPackage(); + + var recentPackages = packageManagementService.RecentPackageRepository.GetPackages(); + + var expectedPackages = new FakePackage[] { + installPackageHelper.TestPackage + }; + + PackageCollectionAssert.AreEqual(expectedPackages, recentPackages); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackageRepositoryTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackageRepositoryTests.cs new file mode 100644 index 0000000000..c1ef68db62 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackageRepositoryTests.cs @@ -0,0 +1,111 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.PackageManagement; +using ICSharpCode.PackageManagement.Design; +using NuGet; +using NUnit.Framework; +using PackageManagement.Tests.Helpers; + +namespace PackageManagement.Tests +{ + [TestFixture] + public class RecentPackageRepositoryTests + { + RecentPackageRepository repository; + + void CreateRepository() + { + repository = new RecentPackageRepository(); + } + + FakePackage AddOnePackageToRepository(string id) + { + var package = new FakePackage(id); + repository.AddPackage(package); + return package; + } + + IEnumerable AddTwoDifferentPackagesToRepository() + { + yield return AddOnePackageToRepository("Test.Package.1"); + yield return AddOnePackageToRepository("Test.Package.2"); + } + + IEnumerable AddFourDifferentPackagesToRepository() + { + yield return AddOnePackageToRepository("Test.Package.1"); + yield return AddOnePackageToRepository("Test.Package.2"); + yield return AddOnePackageToRepository("Test.Package.3"); + yield return AddOnePackageToRepository("Test.Package.4"); + } + + [Test] + public void Source_NewRecentRepositoryCreated_IsRecentPackages() + { + CreateRepository(); + Assert.AreEqual("RecentPackages", repository.Source); + } + + [Test] + public void GetPackages_RepositoryIsEmptyAndOnePackageAdded_ReturnsPackageAdded() + { + CreateRepository(); + var package = AddOnePackageToRepository("Test.Package"); + + var packages = repository.GetPackages(); + + var expectedPackages = new FakePackage[] { + package + }; + + PackageCollectionAssert.AreEqual(expectedPackages, packages); + } + + [Test] + public void GetPackages_RepositoryIsEmptyAndTwoDifferentPackagesAdded_ReturnsPackagesInReverseOrderWithLastAddedFirst() + { + CreateRepository(); + var packagesAdded = AddTwoDifferentPackagesToRepository(); + + var packages = repository.GetPackages(); + + var expectedPackages = packagesAdded.Reverse(); + + PackageCollectionAssert.AreEqual(expectedPackages, packages); + } + + [Test] + public void GetPackages_RepositoryCanHoldThreePackagesAndFourPackagesAdded_ReturnsLastThreePackagesAddedInReverseOrder() + { + CreateRepository(); + repository.MaximumPackagesCount = 3; + var packagesAdded = AddFourDifferentPackagesToRepository(); + + var packages = repository.GetPackages(); + + var expectedPackages = packagesAdded.Reverse().Take(3); + + PackageCollectionAssert.AreEqual(expectedPackages, packages); + } + + [Test] + public void GetPackages_RepositoryIsEmptyAndSamePackageIsAddedTwice_OnePackageReturned() + { + CreateRepository(); + AddOnePackageToRepository("Test"); + var package = AddOnePackageToRepository("Test"); + + var packages = repository.GetPackages(); + + var expectedPackages = new FakePackage[] { + package + }; + + PackageCollectionAssert.AreEqual(expectedPackages, packages); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackagesViewModelTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackagesViewModelTests.cs new file mode 100644 index 0000000000..af4c9df198 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/RecentPackagesViewModelTests.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.PackageManagement; +using ICSharpCode.PackageManagement.Design; +using NUnit.Framework; +using PackageManagement.Tests.Helpers; + +namespace PackageManagement.Tests +{ + [TestFixture] + public class RecentPackagesViewModelTests + { + RecentPackagesViewModel viewModel; + FakePackageManagementService packageManagementService; + FakeTaskFactory taskFactory; + + void CreateViewModel() + { + CreatePackageManagementService(); + CreateViewModel(packageManagementService); + } + + void CreatePackageManagementService() + { + packageManagementService = new FakePackageManagementService(); + } + + void CreateViewModel(FakePackageManagementService packageManagementService) + { + taskFactory = new FakeTaskFactory(); + viewModel = new RecentPackagesViewModel(packageManagementService, taskFactory); + } + + void CompleteReadPackagesTask() + { + taskFactory.ExecuteAllFakeTasks(); + } + + void ClearReadPackagesTasks() + { + taskFactory.ClearAllFakeTasks(); + } + + [Test] + public void PackageViewModels_PackageIsInstalledAfterRecentPackagesDisplayed_PackagesOnDisplayAreUpdated() + { + CreateViewModel(); + viewModel.ReadPackages(); + CompleteReadPackagesTask(); + var package = new FakePackage("Test"); + FakePackageRepository repository = packageManagementService.FakeRecentPackageRepository; + repository.FakePackages.Add(package); + + ClearReadPackagesTasks(); + packageManagementService.FirePackageInstalled(); + CompleteReadPackagesTask(); + + var expectedPackages = new FakePackage[] { + package + }; + + PackageCollectionAssert.AreEqual(expectedPackages, viewModel.PackageViewModels); + } + } +}